1. 01 Jul, 2015 3 commits
  2. 13 Mar, 2015 1 commit
  3. 06 Jan, 2015 1 commit
  4. 12 Dec, 2014 4 commits
    • Miklos Szeredi's avatar
      fuse: introduce fuse_simple_request() helper · 7078187a
      Miklos Szeredi authored
      
      
      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: default avatarMiklos Szeredi <mszeredi@suse.cz>
      7078187a
    • Miklos Szeredi's avatar
      fuse: reduce max out args · f704dcb5
      Miklos Szeredi authored
      
      
      The third out-arg is never actually used.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      f704dcb5
    • Miklos Szeredi's avatar
      fuse: hold inode instead of path after release · baebccbe
      Miklos Szeredi authored
      
      
      path_put() in release could trigger a DESTROY request in fuseblk.  The
      possible deadlock was worked around by doing the path_put() with
      schedule_work().
      
      This complexity isn't needed if we just hold the inode instead of the path.
      Since we now flush all requests before destroying the super block we can be
      sure that all held inodes will be dropped.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      baebccbe
    • Miklos Szeredi's avatar
      fuse: flush requests on umount · 580640ba
      Miklos Szeredi authored
      
      
      Use fuse_abort_conn() instead of fuse_conn_kill() in fuse_put_super().
      This flushes and aborts requests still on any queues.  But since we've
      already reset fc->connected, those requests would not be useful anyway and
      would be flushed when the fuse device is closed.
      
      Next patches will rely on requests being flushed before the superblock is
      destroyed.
      
      Use fuse_abort_conn() in cuse_process_init_reply() too, since it makes no
      difference there, and we can get rid of fuse_conn_kill().
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      580640ba
  5. 06 May, 2014 1 commit
  6. 28 Apr, 2014 4 commits
  7. 02 Apr, 2014 3 commits
  8. 22 Jan, 2014 2 commits
    • Andrew Gallagher's avatar
      fuse: support clients that don't implement 'open' · 7678ac50
      Andrew Gallagher authored
      
      
      open/release operations require userspace transitions to keep track
      of the open count and to perform any FS-specific setup.  However,
      for some purely read-only FSs which don't need to perform any setup
      at open/release time, we can avoid the performance overhead of
      calling into userspace for open/release calls.
      
      This patch adds the necessary support to the fuse kernel modules to prevent
      open/release operations from hitting in userspace. When the client returns
      ENOSYS, we avoid sending the subsequent release to userspace, and also
      remember this so that future opens also don't trigger a userspace
      operation.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      7678ac50
    • Andrew Gallagher's avatar
      fuse: don't invalidate attrs when not using atime · 451418fc
      Andrew Gallagher authored
      
      
      Various read operations (e.g. readlink, readdir) invalidate the cached
      attrs for atime changes.  This patch adds a new function
      'fuse_invalidate_atime', which checks for a read-only super block and
      avoids the attr invalidation in that case.
      Signed-off-by: default avatarAndrew Gallagher <andrewjcg@fb.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      451418fc
  9. 25 Oct, 2013 2 commits
  10. 01 Oct, 2013 2 commits
    • Miklos Szeredi's avatar
      fuse: writepages: handle same page rewrites · 8b284dc4
      Miklos Szeredi authored
      
      
      As Maxim Patlasov pointed out, it's possible to get a dirty page while it's
      copy is still under writeback, despite fuse_page_mkwrite() doing its thing
      (direct IO).
      
      This could result in two concurrent write request for the same offset, with
      data corruption if they get mixed up.
      
      To prevent this, fuse needs to check and delay such writes.  This
      implementation does this by:
      
       1. check if page is still under writeout, if so create a new, single page
          secondary request for it
      
       2. chain this secondary request onto the in-flight request
      
       2/a. if a seconday request for the same offset was already chained to the
          in-flight request, then just copy the contents of the page and discard
          the new secondary request.  This makes sure that for each page will
          have at most two requests associated with it
      
       3. when the in-flight request finished, send off all secondary requests
          chained onto it
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      8b284dc4
    • Miklos Szeredi's avatar
      fuse: readdirplus: fix RCU walk · 6314efee
      Miklos Szeredi authored
      
      
      Doing dput(parent) is not valid in RCU walk mode.  In RCU mode it would
      probably be okay to update the parent flags, but it's actually not
      necessary most of the time...
      
      So only set the FUSE_I_ADVISE_RDPLUS flag on the parent when the entry was
      recently initialized by READDIRPLUS.
      
      This is achieved by setting FUSE_I_INIT_RDPLUS on entries added by
      READDIRPLUS and only dropping out of RCU mode if this flag is set.
      FUSE_I_INIT_RDPLUS is cleared once the FUSE_I_ADVISE_RDPLUS flag is set in
      the parent.
      Reported-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      6314efee
  11. 03 Sep, 2013 1 commit
    • Maxim Patlasov's avatar
      fuse: hotfix truncate_pagecache() issue · 06a7c3c2
      Maxim Patlasov authored
      
      
      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: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      Cc: stable@vger.kernel.org
      06a7c3c2
  12. 01 May, 2013 1 commit
  13. 18 Apr, 2013 1 commit
  14. 17 Apr, 2013 4 commits
    • Maxim Patlasov's avatar
      fuse: make fuse_direct_io() aware about AIO · 36cf66ed
      Maxim Patlasov authored
      
      
      The patch implements passing "struct fuse_io_priv *io" down the stack up to
      fuse_send_read/write where it is used to submit request asynchronously.
      io->async==0 designates synchronous processing.
      
      Non-trivial part of the patch is changes in fuse_direct_io(): resources
      like fuse requests and user pages cannot be released immediately in async
      case.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      36cf66ed
    • Maxim Patlasov's avatar
      fuse: add support of async IO · 01e9d11a
      Maxim Patlasov authored
      
      
      The patch implements a framework to process an IO request asynchronously. The
      idea is to associate several fuse requests with a single kiocb by means of
      fuse_io_priv structure. The structure plays the same role for FUSE as 'struct
      dio' for direct-io.c.
      
      The framework is supposed to be used like this:
       - someone (who wants to process an IO asynchronously) allocates fuse_io_priv
         and initializes it setting 'async' field to non-zero value.
       - as soon as fuse request is filled, it can be submitted (in non-blocking way)
         by fuse_async_req_send()
       - when all submitted requests are ACKed by userspace, io->reqs drops to zero
         triggering aio_complete()
      
      In case of IO initiated by libaio, aio_complete() will finish processing the
      same way as in case of dio_complete() calling aio_complete(). But the
      framework may be also used for internal FUSE use when initial IO request
      was synchronous (from user perspective), but it's beneficial to process it
      asynchronously. Then the caller should wait on kiocb explicitly and
      aio_complete() will wake the caller up.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      01e9d11a
    • Maxim Patlasov's avatar
      fuse: add flag fc->initialized · 796523fb
      Maxim Patlasov authored
      
      
      Existing flag fc->blocked is used to suspend request allocation both in case
      of many background request submitted and period of time before init_reply
      arrives from userspace. Next patch will skip blocking allocations of
      synchronous request (disregarding fc->blocked). This is mostly OK, but
      we still need to suspend allocations if init_reply is not arrived yet. The
      patch introduces flag fc->initialized which will serve this purpose.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      796523fb
    • Maxim Patlasov's avatar
      fuse: make request allocations for background processing explicit · 8b41e671
      Maxim Patlasov authored
      
      
      There are two types of processing requests in FUSE: synchronous (via
      fuse_request_send()) and asynchronous (via adding to fc->bg_queue).
      
      Fortunately, the type of processing is always known in advance, at the time
      of request allocation. This preparatory patch utilizes this fact making
      fuse_get_req() aware about the type. Next patches will use it.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      8b41e671
  15. 07 Feb, 2013 1 commit
    • Eric Wong's avatar
      fuse: allow control of adaptive readdirplus use · 634734b6
      Eric Wong authored
      
      
      For some filesystems (e.g. GlusterFS), the cost of performing a
      normal readdir and readdirplus are identical.  Since adaptively
      using readdirplus has no benefit for those systems, give
      users/filesystems the option to control adaptive readdirplus use.
      
      v2 of this patch incorporates Miklos's suggestion to simplify the code,
      as well as improving consistency of macro names and documentation.
      Signed-off-by: default avatarEric Wong <normalperson@yhbt.net>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      634734b6
  16. 31 Jan, 2013 2 commits
  17. 24 Jan, 2013 5 commits
    • Miklos Szeredi's avatar
      fuse: cleanup fuse_direct_io() · fb05f41f
      Miklos Szeredi authored
      
      
      Fix the following sparse warnings:
      
      fs/fuse/file.c:1216:43: warning: cast removes address space of expression
      fs/fuse/file.c:1216:43: warning: incorrect type in initializer (different address spaces)
      fs/fuse/file.c:1216:43:    expected void [noderef] <asn:1>*iov_base
      fs/fuse/file.c:1216:43:    got void *<noident>
      fs/fuse/file.c:1241:43: warning: cast removes address space of expression
      fs/fuse/file.c:1241:43: warning: incorrect type in initializer (different address spaces)
      fs/fuse/file.c:1241:43:    expected void [noderef] <asn:1>*iov_base
      fs/fuse/file.c:1241:43:    got void *<noident>
      fs/fuse/file.c:1267:43: warning: cast removes address space of expression
      fs/fuse/file.c:1267:43: warning: incorrect type in initializer (different address spaces)
      fs/fuse/file.c:1267:43:    expected void [noderef] <asn:1>*iov_base
      fs/fuse/file.c:1267:43:    got void *<noident>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      fb05f41f
    • Maxim Patlasov's avatar
      fuse: add per-page descriptor <offset, length> to fuse_req · b2430d75
      Maxim Patlasov authored
      
      
      The ability to save page pointers along with lengths and offsets in fuse_req
      will be useful to cover several iovec-s with a single fuse_req.
      
      Per-request page_offset is removed because anybody who need it can use
      req->page_descs[0].offset instead.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      b2430d75
    • Maxim Patlasov's avatar
      fuse: categorize fuse_get_req() · b111c8c0
      Maxim Patlasov authored
      
      
      The patch categorizes all fuse_get_req() invocations into two categories:
       - fuse_get_req_nopages(fc) - when caller doesn't care about req->pages
       - fuse_get_req(fc, n) - when caller need n page pointers (n > 0)
      
      Adding fuse_get_req_nopages() helps to avoid numerous fuse_get_req(fc, 0)
      scattered over code. Now it's clear from the first glance when a caller need
      fuse_req with page pointers.
      
      The patch doesn't make any logic changes. In multi-page case, it silly
      allocates array of FUSE_MAX_PAGES_PER_REQ page pointers. This will be amended
      by future patches.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      b111c8c0
    • Maxim Patlasov's avatar
      fuse: general infrastructure for pages[] of variable size · 4250c066
      Maxim Patlasov authored
      
      
      The patch removes inline array of FUSE_MAX_PAGES_PER_REQ page pointers from
      fuse_req. Instead of that, req->pages may now point either to small inline
      array or to an array allocated dynamically.
      
      This essentially means that all callers of fuse_request_alloc[_nofs] should
      pass the number of pages needed explicitly.
      
      The patch doesn't make any logic changes.
      Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      4250c066
    • Anand V. Avati's avatar
      fuse: implement NFS-like readdirplus support · 0b05b183
      Anand V. Avati authored
      
      
      This patch implements readdirplus support in FUSE, similar to NFS.
      The payload returned in the readdirplus call contains
      'fuse_entry_out' structure thereby providing all the necessary inputs
      for 'faking' a lookup() operation on the spot.
      
      If the dentry and inode already existed (for e.g. in a re-run of ls -l)
      then just the inode attributes timeout and dentry timeout are refreshed.
      
      With a simple client->network->server implementation of a FUSE based
      filesystem, the following performance observations were made:
      
      Test: Performing a filesystem crawl over 20,000 files with
      
      sh# time ls -lR /mnt
      
      Without readdirplus:
      Run 1: 18.1s
      Run 2: 16.0s
      Run 3: 16.2s
      
      With readdirplus:
      Run 1: 4.1s
      Run 2: 3.8s
      Run 3: 3.8s
      
      The performance improvement is significant as it avoided 20,000 upcalls
      calls (lookup). Cache consistency is no worse than what already is.
      Signed-off-by: default avatarAnand V. Avati <avati@redhat.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      0b05b183
  18. 15 Nov, 2012 1 commit
    • Eric W. Biederman's avatar
      userns: Support fuse interacting with multiple user namespaces · 499dcf20
      Eric W. Biederman authored
      
      
      Use kuid_t and kgid_t in struct fuse_conn and struct fuse_mount_data.
      
      The connection between between a fuse filesystem and a fuse daemon is
      established when a fuse filesystem is mounted and provided with a file
      descriptor the fuse daemon created by opening /dev/fuse.
      
      For now restrict the communication of uids and gids between the fuse
      filesystem and the fuse daemon to the initial user namespace.  Enforce
      this by verifying the file descriptor passed to the mount of fuse was
      opened in the initial user namespace.  Ensuring the mount happens in
      the initial user namespace is not necessary as mounts from non-initial
      user namespaces are not yet allowed.
      
      In fuse_req_init_context convert the currrent fsuid and fsgid into the
      initial user namespace for the request that will be sent to the fuse
      daemon.
      
      In fuse_fill_attr convert the uid and gid passed from the fuse daemon
      from the initial user namespace into kuids and kgids.
      
      In iattr_to_fattr called from fuse_setattr convert kuids and kgids
      into the uids and gids in the initial user namespace before passing
      them to the fuse filesystem.
      
      In fuse_change_attributes_common called from fuse_dentry_revalidate,
      fuse_permission, fuse_geattr, and fuse_setattr, and fuse_iget convert
      the uid and gid from the fuse daemon into a kuid and a kgid to store
      on the fuse inode.
      
      By default fuse mounts are restricted to task whose uid, suid, and
      euid matches the fuse user_id and whose gid, sgid, and egid matches
      the fuse group id.  Convert the user_id and group_id mount options
      into kuids and kgids at mount time, and use uid_eq and gid_eq to
      compare the in fuse_allow_task.
      
      Cc: Miklos Szeredi <miklos@szeredi.hu>
      Acked-by: default avatarSerge Hallyn <serge.hallyn@canonical.com>
      Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
      499dcf20
  19. 18 Jul, 2012 1 commit