1. 25 May, 2010 8 commits
    • Miklos Szeredi's avatar
      fuse: support splice() reading from fuse device · c3021629
      Miklos Szeredi authored
      Allow userspace filesystem implementation to use splice() to read from
      the fuse device.
      
      The userspace filesystem can now transfer data coming from a WRITE
      request to an arbitrary file descriptor (regular file, block device or
      socket) without having to go through a userspace buffer.
      
      The semantics of using splice() to read messages are:
      
       1)  with a single splice() call move the whole message from the fuse
           device to a temporary pipe
       2)  read the header from the pipe and determine the message type
       3a) if message is a WRITE then splice data from pipe to destination
       3b) else read rest of message to userspace buffer
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      c3021629
    • Miklos Szeredi's avatar
      fuse: allow splice to move pages · ce534fb0
      Miklos Szeredi authored
      When splicing buffers to the fuse device with SPLICE_F_MOVE, try to
      move pages from the pipe buffer into the page cache.  This allows
      populating the fuse filesystem's cache without ever touching the page
      contents, i.e. zero copy read capability.
      
      The following steps are performed when trying to move a page into the
      page cache:
      
       - buf->ops->confirm() to make sure the new page is uptodate
       - buf->ops->steal() to try to remove the new page from it's previous place
       - remove_from_page_cache() on the old page
       - add_to_page_cache_locked() on the new page
      
      If any of the above steps fail (non fatally) then the code falls back
      to copying the page.  In particular ->steal() will fail if there are
      external references (other than the page cache and the pipe buffer) to
      the page.
      
      Also since the remove_from_page_cache() + add_to_page_cache_locked()
      are non-atomic it is possible that the page cache is repopulated in
      between the two and add_to_page_cache_locked() will fail.  This could
      be fixed by creating a new atomic replace_page_cache_page() function.
      
      fuse_readpages_end() needed to be reworked so it works even if
      page->mapping is NULL for some or all pages which can happen if the
      add_to_page_cache_locked() failed.
      
      A number of sanity checks were added to make sure the stolen pages
      don't have weird flags set, etc...  These could be moved into generic
      splice/steal code.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      ce534fb0
    • Miklos Szeredi's avatar
      mm: export remove_from_page_cache() to modules · a52116ab
      Miklos Szeredi authored
      This is needed to enable moving pages into the page cache in fuse with
      splice(..., SPLICE_F_MOVE).
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      a52116ab
    • Miklos Szeredi's avatar
      mm: export lru_cache_add_*() to modules · 47846b06
      Miklos Szeredi authored
      This is needed to enable moving pages into the page cache in fuse with
      splice(..., SPLICE_F_MOVE).
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      47846b06
    • Miklos Szeredi's avatar
      fuse: support splice() writing to fuse device · dd3bb14f
      Miklos Szeredi authored
      Allow userspace filesystem implementation to use splice() to write to
      the fuse device.  The semantics of using splice() are:
      
       1) buffer the message header and data in a temporary pipe
       2) with a *single* splice() call move the message from the temporary pipe
          to the fuse device
      
      The READ reply message has the most interesting use for this, since
      now the data from an arbitrary file descriptor (which could be a
      regular file, a block device or a socket) can be tranferred into the
      fuse device without having to go through a userspace buffer.  It will
      also allow zero copy moving of pages.
      
      One caveat is that the protocol on the fuse device requires the length
      of the whole message to be written into the header.  But the length of
      the data transferred into the temporary pipe may not be known in
      advance.  The current library implementation works around this by
      using vmplice to write the header and modifying the header after
      splicing the data into the pipe (error handling omitted):
      
      	struct fuse_out_header out;
      
      	iov.iov_base = &out;
      	iov.iov_len = sizeof(struct fuse_out_header);
      	vmsplice(pip[1], &iov, 1, 0);
      	len = splice(input_fd, input_offset, pip[1], NULL, len, 0);
      	/* retrospectively modify the header: */
      	out.len = len + sizeof(struct fuse_out_header);
      	splice(pip[0], NULL, fuse_chan_fd(req->ch), NULL, out.len, flags);
      
      This works since vmsplice only saves a pointer to the data, it does
      not copy the data itself.
      
      Since pipes are currently limited to 16 pages and messages need to be
      spliced atomically, the length of the data is limited to 15 pages (or
      60kB for 4k pages).
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      dd3bb14f
    • Miklos Szeredi's avatar
      fuse: get page reference for readpages · b5dd3285
      Miklos Szeredi authored
      Acquire a page ref on pages in ->readpages() and release them when the
      read has finished.  Not acquiring a reference didn't seem to cause any
      trouble since the page is locked and will not be kicked out of the
      page cache during the read.
      
      However the following patches will want to remove the page from the
      cache so a separate ref is needed.  Making the reference in req->pages
      explicit also makes the code easier to understand.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      b5dd3285
    • Miklos Szeredi's avatar
      fuse: use get_user_pages_fast() · 1bf94ca7
      Miklos Szeredi authored
      Replace uses of get_user_pages() with get_user_pages_fast().  It looks
      nicer and should be faster in most cases.
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      1bf94ca7
    • Dan Carpenter's avatar
      fuse: remove unneeded variable · 4aa0edd2
      Dan Carpenter authored
      "map" isn't needed any more after: 0bd87182 "fuse: fix kunmap in
      fuse_ioctl_copy_user" 
      Signed-off-by: default avatarDan Carpenter <error27@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
      4aa0edd2
  2. 24 May, 2010 23 commits
  3. 23 May, 2010 2 commits
  4. 22 May, 2010 7 commits