1. 11 5月, 2015 1 次提交
    • A
      new ->follow_link() and ->put_link() calling conventions · 680baacb
      Al Viro 提交于
      a) instead of storing the symlink body (via nd_set_link()) and returning
      an opaque pointer later passed to ->put_link(), ->follow_link() _stores_
      that opaque pointer (into void * passed by address by caller) and returns
      the symlink body.  Returning ERR_PTR() on error, NULL on jump (procfs magic
      symlinks) and pointer to symlink body for normal symlinks.  Stored pointer
      is ignored in all cases except the last one.
      
      Storing NULL for opaque pointer (or not storing it at all) means no call
      of ->put_link().
      
      b) the body used to be passed to ->put_link() implicitly (via nameidata).
      Now only the opaque pointer is.  In the cases when we used the symlink body
      to free stuff, ->follow_link() now should store it as opaque pointer in addition
      to returning it.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      680baacb
  2. 16 4月, 2015 1 次提交
  3. 23 2月, 2015 1 次提交
    • D
      VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry) · e36cb0b8
      David Howells 提交于
      Convert the following where appropriate:
      
       (1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
      
       (2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
      
       (3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry).  This is actually more
           complicated than it appears as some calls should be converted to
           d_can_lookup() instead.  The difference is whether the directory in
           question is a real dir with a ->lookup op or whether it's a fake dir with
           a ->d_automount op.
      
      In some circumstances, we can subsume checks for dentry->d_inode not being
      NULL into this, provided we the code isn't in a filesystem that expects
      d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
      use d_inode() rather than d_backing_inode() to get the inode pointer).
      
      Note that the dentry type field may be set to something other than
      DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
      manages the fall-through from a negative dentry to a lower layer.  In such a
      case, the dentry type of the negative union dentry is set to the same as the
      type of the lower dentry.
      
      However, if you know d_inode is not NULL at the call site, then you can use
      the d_is_xxx() functions even in a filesystem.
      
      There is one further complication: a 0,0 chardev dentry may be labelled
      DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE.  Strictly, this was
      intended for special directory entry types that don't have attached inodes.
      
      The following perl+coccinelle script was used:
      
      use strict;
      
      my @callers;
      open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
          die "Can't grep for S_ISDIR and co. callers";
      @callers = <$fd>;
      close($fd);
      unless (@callers) {
          print "No matches\n";
          exit(0);
      }
      
      my @cocci = (
          '@@',
          'expression E;',
          '@@',
          '',
          '- S_ISLNK(E->d_inode->i_mode)',
          '+ d_is_symlink(E)',
          '',
          '@@',
          'expression E;',
          '@@',
          '',
          '- S_ISDIR(E->d_inode->i_mode)',
          '+ d_is_dir(E)',
          '',
          '@@',
          'expression E;',
          '@@',
          '',
          '- S_ISREG(E->d_inode->i_mode)',
          '+ d_is_reg(E)' );
      
      my $coccifile = "tmp.sp.cocci";
      open($fd, ">$coccifile") || die $coccifile;
      print($fd "$_\n") || die $coccifile foreach (@cocci);
      close($fd);
      
      foreach my $file (@callers) {
          chomp $file;
          print "Processing ", $file, "\n";
          system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
      	die "spatch failed";
      }
      
      [AV: overlayfs parts skipped]
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      e36cb0b8
  4. 06 1月, 2015 1 次提交
    • M
      fuse: fix LOOKUP vs INIT compat handling · 21f62174
      Miklos Szeredi 提交于
      Analysis from Marc:
      
       "Commit 7078187a ("fuse: introduce fuse_simple_request() helper")
        from the above pull request triggers some EIO errors for me in some tests
        that rely on fuse
      
        Looking at the code changes and a bit of debugging info I think there's a
        general problem here that fuse_get_req checks and possibly waits for
        fc->initialized, and this was always called first.  But this commit
        changes the ordering and in many places fc->minor is now possibly used
        before fuse_get_req, and we can't be sure that fc has been initialized.
        In my case fuse_lookup_init sets req->out.args[0].size to the wrong size
        because fc->minor at that point is still 0, leading to the EIO error."
      
      Fix by moving the compat adjustments into fuse_simple_request() to after
      fuse_get_req().
      
      This is also more readable than the original, since now compatibility is
      handled in a single function instead of cluttering each operation.
      Reported-by: NMarc Dionne <marc.c.dionne@gmail.com>
      Tested-by: NMarc Dionne <marc.c.dionne@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Fixes: 7078187a ("fuse: introduce fuse_simple_request() helper")
      21f62174
  5. 12 12月, 2014 1 次提交
    • M
      fuse: introduce fuse_simple_request() helper · 7078187a
      Miklos Szeredi 提交于
      The following pattern is repeated many times:
      
      	req = fuse_get_req_nopages(fc);
      	/* Initialize req->(in|out).args */
      	fuse_request_send(fc, req);
      	err = req->out.h.error;
      	fuse_put_request(req);
      
      Create a new replacement helper:
      
      	/* Initialize args */
      	err = fuse_simple_request(fc, &args);
      
      In addition to reducing the code size, this will ease moving from the
      complex arg-based to a simpler page-based I/O on the fuse device.
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      7078187a
  6. 20 11月, 2014 1 次提交
  7. 09 10月, 2014 2 次提交
  8. 08 8月, 2014 1 次提交
  9. 10 7月, 2014 1 次提交
  10. 07 7月, 2014 2 次提交
    • A
      fuse: ignore entry-timeout on LOOKUP_REVAL · 154210cc
      Anand Avati 提交于
      The following test case demonstrates the bug:
      
        sh# mount -t glusterfs localhost:meta-test /mnt/one
      
        sh# mount -t glusterfs localhost:meta-test /mnt/two
      
        sh# echo stuff > /mnt/one/file; rm -f /mnt/two/file; echo stuff > /mnt/one/file
        bash: /mnt/one/file: Stale file handle
      
        sh# echo stuff > /mnt/one/file; rm -f /mnt/two/file; sleep 1; echo stuff > /mnt/one/file
      
      On the second open() on /mnt/one, FUSE would have used the old
      nodeid (file handle) trying to re-open it. Gluster is returning
      -ESTALE. The ESTALE propagates back to namei.c:filename_lookup()
      where lookup is re-attempted with LOOKUP_REVAL. The right
      behavior now, would be for FUSE to ignore the entry-timeout and
      and do the up-call revalidation. Instead FUSE is ignoring
      LOOKUP_REVAL, succeeding the revalidation (because entry-timeout
      has not passed), and open() is again retried on the old file
      handle and finally the ESTALE is going back to the application.
      
      Fix: if revalidation is happening with LOOKUP_REVAL, then ignore
      entry-timeout and always do the up-call.
      Signed-off-by: NAnand Avati <avati@redhat.com>
      Reviewed-by: NNiels de Vos <ndevos@redhat.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      154210cc
    • M
      fuse: timeout comparison fix · 126b9d43
      Miklos Szeredi 提交于
      As suggested by checkpatch.pl, use time_before64() instead of direct
      comparison of jiffies64 values.
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Cc: <stable@vger.kernel.org>
      126b9d43
  11. 28 4月, 2014 7 次提交
  12. 02 4月, 2014 2 次提交
    • M
      fuse: Trust kernel i_mtime only · b0aa7606
      Maxim Patlasov 提交于
      Let the kernel maintain i_mtime locally:
       - clear S_NOCMTIME
       - implement i_op->update_time()
       - flush mtime on fsync and last close
       - update i_mtime explicitly on truncate and fallocate
      
      Fuse inode flag FUSE_I_MTIME_DIRTY serves as indication that local i_mtime
      should be flushed to the server eventually.
      Signed-off-by: NMaxim Patlasov <MPatlasov@parallels.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      b0aa7606
    • P
      fuse: Trust kernel i_size only · 8373200b
      Pavel Emelyanov 提交于
      Make fuse think that when writeback is on the inode's i_size is always
      up-to-date and not update it with the value received from the userspace.
      This is done because the page cache code may update i_size without letting
      the FS know.
      
      This assumption implies fixing the previously introduced short-read helper --
      when a short read occurs the 'hole' is filled with zeroes.
      
      fuse_file_fallocate() is also fixed because now we should keep i_size up to
      date, so it must be updated if FUSE_FALLOCATE request succeeded.
      Signed-off-by: NMaxim V. Patlasov <MPatlasov@parallels.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      8373200b
  13. 23 1月, 2014 1 次提交
  14. 25 10月, 2013 1 次提交
  15. 01 10月, 2013 3 次提交
  16. 13 9月, 2013 1 次提交
  17. 06 9月, 2013 3 次提交
  18. 03 9月, 2013 3 次提交
    • M
      fuse: readdir: check for slash in names · efeb9e60
      Miklos Szeredi 提交于
      Userspace can add names containing a slash character to the directory
      listing.  Don't allow this as it could cause all sorts of trouble.
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      efeb9e60
    • M
      fuse: hotfix truncate_pagecache() issue · 06a7c3c2
      Maxim Patlasov 提交于
      The way how fuse calls truncate_pagecache() from fuse_change_attributes()
      is completely wrong. Because, w/o i_mutex held, we never sure whether
      'oldsize' and 'attr->size' are valid by the time of execution of
      truncate_pagecache(inode, oldsize, attr->size). In fact, as soon as we
      released fc->lock in the middle of fuse_change_attributes(), we completely
      loose control of actions which may happen with given inode until we reach
      truncate_pagecache. The list of potentially dangerous actions includes
      mmap-ed reads and writes, ftruncate(2) and write(2) extending file size.
      
      The typical outcome of doing truncate_pagecache() with outdated arguments
      is data corruption from user point of view. This is (in some sense)
      acceptable in cases when the issue is triggered by a change of the file on
      the server (i.e. externally wrt fuse operation), but it is absolutely
      intolerable in scenarios when a single fuse client modifies a file without
      any external intervention. A real life case I discovered by fsx-linux
      looked like this:
      
      1. Shrinking ftruncate(2) comes to fuse_do_setattr(). The latter sends
      FUSE_SETATTR to the server synchronously, but before getting fc->lock ...
      2. fuse_dentry_revalidate() is asynchronously called. It sends FUSE_LOOKUP
      to the server synchronously, then calls fuse_change_attributes(). The
      latter updates i_size, releases fc->lock, but before comparing oldsize vs
      attr->size..
      3. fuse_do_setattr() from the first step proceeds by acquiring fc->lock and
      updating attributes and i_size, but now oldsize is equal to
      outarg.attr.size because i_size has just been updated (step 2). Hence,
      fuse_do_setattr() returns w/o calling truncate_pagecache().
      4. As soon as ftruncate(2) completes, the user extends file size by
      write(2) making a hole in the middle of file, then reads data from the hole
      either by read(2) or mmap-ed read. The user expects to get zero data from
      the hole, but gets stale data because truncate_pagecache() is not executed
      yet.
      
      The scenario above illustrates one side of the problem: not truncating the
      page cache even though we should. Another side corresponds to truncating
      page cache too late, when the state of inode changed significantly.
      Theoretically, the following is possible:
      
      1. As in the previous scenario fuse_dentry_revalidate() discovered that
      i_size changed (due to our own fuse_do_setattr()) and is going to call
      truncate_pagecache() for some 'new_size' it believes valid right now. But
      by the time that particular truncate_pagecache() is called ...
      2. fuse_do_setattr() returns (either having called truncate_pagecache() or
      not -- it doesn't matter).
      3. The file is extended either by write(2) or ftruncate(2) or fallocate(2).
      4. mmap-ed write makes a page in the extended region dirty.
      
      The result will be the lost of data user wrote on the fourth step.
      
      The patch is a hotfix resolving the issue in a simplistic way: let's skip
      dangerous i_size update and truncate_pagecache if an operation changing
      file size is in progress. This simplistic approach looks correct for the
      cases w/o external changes. And to handle them properly, more sophisticated
      and intrusive techniques (e.g. NFS-like one) would be required. I'd like to
      postpone it until the issue is well discussed on the mailing list(s).
      
      Changed in v2:
       - improved patch description to cover both sides of the issue.
      Signed-off-by: NMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      06a7c3c2
    • A
      fuse: invalidate inode attributes on xattr modification · d331a415
      Anand Avati 提交于
      Calls like setxattr and removexattr result in updation of ctime.
      Therefore invalidate inode attributes to force a refresh.
      Signed-off-by: NAnand Avati <avati@redhat.com>
      Reviewed-by: NBrian Foster <bfoster@redhat.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      d331a415
  19. 17 7月, 2013 5 次提交
  20. 29 6月, 2013 1 次提交
  21. 03 6月, 2013 1 次提交
    • M
      fuse: fix readdirplus Oops in fuse_dentry_revalidate · 28420dad
      Miklos Szeredi 提交于
      Fix bug introduced by commit 4582a4ab "FUSE: Adapt readdirplus to application
      usage patterns".
      
      We need to check for a positive dentry; negative dentries are not added by
      readdirplus.  Secondly we need to advise the use of readdirplus on the *parent*,
      otherwise the whole thing is useless.  Thirdly all this is only relevant if
      "readdirplus_auto" mode is selected by the filesystem.
      
      We advise the use of readdirplus only if the dentry was still valid.  If we had
      to redo the lookup then there was no use in doing the -plus version.
      Reported-by: NBernd Schubert <bernd.schubert@itwm.fraunhofer.de>
      Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
      CC: Feng Shuo <steve.shuo.feng@gmail.com>
      CC: stable@vger.kernel.org
      28420dad