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>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
32 #include <linux/smp_lock.h>
37 extern int lufs_notify_change(struct dentry*, struct iattr*);
38 extern int lu_revalidate_inode(struct dentry*);
40 static int lu_file_open(struct inode *inode, struct file *file)
43 struct server_slot *slot;
49 if((gres = generic_file_open(inode, file)) < 0)
52 TRACE("f_mode: %u, i_mode: %u\n", file->f_mode, inode->i_mode);
53 TRACE("f_flags: %u, i_flags: %u\n", file->f_flags, inode->i_flags);
55 if((slot = lu_getslot(GET_INFO(file->f_dentry->d_sb))) == NULL)
58 if((res = lu_getname(file->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
59 WARN("lu_getname failed!\n");
63 flags = file->f_flags & O_ACCMODE;
64 iov[0].iov_base = &flags;
65 iov[0].iov_len = sizeof(flags);
66 iov[1].iov_base = slot->s_buf;
67 iov[1].iov_len = strlen(slot->s_buf) + 1;
69 lu_execute(GET_INFO(file->f_dentry->d_sb), slot, PTYPE_OPEN, iov, 2, NULL, 0);
78 static int lu_file_release(struct inode *inode, struct file *file)
81 struct server_slot *slot;
86 if((slot = lu_getslot(GET_INFO(file->f_dentry->d_sb))) == NULL)
89 if((res = lu_getname(file->f_dentry, slot->s_buf, LU_MAXPATHLEN)) < 0){
90 WARN("lu_getname failed!\n");
94 iov.iov_base = slot->s_buf;
95 iov.iov_len = strlen(slot->s_buf) + 1;
97 if((res = lu_execute(GET_INFO(file->f_dentry->d_sb), slot, PTYPE_RELEASE, &iov, 1, NULL, 0)) < 0)
101 TRACE("release failed\n");
115 static int lu_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
117 struct dentry *dentry = filp->f_dentry;
122 if(!(res = lu_revalidate_inode(dentry)))
123 res = generic_file_read(filp, buf, count, ppos);
130 static int lu_file_readpage(struct file *f, struct page *p)
133 struct iovec siov[3], riov;
136 struct server_slot *slot;
140 if((slot = lu_getslot(GET_INFO(f->f_dentry->d_sb))) == NULL)
145 if((res = lu_getname(f->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
146 WARN("lu_getname failed!\n");
150 offset = p->index << PAGE_CACHE_SHIFT;
153 siov[0].iov_base = &offset;
154 siov[0].iov_len = sizeof(offset);
155 siov[1].iov_base = &count;
156 siov[1].iov_len = sizeof(count);
157 siov[2].iov_base = slot->s_buf;
158 siov[2].iov_len = strlen(slot->s_buf) + 1;
160 riov.iov_base = page_address(p);
161 riov.iov_len = count;
163 if((res = lu_execute(GET_INFO(f->f_dentry->d_sb), slot, PTYPE_READ, siov, 3, &riov, 1)) < 0)
167 TRACE("read failed\n");
172 flush_dcache_page(p);
185 static int lu_file_writepage(struct page *p)
193 static int lu_file_preparewrite(struct file *f, struct page *p, unsigned offset, unsigned to)
202 static int lu_file_commitwrite(struct file *f, struct page *p, unsigned offset, unsigned to)
205 struct server_slot *slot;
213 if((slot = lu_getslot(GET_INFO(f->f_dentry->d_sb))) == NULL)
216 if((res = lu_getname(f->f_dentry, slot->s_buf, LU_MAXDATA)) < 0){
217 WARN("lu_getname failed!\n");
223 buf = kmap(p) + offset;
225 off = offset + (((long long)p->index) << PAGE_CACHE_SHIFT);
227 iov[0].iov_base = &off;
228 iov[0].iov_len = sizeof(off);
229 iov[1].iov_base = &cnt;
230 iov[1].iov_len = sizeof(cnt);
231 iov[2].iov_base = slot->s_buf;
232 iov[2].iov_len = strlen(slot->s_buf) + 1;
233 iov[3].iov_base = buf;
234 iov[3].iov_len = cnt;
236 TRACE("write %s, offset %Ld, count %d\n", slot->s_buf, off, (int)cnt);
238 if((res = lu_execute(GET_INFO(f->f_dentry->d_sb), slot, PTYPE_WRITE, iov, 4, NULL, 0)) < 0)
243 TRACE("write failed\n");
248 f->f_dentry->d_inode->i_mtime = f->f_dentry->d_inode->i_atime = CURRENT_TIME;
249 if(off + cnt > f->f_dentry->d_inode->i_size)
250 f->f_dentry->d_inode->i_size = off + cnt;
263 static int lu_file_mmap(struct file *filp, struct vm_area_struct *vma)
265 struct dentry *dentry = filp->f_dentry;
270 if(!(res = lu_revalidate_inode(dentry)))
271 res = generic_file_mmap(filp, vma);
278 static ssize_t lu_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
280 struct dentry *dentry = filp->f_dentry;
285 if(!(res = lu_revalidate_inode(dentry)) && (count > 0))
286 res = generic_file_write(filp, buf, count, ppos);
294 * Without this function, fsync() returns EINVAL indicating that the
295 * file is special (eg pipe or socket) and does not support
298 * This causes, for example, Emacs to report "Writing file: Invalid
299 * argument, <filename>" when saving a file to a lufs file system.
301 * The opengroup spec states "It is explicitly intended that a null
302 * implementation is permitted." This is therefore a quick but valid
303 * hack to avoid this problem.
305 * See http://www.moses.uklinux.net/patches/lki-3.html#ss3.4
306 * http://www.opengroup.org/onlinepubs/007904975/functions/fsync.html
308 * James Marsh <marshj@cs.man.ac.uk> 22-Apr-2003
310 static int lu_file_fsync(struct file *filp, struct dentry *dentryp, int datasync)
315 struct file_operations lu_file_operations = {
316 llseek: generic_file_llseek,
318 write: lu_file_write,
321 release: lu_file_release,
325 struct inode_operations lu_file_inode_operations = {
326 revalidate: lu_revalidate_inode,
327 setattr: lufs_notify_change,
330 struct address_space_operations lu_file_aops = {
331 readpage: lu_file_readpage,
332 writepage: lu_file_writepage,
333 prepare_write: lu_file_preparewrite,
334 commit_write: lu_file_commitwrite,