]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 24 Aug 2011 16:14:42 +0000 (09:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 24 Aug 2011 16:14:42 +0000 (09:14 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: check size of FUSE_NOTIFY_INVAL_ENTRY message
  fuse: mark pages accessed when written to
  fuse: delete dead .write_begin and .write_end aops
  fuse: fix flock
  fuse: fix non-ANSI void function notation

1  2 
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

diff --combined fs/fuse/file.c
index d480d9af46c964f8b86ced68feb7e787959a4fdb,7155f49b2ef6c122f53dd2655996d561bd327679..594f07a81c2899ba33a173be33cfc818afa0d39b
@@@ -14,6 -14,7 +14,7 @@@
  #include <linux/sched.h>
  #include <linux/module.h>
  #include <linux/compat.h>
+ #include <linux/swap.h>
  
  static const struct file_operations fuse_direct_io_file_operations;
  
@@@ -245,6 -246,12 +246,12 @@@ void fuse_release_common(struct file *f
        req = ff->reserved_req;
        fuse_prepare_release(ff, file->f_flags, opcode);
  
+       if (ff->flock) {
+               struct fuse_release_in *inarg = &req->misc.release.in;
+               inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
+               inarg->lock_owner = fuse_lock_owner_id(ff->fc,
+                                                      (fl_owner_t) file);
+       }
        /* Hold vfsmount and dentry until release is finished */
        path_get(&file->f_path);
        req->misc.release.path = file->f_path;
@@@ -400,8 -407,7 +407,8 @@@ static void fuse_sync_writes(struct ino
        fuse_release_nowrite(inode);
  }
  
 -int fuse_fsync_common(struct file *file, int datasync, int isdir)
 +int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 +                    int datasync, int isdir)
  {
        struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        if (is_bad_inode(inode))
                return -EIO;
  
 +      err = filemap_write_and_wait_range(inode->i_mapping, start, end);
 +      if (err)
 +              return err;
 +
        if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
                return 0;
  
 +      mutex_lock(&inode->i_mutex);
 +
        /*
         * Start writeback against all dirty pages of the inode, then
         * wait for all outstanding writes, before sending the FSYNC
         */
        err = write_inode_now(inode, 0);
        if (err)
 -              return err;
 +              goto out;
  
        fuse_sync_writes(inode);
  
        req = fuse_get_req(fc);
 -      if (IS_ERR(req))
 -              return PTR_ERR(req);
 +      if (IS_ERR(req)) {
 +              err = PTR_ERR(req);
 +              goto out;
 +      }
  
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
                        fc->no_fsync = 1;
                err = 0;
        }
 +out:
 +      mutex_unlock(&inode->i_mutex);
        return err;
  }
  
 -static int fuse_fsync(struct file *file, int datasync)
 +static int fuse_fsync(struct file *file, loff_t start, loff_t end,
 +                    int datasync)
  {
 -      return fuse_fsync_common(file, datasync, 0);
 +      return fuse_fsync_common(file, start, end, datasync, 0);
  }
  
  void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
@@@ -755,18 -750,6 +762,6 @@@ static size_t fuse_send_write(struct fu
        return req->misc.write.out.size;
  }
  
- static int fuse_write_begin(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned flags,
-                       struct page **pagep, void **fsdata)
- {
-       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-       *pagep = grab_cache_page_write_begin(mapping, index, flags);
-       if (!*pagep)
-               return -ENOMEM;
-       return 0;
- }
  void fuse_write_update_size(struct inode *inode, loff_t pos)
  {
        struct fuse_conn *fc = get_fuse_conn(inode);
        spin_unlock(&fc->lock);
  }
  
- static int fuse_buffered_write(struct file *file, struct inode *inode,
-                              loff_t pos, unsigned count, struct page *page)
- {
-       int err;
-       size_t nres;
-       struct fuse_conn *fc = get_fuse_conn(inode);
-       unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
-       struct fuse_req *req;
-       if (is_bad_inode(inode))
-               return -EIO;
-       /*
-        * Make sure writepages on the same page are not mixed up with
-        * plain writes.
-        */
-       fuse_wait_on_page_writeback(inode, page->index);
-       req = fuse_get_req(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-       req->in.argpages = 1;
-       req->num_pages = 1;
-       req->pages[0] = page;
-       req->page_offset = offset;
-       nres = fuse_send_write(req, file, pos, count, NULL);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
-       if (!err && !nres)
-               err = -EIO;
-       if (!err) {
-               pos += nres;
-               fuse_write_update_size(inode, pos);
-               if (count == PAGE_CACHE_SIZE)
-                       SetPageUptodate(page);
-       }
-       fuse_invalidate_attr(inode);
-       return err ? err : nres;
- }
- static int fuse_write_end(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned copied,
-                       struct page *page, void *fsdata)
- {
-       struct inode *inode = mapping->host;
-       int res = 0;
-       if (copied)
-               res = fuse_buffered_write(file, inode, pos, copied, page);
-       unlock_page(page);
-       page_cache_release(page);
-       return res;
- }
  static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
                                    struct inode *inode, loff_t pos,
                                    size_t count)
@@@ -908,6 -835,8 +847,8 @@@ static ssize_t fuse_fill_write_pages(st
                pagefault_enable();
                flush_dcache_page(page);
  
+               mark_page_accessed(page);
                if (!tmp) {
                        unlock_page(page);
                        page_cache_release(page);
@@@ -1507,7 -1436,7 +1448,7 @@@ static int fuse_setlk(struct file *file
        pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
        int err;
  
 -      if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
 +      if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
                /* NLM needs asynchronous locks, which we don't support yet */
                return -ENOLCK;
        }
@@@ -1559,11 -1488,14 +1500,14 @@@ static int fuse_file_flock(struct file 
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
  
-       if (fc->no_lock) {
+       if (fc->no_flock) {
                err = flock_lock_file_wait(file, fl);
        } else {
+               struct fuse_file *ff = file->private_data;
                /* emulate flock with POSIX locks */
                fl->fl_owner = (fl_owner_t) file;
+               ff->flock = true;
                err = fuse_setlk(file, fl, 1);
        }
  
@@@ -1612,32 -1544,15 +1556,32 @@@ static loff_t fuse_file_llseek(struct f
        struct inode *inode = file->f_path.dentry->d_inode;
  
        mutex_lock(&inode->i_mutex);
 -      switch (origin) {
 -      case SEEK_END:
 +      if (origin != SEEK_CUR || origin != SEEK_SET) {
                retval = fuse_update_attributes(inode, NULL, file, NULL);
                if (retval)
                        goto exit;
 +      }
 +
 +      switch (origin) {
 +      case SEEK_END:
                offset += i_size_read(inode);
                break;
        case SEEK_CUR:
                offset += file->f_pos;
 +              break;
 +      case SEEK_DATA:
 +              if (offset >= i_size_read(inode)) {
 +                      retval = -ENXIO;
 +                      goto exit;
 +              }
 +              break;
 +      case SEEK_HOLE:
 +              if (offset >= i_size_read(inode)) {
 +                      retval = -ENXIO;
 +                      goto exit;
 +              }
 +              offset = i_size_read(inode);
 +              break;
        }
        retval = -EINVAL;
        if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
@@@ -2201,8 -2116,6 +2145,6 @@@ static const struct address_space_opera
        .readpage       = fuse_readpage,
        .writepage      = fuse_writepage,
        .launder_page   = fuse_launder_page,
-       .write_begin    = fuse_write_begin,
-       .write_end      = fuse_write_end,
        .readpages      = fuse_readpages,
        .set_page_dirty = __set_page_dirty_nobuffers,
        .bmap           = fuse_bmap,
diff --combined fs/fuse/fuse_i.h
index c6aa2d4b851733a250205734215c785be6944507,eb8c6135fbbf2b0d9c225b322e6e4ab6f2b1eac0..cf6db0a932192c30d6dc65a327cca84e7258a5dc
@@@ -135,6 -135,9 +135,9 @@@ struct fuse_file 
  
        /** Wait queue head for poll */
        wait_queue_head_t poll_wait;
+       /** Has flock been performed on this file? */
+       bool flock:1;
  };
  
  /** One input argument of a request */
@@@ -448,7 -451,7 +451,7 @@@ struct fuse_conn 
        /** Is removexattr not implemented by fs? */
        unsigned no_removexattr:1;
  
-       /** Are file locking primitives not implemented by fs? */
+       /** Are posix file locking primitives not implemented by fs? */
        unsigned no_lock:1;
  
        /** Is access not implemented by fs? */
        /** Don't apply umask to creation modes */
        unsigned dont_mask:1;
  
+       /** Are BSD file locking primitives not implemented by fs? */
+       unsigned no_flock:1;
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
  
@@@ -589,8 -595,7 +595,8 @@@ void fuse_release_common(struct file *f
  /**
   * Send FSYNC or FSYNCDIR request
   */
 -int fuse_fsync_common(struct file *file, int datasync, int isdir);
 +int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 +                    int datasync, int isdir);
  
  /**
   * Notify poll wakeup
diff --combined fs/fuse/inode.c
index 38f84cd48b67d057798f8f75fe5c8f22f12b10dc,f541d639844be3ae8a7dc0f3e88596787562b973..12b502929da9c51ef78f5ee6d53948e1f5b991a6
@@@ -71,7 -71,7 +71,7 @@@ struct fuse_mount_data 
        unsigned blksize;
  };
  
- struct fuse_forget_link *fuse_alloc_forget()
+ struct fuse_forget_link *fuse_alloc_forget(void)
  {
        return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
  }
@@@ -809,6 -809,10 +809,10 @@@ static void process_init_reply(struct f
                                fc->async_read = 1;
                        if (!(arg->flags & FUSE_POSIX_LOCKS))
                                fc->no_lock = 1;
+                       if (arg->minor >= 17) {
+                               if (!(arg->flags & FUSE_FLOCK_LOCKS))
+                                       fc->no_flock = 1;
+                       }
                        if (arg->flags & FUSE_ATOMIC_O_TRUNC)
                                fc->atomic_o_trunc = 1;
                        if (arg->minor >= 9) {
                } else {
                        ra_pages = fc->max_read / PAGE_CACHE_SIZE;
                        fc->no_lock = 1;
+                       fc->no_flock = 1;
                }
  
                fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
@@@ -843,7 -848,8 +848,8 @@@ static void fuse_send_init(struct fuse_
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
        arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
        arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
-               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
+               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
+               FUSE_FLOCK_LOCKS;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
@@@ -921,8 -927,6 +927,8 @@@ static int fuse_fill_super(struct super
        if (sb->s_flags & MS_MANDLOCK)
                goto err;
  
 +      sb->s_flags &= ~MS_NOSEC;
 +
        if (!parse_fuse_opt((char *) data, &d, is_bdev))
                goto err;