diff options
Diffstat (limited to 'fs/coda/file.c')
| -rw-r--r-- | fs/coda/file.c | 174 |
1 files changed, 58 insertions, 116 deletions
diff --git a/fs/coda/file.c b/fs/coda/file.c index 30b4630bd73..9e83b779021 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -13,20 +13,18 @@ #include <linux/file.h> #include <linux/fs.h> #include <linux/stat.h> +#include <linux/cred.h> #include <linux/errno.h> -#include <linux/smp_lock.h> +#include <linux/spinlock.h> #include <linux/string.h> +#include <linux/slab.h> #include <asm/uaccess.h> #include <linux/coda.h> -#include <linux/coda_linux.h> -#include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> -#include <linux/coda_proc.h> -/* if CODA_STORE fails with EOPNOTSUPP, venus clearly doesn't support - * CODA_STORE/CODA_RELEASE and we fall back on using the CODA_CLOSE upcall */ -static int use_coda_close; +#include "coda_linux.h" +#include "coda_int.h" static ssize_t coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *ppos) @@ -38,16 +36,19 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - if (!host_file->f_op || !host_file->f_op->read) + if (!host_file->f_op->read) return -EINVAL; return host_file->f_op->read(host_file, buf, count, ppos); } static ssize_t -coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, - read_actor_t actor, void *target) +coda_file_splice_read(struct file *coda_file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t count, + unsigned int flags) { + ssize_t (*splice_read)(struct file *, loff_t *, + struct pipe_inode_info *, size_t, unsigned int); struct coda_file_info *cfi; struct file *host_file; @@ -55,16 +56,17 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - if (!host_file->f_op || !host_file->f_op->sendfile) - return -EINVAL; + splice_read = host_file->f_op->splice_read; + if (!splice_read) + splice_read = default_file_splice_read; - return host_file->f_op->sendfile(host_file, ppos, count, actor, target); + return splice_read(host_file, ppos, pipe, count, flags); } static ssize_t coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode; + struct inode *host_inode, *coda_inode = file_inode(coda_file); struct coda_file_info *cfi; struct file *host_file; ssize_t ret; @@ -73,10 +75,11 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - if (!host_file->f_op || !host_file->f_op->write) + if (!host_file->f_op->write) return -EINVAL; - host_inode = host_file->f_dentry->d_inode; + host_inode = file_inode(host_file); + file_start_write(host_file); mutex_lock(&coda_inode->i_mutex); ret = host_file->f_op->write(host_file, buf, count, ppos); @@ -85,6 +88,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9; coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC; mutex_unlock(&coda_inode->i_mutex); + file_end_write(host_file); return ret; } @@ -101,24 +105,29 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - if (!host_file->f_op || !host_file->f_op->mmap) + if (!host_file->f_op->mmap) return -ENODEV; - coda_inode = coda_file->f_dentry->d_inode; - host_inode = host_file->f_dentry->d_inode; + coda_inode = file_inode(coda_file); + host_inode = file_inode(host_file); + + cii = ITOC(coda_inode); + spin_lock(&cii->c_lock); coda_file->f_mapping = host_file->f_mapping; if (coda_inode->i_mapping == &coda_inode->i_data) coda_inode->i_mapping = host_inode->i_mapping; /* only allow additional mmaps as long as userspace isn't changing * the container file on us! */ - else if (coda_inode->i_mapping != host_inode->i_mapping) + else if (coda_inode->i_mapping != host_inode->i_mapping) { + spin_unlock(&cii->c_lock); return -EBUSY; + } /* keep track of how often the coda_inode/host_file has been mmapped */ - cii = ITOC(coda_inode); cii->c_mapcount++; cfi->cfi_mapcount++; + spin_unlock(&cii->c_lock); return host_file->f_op->mmap(host_file, vma); } @@ -131,21 +140,17 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) unsigned short coda_flags = coda_flags_to_cflags(flags); struct coda_file_info *cfi; - coda_vfs_stat.open++; - cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL); - if (!cfi) { - unlock_kernel(); + if (!cfi) return -ENOMEM; - } - - lock_kernel(); error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, - &host_file); - if (error || !host_file) { + &host_file); + if (!host_file) + error = -EIO; + + if (error) { kfree(cfi); - unlock_kernel(); return error; } @@ -157,54 +162,9 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) BUG_ON(coda_file->private_data != NULL); coda_file->private_data = cfi; - - unlock_kernel(); return 0; } -int coda_flush(struct file *coda_file) -{ - unsigned short flags = coda_file->f_flags & ~O_EXCL; - unsigned short coda_flags = coda_flags_to_cflags(flags); - struct coda_file_info *cfi; - struct inode *coda_inode; - int err = 0, fcnt; - - lock_kernel(); - - coda_vfs_stat.flush++; - - /* last close semantics */ - fcnt = file_count(coda_file); - if (fcnt > 1) - goto out; - - /* No need to make an upcall when we have not made any modifications - * to the file */ - if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY) - goto out; - - if (use_coda_close) - goto out; - - cfi = CODA_FTOC(coda_file); - BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); - - coda_inode = coda_file->f_dentry->d_inode; - - err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, - coda_file->f_uid); - - if (err == -EOPNOTSUPP) { - use_coda_close = 1; - err = 0; - } - -out: - unlock_kernel(); - return err; -} - int coda_release(struct inode *coda_inode, struct file *coda_file) { unsigned short flags = (coda_file->f_flags) & (~O_EXCL); @@ -212,89 +172,71 @@ int coda_release(struct inode *coda_inode, struct file *coda_file) struct coda_file_info *cfi; struct coda_inode_info *cii; struct inode *host_inode; - int err = 0; - - lock_kernel(); - coda_vfs_stat.release++; - - if (!use_coda_close) { - err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode), - coda_flags); - if (err == -EOPNOTSUPP) { - use_coda_close = 1; - err = 0; - } - } + int err; cfi = CODA_FTOC(coda_file); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); - if (use_coda_close) - err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode), - coda_flags, coda_file->f_uid); + err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode), + coda_flags, coda_file->f_cred->fsuid); - host_inode = cfi->cfi_container->f_dentry->d_inode; + host_inode = file_inode(cfi->cfi_container); cii = ITOC(coda_inode); /* did we mmap this file? */ + spin_lock(&cii->c_lock); if (coda_inode->i_mapping == &host_inode->i_data) { cii->c_mapcount -= cfi->cfi_mapcount; if (!cii->c_mapcount) coda_inode->i_mapping = &coda_inode->i_data; } + spin_unlock(&cii->c_lock); fput(cfi->cfi_container); kfree(coda_file->private_data); coda_file->private_data = NULL; - unlock_kernel(); - return err; + /* VFS fput ignores the return value from file_operations->release, so + * there is no use returning an error here */ + return 0; } -int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) +int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync) { struct file *host_file; - struct dentry *host_dentry; - struct inode *host_inode, *coda_inode = coda_dentry->d_inode; + struct inode *coda_inode = file_inode(coda_file); struct coda_file_info *cfi; - int err = 0; + int err; if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) || S_ISLNK(coda_inode->i_mode))) return -EINVAL; + err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end); + if (err) + return err; + mutex_lock(&coda_inode->i_mutex); + cfi = CODA_FTOC(coda_file); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - coda_vfs_stat.fsync++; - - if (host_file->f_op && host_file->f_op->fsync) { - host_dentry = host_file->f_dentry; - host_inode = host_dentry->d_inode; - mutex_lock(&host_inode->i_mutex); - err = host_file->f_op->fsync(host_file, host_dentry, datasync); - mutex_unlock(&host_inode->i_mutex); - } - - if ( !err && !datasync ) { - lock_kernel(); + err = vfs_fsync(host_file, datasync); + if (!err && !datasync) err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode)); - unlock_kernel(); - } + mutex_unlock(&coda_inode->i_mutex); return err; } -struct file_operations coda_file_operations = { +const struct file_operations coda_file_operations = { .llseek = generic_file_llseek, .read = coda_file_read, .write = coda_file_write, .mmap = coda_file_mmap, .open = coda_open, - .flush = coda_flush, .release = coda_release, .fsync = coda_fsync, - .sendfile = coda_file_sendfile, + .splice_read = coda_file_splice_read, }; |
