Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-drm-fsl-dcu.git] / fs / fuse / file.c
index 183626868eea602d4658e5395ec31f46130c0afe..2fd06927e851674e14968cda55898ec832ab2ac0 100644 (file)
@@ -69,7 +69,7 @@ void fuse_finish_open(struct inode *inode, struct file *file,
        if (outarg->open_flags & FOPEN_DIRECT_IO)
                file->f_op = &fuse_direct_io_file_operations;
        if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
-               invalidate_inode_pages(inode->i_mapping);
+               invalidate_mapping_pages(inode->i_mapping, 0, -1);
        ff->fh = outarg->fh;
        file->private_data = ff;
 }
@@ -141,8 +141,8 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
                                        isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
 
                /* Hold vfsmount and dentry until release is finished */
-               req->vfsmount = mntget(file->f_vfsmnt);
-               req->dentry = dget(file->f_dentry);
+               req->vfsmount = mntget(file->f_path.mnt);
+               req->dentry = dget(file->f_path.dentry);
                request_send_background(fc, req);
        }
 
@@ -184,7 +184,7 @@ static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req;
@@ -397,14 +397,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 
        err = -EIO;
        if (is_bad_inode(inode))
-               goto clean_pages_up;
+               goto out;
 
        data.file = file;
        data.inode = inode;
        data.req = fuse_get_req(fc);
        err = PTR_ERR(data.req);
        if (IS_ERR(data.req))
-               goto clean_pages_up;
+               goto out;
 
        err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
        if (!err) {
@@ -413,10 +413,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
                else
                        fuse_put_request(fc, data.req);
        }
-       return err;
-
-clean_pages_up:
-       put_pages_list(pages);
+out:
        return err;
 }
 
@@ -481,13 +478,13 @@ static int fuse_commit_write(struct file *file, struct page *page,
                err = -EIO;
        if (!err) {
                pos += count;
-               if (pos > i_size_read(inode))
+               spin_lock(&fc->lock);
+               if (pos > inode->i_size)
                        i_size_write(inode, pos);
+               spin_unlock(&fc->lock);
 
-               if (offset == 0 && to == PAGE_CACHE_SIZE) {
-                       clear_page_dirty(page);
+               if (offset == 0 && to == PAGE_CACHE_SIZE)
                        SetPageUptodate(page);
-               }
        }
        fuse_invalidate_attr(inode);
        return err;
@@ -534,7 +531,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
 static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
                              size_t count, loff_t *ppos, int write)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        size_t nmax = write ? fc->max_write : fc->max_read;
        loff_t pos = *ppos;
@@ -586,8 +583,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
        }
        fuse_put_request(fc, req);
        if (res > 0) {
-               if (write && pos > i_size_read(inode))
-                       i_size_write(inode, pos);
+               if (write) {
+                       spin_lock(&fc->lock);
+                       if (pos > inode->i_size)
+                               i_size_write(inode, pos);
+                       spin_unlock(&fc->lock);
+               }
                *ppos = pos;
        }
        fuse_invalidate_attr(inode);
@@ -604,7 +605,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
 static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t res;
        /* Don't allow parallel writes to the same file */
        mutex_lock(&inode->i_mutex);
@@ -659,7 +660,7 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
 static void fuse_lk_fill(struct fuse_req *req, struct file *file,
                         const struct file_lock *fl, int opcode, pid_t pid)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_lk_in *arg = &req->misc.lk_in;
@@ -679,7 +680,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
 
 static int fuse_getlk(struct file *file, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_lk_out outarg;
@@ -704,7 +705,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
 
 static int fuse_setlk(struct file *file, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
@@ -731,7 +732,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
 
 static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
@@ -751,6 +752,42 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
        return err;
 }
 
+static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
+{
+       struct inode *inode = mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_bmap_in inarg;
+       struct fuse_bmap_out outarg;
+       int err;
+
+       if (!inode->i_sb->s_bdev || fc->no_bmap)
+               return 0;
+
+       req = fuse_get_req(fc);
+       if (IS_ERR(req))
+               return 0;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.block = block;
+       inarg.blocksize = inode->i_sb->s_blocksize;
+       req->in.h.opcode = FUSE_BMAP;
+       req->in.h.nodeid = get_node_id(inode);
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS)
+               fc->no_bmap = 1;
+
+       return err ? 0 : outarg.block;
+}
+
 static const struct file_operations fuse_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
@@ -784,6 +821,7 @@ static const struct address_space_operations fuse_file_aops  = {
        .commit_write   = fuse_commit_write,
        .readpages      = fuse_readpages,
        .set_page_dirty = fuse_set_page_dirty,
+       .bmap           = fuse_bmap,
 };
 
 void fuse_init_file_inode(struct inode *inode)