3 * Copyright (C) 2002 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
8 * LUFS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * LUFS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/version.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <linux/pagemap.h>
28 #include <linux/socket.h>
30 #include <asm/uaccess.h>
31 #include <asm/system.h>
33 #include <linux/smp_lock.h>
38 extern int lufs_notify_change(struct dentry*, struct iattr*);
39 extern int lu_revalidate_inode(struct dentry*);
41 static int lu_file_open(struct inode *inode, struct file *file)
44 struct server_slot *slot;
50 if((gres = generic_file_open(inode, file)) < 0)
53 TRACE("f_mode: %u, i_mode: %u\n", file->f_mode, inode->i_mode);
54 TRACE("f_flags: %u, i_flags: %u\n", file->f_flags, inode->i_flags);
56 if((slot = lu_getslot(GET_INFO(file->f_dentry->d_sb))) == NULL)
59 if((res = lu_getname(file->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
60 WARN("lu_getname failed!\n");
64 flags = file->f_flags & O_ACCMODE;
65 iov[0].iov_base = &flags;
66 iov[0].iov_len = sizeof(flags);
67 iov[1].iov_base = slot->s_buf;
68 iov[1].iov_len = strlen(slot->s_buf) + 1;
70 lu_execute(GET_INFO(file->f_dentry->d_sb), slot, PTYPE_OPEN, iov, 2, NULL, 0);
79 static int lu_file_release(struct inode *inode, struct file *file)
82 struct server_slot *slot;
87 if((slot = lu_getslot(GET_INFO(file->f_dentry->d_sb))) == NULL)
90 if((res = lu_getname(file->f_dentry, slot->s_buf, LU_MAXPATHLEN)) < 0){
91 WARN("lu_getname failed!\n");
95 iov.iov_base = slot->s_buf;
96 iov.iov_len = strlen(slot->s_buf) + 1;
98 if((res = lu_execute(GET_INFO(file->f_dentry->d_sb), slot, PTYPE_RELEASE, &iov, 1, NULL, 0)) < 0)
102 TRACE("release failed\n");
116 static int lu_file_readpage(struct file *f, struct page *p)
119 struct iovec siov[3], riov;
122 struct server_slot *slot;
126 if((slot = lu_getslot(GET_INFO(f->f_dentry->d_sb))) == NULL)
131 if((res = lu_getname(f->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
132 WARN("lu_getname failed!\n");
136 offset = p->index << PAGE_CACHE_SHIFT;
139 siov[0].iov_base = &offset;
140 siov[0].iov_len = sizeof(offset);
141 siov[1].iov_base = &count;
142 siov[1].iov_len = sizeof(count);
143 siov[2].iov_base = slot->s_buf;
144 siov[2].iov_len = strlen(slot->s_buf) + 1;
146 riov.iov_base = page_address(p);
147 riov.iov_len = count;
149 if((res = lu_execute(GET_INFO(f->f_dentry->d_sb), slot, PTYPE_READ, siov, 3, &riov, 1)) < 0)
153 TRACE("read failed\n");
158 flush_dcache_page(p);
171 static int lu_file_writepage(struct page *p, struct writeback_control *wbc)
179 static int lu_file_preparewrite(struct file *f, struct page *p, unsigned offset, unsigned to)
188 static int lu_file_commitwrite(struct file *f, struct page *p, unsigned offset, unsigned to)
191 struct server_slot *slot;
199 if((slot = lu_getslot(GET_INFO(f->f_dentry->d_sb))) == NULL)
202 if((res = lu_getname(f->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
203 WARN("lu_getname failed!\n");
209 buf = kmap(p) + offset;
211 off = offset + (((long long)p->index) << PAGE_CACHE_SHIFT);
213 iov[0].iov_base = &off;
214 iov[0].iov_len = sizeof(off);
215 iov[1].iov_base = &cnt;
216 iov[1].iov_len = sizeof(cnt);
217 iov[2].iov_base = slot->s_buf;
218 iov[2].iov_len = strlen(slot->s_buf) + 1;
219 iov[3].iov_base = buf;
220 iov[3].iov_len = cnt;
222 TRACE("write %s, offset %Ld, count %d\n", slot->s_buf, off, (int)cnt);
224 if((res = lu_execute(GET_INFO(f->f_dentry->d_sb), slot, PTYPE_WRITE, iov, 4, NULL, 0)) < 0)
229 TRACE("write failed\n");
234 f->f_dentry->d_inode->i_mtime = f->f_dentry->d_inode->i_atime = CURRENT_TIME;
235 if(off + cnt > f->f_dentry->d_inode->i_size)
236 f->f_dentry->d_inode->i_size = off + cnt;
249 static int lu_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
251 struct dentry *dentry = filp->f_dentry;
256 if(!(res = lu_revalidate_inode(dentry)))
257 res = generic_file_read(filp, buf, count, ppos);
264 static int lu_file_mmap(struct file *filp, struct vm_area_struct *vma)
266 struct dentry *dentry = filp->f_dentry;
271 if(!(res = lu_revalidate_inode(dentry)))
272 res = generic_file_mmap(filp, vma);
279 static ssize_t lu_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
281 struct dentry *dentry = filp->f_dentry;
286 if(!(res = lu_revalidate_inode(dentry)) && (count > 0))
287 res = generic_file_write(filp, buf, count, ppos);
294 static int lu_file_fsync(struct file *filp, struct dentry *dentryp, int datasync)
299 struct file_operations lu_file_operations = {
300 .llseek = generic_file_llseek,
301 .read = lu_file_read,
302 .write = lu_file_write,
303 .mmap = lu_file_mmap,
304 .open = lu_file_open,
305 .release = lu_file_release,
306 .fsync = lu_file_fsync,
309 struct inode_operations lu_file_inode_operations = {
310 .setattr = lufs_notify_change,
313 struct address_space_operations lu_file_aops = {
314 .readpage = lu_file_readpage,
315 .writepage = lu_file_writepage,
316 .prepare_write = lu_file_preparewrite,
317 .commit_write = lu_file_commitwrite,