1. 06 9月, 2013 3 次提交
    • M
      fscache: Netfs function for cleanup post readpages · 5a6f282a
      Milosz Tanski 提交于
      Currently the fscache code expect the netfs to call fscache_readpages_or_alloc
      inside the aops readpages callback.  It marks all the pages in the list
      provided by readahead with PG_private_2.  In the cases that the netfs fails to
      read all the pages (which is legal) it ends up returning to the readahead and
      triggering a BUG.  This happens because the page list still contains marked
      pages.
      
      This patch implements a simple fscache_readpages_cancel function that the netfs
      should call before returning from readpages.  It will revoke the pages from the
      underlying cache backend and unmark them.
      
      The problem was originally worked out in the Ceph devel tree, but it also
      occurs in CIFS.  It appears that NFS, AFS and 9P are okay as read_cache_pages()
      will clean up the unprocessed pages in the case of an error.
      
      This can be used to address the following oops:
      
      [12410647.597278] BUG: Bad page state in process petabucket  pfn:3d504e
      [12410647.597292] page:ffffea000f541380 count:0 mapcount:0 mapping:
      	(null) index:0x0
      [12410647.597298] page flags: 0x200000000001000(private_2)
      
      ...
      
      [12410647.597334] Call Trace:
      [12410647.597345]  [<ffffffff815523f2>] dump_stack+0x19/0x1b
      [12410647.597356]  [<ffffffff8111def7>] bad_page+0xc7/0x120
      [12410647.597359]  [<ffffffff8111e49e>] free_pages_prepare+0x10e/0x120
      [12410647.597361]  [<ffffffff8111fc80>] free_hot_cold_page+0x40/0x170
      [12410647.597363]  [<ffffffff81123507>] __put_single_page+0x27/0x30
      [12410647.597365]  [<ffffffff81123df5>] put_page+0x25/0x40
      [12410647.597376]  [<ffffffffa02bdcf9>] ceph_readpages+0x2e9/0x6e0 [ceph]
      [12410647.597379]  [<ffffffff81122a8f>] __do_page_cache_readahead+0x1af/0x260
      [12410647.597382]  [<ffffffff81122ea1>] ra_submit+0x21/0x30
      [12410647.597384]  [<ffffffff81118f64>] filemap_fault+0x254/0x490
      [12410647.597387]  [<ffffffff8113a74f>] __do_fault+0x6f/0x4e0
      [12410647.597391]  [<ffffffff810125bd>] ? __switch_to+0x16d/0x4a0
      [12410647.597395]  [<ffffffff810865ba>] ? finish_task_switch+0x5a/0xc0
      [12410647.597398]  [<ffffffff8113d856>] handle_pte_fault+0xf6/0x930
      [12410647.597401]  [<ffffffff81008c33>] ? pte_mfn_to_pfn+0x93/0x110
      [12410647.597403]  [<ffffffff81008cce>] ? xen_pmd_val+0xe/0x10
      [12410647.597405]  [<ffffffff81005469>] ? __raw_callee_save_xen_pmd_val+0x11/0x1e
      [12410647.597407]  [<ffffffff8113f361>] handle_mm_fault+0x251/0x370
      [12410647.597411]  [<ffffffff812b0ac4>] ? call_rwsem_down_read_failed+0x14/0x30
      [12410647.597414]  [<ffffffff8155bffa>] __do_page_fault+0x1aa/0x550
      [12410647.597418]  [<ffffffff8108011d>] ? up_write+0x1d/0x20
      [12410647.597422]  [<ffffffff8113141c>] ? vm_mmap_pgoff+0xbc/0xe0
      [12410647.597425]  [<ffffffff81143bb8>] ? SyS_mmap_pgoff+0xd8/0x240
      [12410647.597427]  [<ffffffff8155c3ae>] do_page_fault+0xe/0x10
      [12410647.597431]  [<ffffffff81558818>] page_fault+0x28/0x30
      Signed-off-by: NMilosz Tanski <milosz@adfin.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      5a6f282a
    • D
      FS-Cache: Fix heading in documentation · 696f69b6
      David Howells 提交于
      Fix a heading in the documentation to make it consistent with the contents
      list.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      696f69b6
    • D
      FS-Cache: Add interface to check consistency of a cached object · da9803bc
      David Howells 提交于
      Extend the fscache netfs API so that the netfs can ask as to whether a cache
      object is up to date with respect to its corresponding netfs object:
      
      	int fscache_check_consistency(struct fscache_cookie *cookie)
      
      This will call back to the netfs to check whether the auxiliary data associated
      with a cookie is correct.  It returns 0 if it is and -ESTALE if it isn't; it
      may also return -ENOMEM and -ERESTARTSYS.
      
      The backends now have to implement a mandatory operation pointer:
      
      	int (*check_consistency)(struct fscache_object *object)
      
      that corresponds to the above API call.  FS-Cache takes care of pinning the
      object and the cookie in memory and managing this call with respect to the
      object state.
      
      Original-author: Hongyi Jia <jiayisuse@gmail.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: Hongyi Jia <jiayisuse@gmail.com>
      cc: Milosz Tanski <milosz@adfin.com>
      da9803bc
  2. 21 12月, 2012 1 次提交
    • D
      FS-Cache: Provide proper invalidation · ef778e7a
      David Howells 提交于
      Provide a proper invalidation method rather than relying on the netfs retiring
      the cookie it has and getting a new one.  The problem with this is that isn't
      easy for the netfs to make sure that it has completed/cancelled all its
      outstanding storage and retrieval operations on the cookie it is retiring.
      
      Instead, have the cache provide an invalidation method that will cancel or wait
      for all currently outstanding operations before invalidating the cache, and
      will cause new operations to queue up behind that.  Whilst invalidation is in
      progress, some requests will be rejected until the cache can stack a barrier on
      the operation queue to cause new operations to be deferred behind it.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      ef778e7a
  3. 08 7月, 2011 1 次提交
    • D
      FS-Cache: Add a helper to bulk uncache pages on an inode · c902ce1b
      David Howells 提交于
      Add an FS-Cache helper to bulk uncache pages on an inode.  This will
      only work for the circumstance where the pages in the cache correspond
      1:1 with the pages attached to an inode's page cache.
      
      This is required for CIFS and NFS: When disabling inode cookie, we were
      returning the cookie and setting cifsi->fscache to NULL but failed to
      invalidate any previously mapped pages.  This resulted in "Bad page
      state" errors and manifested in other kind of errors when running
      fsstress.  Fix it by uncaching mapped pages when we disable the inode
      cookie.
      
      This patch should fix the following oops and "Bad page state" errors
      seen during fsstress testing.
      
        ------------[ cut here ]------------
        kernel BUG at fs/cachefiles/namei.c:201!
        invalid opcode: 0000 [#1] SMP
        Pid: 5, comm: kworker/u:0 Not tainted 2.6.38.7-30.fc15.x86_64 #1 Bochs Bochs
        RIP: 0010: cachefiles_walk_to_object+0x436/0x745 [cachefiles]
        RSP: 0018:ffff88002ce6dd00  EFLAGS: 00010282
        RAX: ffff88002ef165f0 RBX: ffff88001811f500 RCX: 0000000000000000
        RDX: 0000000000000000 RSI: 0000000000000100 RDI: 0000000000000282
        RBP: ffff88002ce6dda0 R08: 0000000000000100 R09: ffffffff81b3a300
        R10: 0000ffff00066c0a R11: 0000000000000003 R12: ffff88002ae54840
        R13: ffff88002ae54840 R14: ffff880029c29c00 R15: ffff88001811f4b0
        FS:  00007f394dd32720(0000) GS:ffff88002ef00000(0000) knlGS:0000000000000000
        CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
        CR2: 00007fffcb62ddf8 CR3: 000000001825f000 CR4: 00000000000006e0
        DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
        DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
        Process kworker/u:0 (pid: 5, threadinfo ffff88002ce6c000, task ffff88002ce55cc0)
        Stack:
         0000000000000246 ffff88002ce55cc0 ffff88002ce6dd58 ffff88001815dc00
         ffff8800185246c0 ffff88001811f618 ffff880029c29d18 ffff88001811f380
         ffff88002ce6dd50 ffffffff814757e4 ffff88002ce6dda0 ffffffff8106ac56
        Call Trace:
         cachefiles_lookup_object+0x78/0xd4 [cachefiles]
         fscache_lookup_object+0x131/0x16d [fscache]
         fscache_object_work_func+0x1bc/0x669 [fscache]
         process_one_work+0x186/0x298
         worker_thread+0xda/0x15d
         kthread+0x84/0x8c
         kernel_thread_helper+0x4/0x10
        RIP  cachefiles_walk_to_object+0x436/0x745 [cachefiles]
        ---[ end trace 1d481c9af1804caa ]---
      
      I tested the uncaching by the following means:
      
       (1) Create a big file on my NFS server (104857600 bytes).
      
       (2) Read the file into the cache with md5sum on the NFS client.  Look in
           /proc/fs/fscache/stats:
      
      	Pages  : mrk=25601 unc=0
      
       (3) Open the file for read/write ("bash 5<>/warthog/bigfile").  Look in proc
           again:
      
      	Pages  : mrk=25601 unc=25601
      Reported-by: NJeff Layton <jlayton@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-and-Tested-by: NSuresh Jayaraman <sjayaraman@suse.de>
      cc: stable@kernel.org
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      c902ce1b
  4. 31 3月, 2011 1 次提交
  5. 20 11月, 2009 1 次提交
    • D
      FS-Cache: Handle pages pending storage that get evicted under OOM conditions · 201a1542
      David Howells 提交于
      Handle netfs pages that the vmscan algorithm wants to evict from the pagecache
      under OOM conditions, but that are waiting for write to the cache.  Under these
      conditions, vmscan calls the releasepage() function of the netfs, asking if a
      page can be discarded.
      
      The problem is typified by the following trace of a stuck process:
      
      	kslowd005     D 0000000000000000     0  4253      2 0x00000080
      	 ffff88001b14f370 0000000000000046 ffff880020d0d000 0000000000000007
      	 0000000000000006 0000000000000001 ffff88001b14ffd8 ffff880020d0d2a8
      	 000000000000ddf0 00000000000118c0 00000000000118c0 ffff880020d0d2a8
      	Call Trace:
      	 [<ffffffffa00782d8>] __fscache_wait_on_page_write+0x8b/0xa7 [fscache]
      	 [<ffffffff8104c0f1>] ? autoremove_wake_function+0x0/0x34
      	 [<ffffffffa0078240>] ? __fscache_check_page_write+0x63/0x70 [fscache]
      	 [<ffffffffa00b671d>] nfs_fscache_release_page+0x4e/0xc4 [nfs]
      	 [<ffffffffa00927f0>] nfs_release_page+0x3c/0x41 [nfs]
      	 [<ffffffff810885d3>] try_to_release_page+0x32/0x3b
      	 [<ffffffff81093203>] shrink_page_list+0x316/0x4ac
      	 [<ffffffff8109372b>] shrink_inactive_list+0x392/0x67c
      	 [<ffffffff813532fa>] ? __mutex_unlock_slowpath+0x100/0x10b
      	 [<ffffffff81058df0>] ? trace_hardirqs_on_caller+0x10c/0x130
      	 [<ffffffff8135330e>] ? mutex_unlock+0x9/0xb
      	 [<ffffffff81093aa2>] shrink_list+0x8d/0x8f
      	 [<ffffffff81093d1c>] shrink_zone+0x278/0x33c
      	 [<ffffffff81052d6c>] ? ktime_get_ts+0xad/0xba
      	 [<ffffffff81094b13>] try_to_free_pages+0x22e/0x392
      	 [<ffffffff81091e24>] ? isolate_pages_global+0x0/0x212
      	 [<ffffffff8108e743>] __alloc_pages_nodemask+0x3dc/0x5cf
      	 [<ffffffff81089529>] grab_cache_page_write_begin+0x65/0xaa
      	 [<ffffffff8110f8c0>] ext3_write_begin+0x78/0x1eb
      	 [<ffffffff81089ec5>] generic_file_buffered_write+0x109/0x28c
      	 [<ffffffff8103cb69>] ? current_fs_time+0x22/0x29
      	 [<ffffffff8108a509>] __generic_file_aio_write+0x350/0x385
      	 [<ffffffff8108a588>] ? generic_file_aio_write+0x4a/0xae
      	 [<ffffffff8108a59e>] generic_file_aio_write+0x60/0xae
      	 [<ffffffff810b2e82>] do_sync_write+0xe3/0x120
      	 [<ffffffff8104c0f1>] ? autoremove_wake_function+0x0/0x34
      	 [<ffffffff810b18e1>] ? __dentry_open+0x1a5/0x2b8
      	 [<ffffffff810b1a76>] ? dentry_open+0x82/0x89
      	 [<ffffffffa00e693c>] cachefiles_write_page+0x298/0x335 [cachefiles]
      	 [<ffffffffa0077147>] fscache_write_op+0x178/0x2c2 [fscache]
      	 [<ffffffffa0075656>] fscache_op_execute+0x7a/0xd1 [fscache]
      	 [<ffffffff81082093>] slow_work_execute+0x18f/0x2d1
      	 [<ffffffff8108239a>] slow_work_thread+0x1c5/0x308
      	 [<ffffffff8104c0f1>] ? autoremove_wake_function+0x0/0x34
      	 [<ffffffff810821d5>] ? slow_work_thread+0x0/0x308
      	 [<ffffffff8104be91>] kthread+0x7a/0x82
      	 [<ffffffff8100beda>] child_rip+0xa/0x20
      	 [<ffffffff8100b87c>] ? restore_args+0x0/0x30
      	 [<ffffffff8102ef83>] ? tg_shares_up+0x171/0x227
      	 [<ffffffff8104be17>] ? kthread+0x0/0x82
      	 [<ffffffff8100bed0>] ? child_rip+0x0/0x20
      
      In the above backtrace, the following is happening:
      
       (1) A page storage operation is being executed by a slow-work thread
           (fscache_write_op()).
      
       (2) FS-Cache farms the operation out to the cache to perform
           (cachefiles_write_page()).
      
       (3) CacheFiles is then calling Ext3 to perform the actual write, using Ext3's
           standard write (do_sync_write()) under KERNEL_DS directly from the netfs
           page.
      
       (4) However, for Ext3 to perform the write, it must allocate some memory, in
           particular, it must allocate at least one page cache page into which it
           can copy the data from the netfs page.
      
       (5) Under OOM conditions, the memory allocator can't immediately come up with
           a page, so it uses vmscan to find something to discard
           (try_to_free_pages()).
      
       (6) vmscan finds a clean netfs page it might be able to discard (possibly the
           one it's trying to write out).
      
       (7) The netfs is called to throw the page away (nfs_release_page()) - but it's
           called with __GFP_WAIT, so the netfs decides to wait for the store to
           complete (__fscache_wait_on_page_write()).
      
       (8) This blocks a slow-work processing thread - possibly against itself.
      
      The system ends up stuck because it can't write out any netfs pages to the
      cache without allocating more memory.
      
      To avoid this, we make FS-Cache cancel some writes that aren't in the middle of
      actually being performed.  This means that some data won't make it into the
      cache this time.  To support this, a new FS-Cache function is added
      fscache_maybe_release_page() that replaces what the netfs releasepage()
      functions used to do with respect to the cache.
      
      The decisions fscache_maybe_release_page() makes are counted and displayed
      through /proc/fs/fscache/stats on a line labelled "VmScan".  There are four
      counters provided: "nos=N" - pages that weren't pending storage; "gon=N" -
      pages that were pending storage when we first looked, but weren't by the time
      we got the object lock; "bsy=N" - pages that we ignored as they were actively
      being written when we looked; and "can=N" - pages that we cancelled the storage
      of.
      
      What I'd really like to do is alter the behaviour of the cancellation
      heuristics, depending on how necessary it is to expel pages.  If there are
      plenty of other pages that aren't waiting to be written to the cache that
      could be ejected first, then it would be nice to hold up on immediate
      cancellation of cache writes - but I don't see a way of doing that.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      201a1542
  6. 13 6月, 2009 1 次提交
  7. 03 4月, 2009 1 次提交
    • D
      FS-Cache: Add the FS-Cache netfs API and documentation · 2d6fff63
      David Howells 提交于
      Add the API for a generic facility (FS-Cache) by which filesystems (such as AFS
      or NFS) may call on local caching capabilities without having to know anything
      about how the cache works, or even if there is a cache:
      
      	+---------+
      	|         |                        +--------------+
      	|   NFS   |--+                     |              |
      	|         |  |                 +-->|   CacheFS    |
      	+---------+  |   +----------+  |   |  /dev/hda5   |
      	             |   |          |  |   +--------------+
      	+---------+  +-->|          |  |
      	|         |      |          |--+
      	|   AFS   |----->| FS-Cache |
      	|         |      |          |--+
      	+---------+  +-->|          |  |
      	             |   |          |  |   +--------------+
      	+---------+  |   +----------+  |   |              |
      	|         |  |                 +-->|  CacheFiles  |
      	|  ISOFS  |--+                     |  /var/cache  |
      	|         |                        +--------------+
      	+---------+
      
      General documentation and documentation of the netfs specific API are provided
      in addition to the header files.
      
      As this patch stands, it is possible to build a filesystem against the facility
      and attempt to use it.  All that will happen is that all requests will be
      immediately denied as if no cache is present.
      
      Further patches will implement the core of the facility.  The facility will
      transfer requests from networking filesystems to appropriate caches if
      possible, or else gracefully deny them.
      
      If this facility is disabled in the kernel configuration, then all its
      operations will trivially reduce to nothing during compilation.
      
      WHY NOT I_MAPPING?
      ==================
      
      I have added my own API to implement caching rather than using i_mapping to do
      this for a number of reasons.  These have been discussed a lot on the LKML and
      CacheFS mailing lists, but to summarise the basics:
      
       (1) Most filesystems don't do hole reportage.  Holes in files are treated as
           blocks of zeros and can't be distinguished otherwise, making it difficult
           to distinguish blocks that have been read from the network and cached from
           those that haven't.
      
       (2) The backing inode must be fully populated before being exposed to
           userspace through the main inode because the VM/VFS goes directly to the
           backing inode and does not interrogate the front inode's VM ops.
      
           Therefore:
      
           (a) The backing inode must fit entirely within the cache.
      
           (b) All backed files currently open must fit entirely within the cache at
           	 the same time.
      
           (c) A working set of files in total larger than the cache may not be
           	 cached.
      
           (d) A file may not grow larger than the available space in the cache.
      
           (e) A file that's open and cached, and remotely grows larger than the
           	 cache is potentially stuffed.
      
       (3) Writes go to the backing filesystem, and can only be transferred to the
           network when the file is closed.
      
       (4) There's no record of what changes have been made, so the whole file must
           be written back.
      
       (5) The pages belong to the backing filesystem, and all metadata associated
           with that page are relevant only to the backing filesystem, and not
           anything stacked atop it.
      
      OVERVIEW
      ========
      
      FS-Cache provides (or will provide) the following facilities:
      
       (1) Caches can be added / removed at any time, even whilst in use.
      
       (2) Adds a facility by which tags can be used to refer to caches, even if
           they're not available yet.
      
       (3) More than one cache can be used at once.  Caches can be selected
           explicitly by use of tags.
      
       (4) The netfs is provided with an interface that allows either party to
           withdraw caching facilities from a file (required for (1)).
      
       (5) A netfs may annotate cache objects that belongs to it.  This permits the
           storage of coherency maintenance data.
      
       (6) Cache objects will be pinnable and space reservations will be possible.
      
       (7) The interface to the netfs returns as few errors as possible, preferring
           rather to let the netfs remain oblivious.
      
       (8) Cookies are used to represent indices, files and other objects to the
           netfs.  The simplest cookie is just a NULL pointer - indicating nothing
           cached there.
      
       (9) The netfs is allowed to propose - dynamically - any index hierarchy it
           desires, though it must be aware that the index search function is
           recursive, stack space is limited, and indices can only be children of
           indices.
      
      (10) Indices can be used to group files together to reduce key size and to make
           group invalidation easier.  The use of indices may make lookup quicker,
           but that's cache dependent.
      
      (11) Data I/O is effectively done directly to and from the netfs's pages.  The
           netfs indicates that page A is at index B of the data-file represented by
           cookie C, and that it should be read or written.  The cache backend may or
           may not start I/O on that page, but if it does, a netfs callback will be
           invoked to indicate completion.  The I/O may be either synchronous or
           asynchronous.
      
      (12) Cookies can be "retired" upon release.  At this point FS-Cache will mark
           them as obsolete and the index hierarchy rooted at that point will get
           recycled.
      
      (13) The netfs provides a "match" function for index searches.  In addition to
           saying whether a match was made or not, this can also specify that an
           entry should be updated or deleted.
      
      FS-Cache maintains a virtual index tree in which all indices, files, objects
      and pages are kept.  Bits of this tree may actually reside in one or more
      caches.
      
                                                 FSDEF
                                                   |
                              +------------------------------------+
                              |                                    |
                             NFS                                  AFS
                              |                                    |
                 +--------------------------+                +-----------+
                 |                          |                |           |
              homedir                     mirror          afs.org   redhat.com
                 |                          |                            |
           +------------+           +---------------+              +----------+
           |            |           |               |              |          |
         00001        00002       00007           00125        vol00001   vol00002
           |            |           |               |                         |
       +---+---+     +-----+      +---+      +------+------+            +-----+----+
       |   |   |     |     |      |   |      |      |      |            |     |    |
      PG0 PG1 PG2   PG0  XATTR   PG0 PG1   DIRENT DIRENT DIRENT        R/W   R/O  Bak
                           |                                            |
                          PG0                                       +-------+
                                                                    |       |
                                                                  00001   00003
                                                                    |
                                                                +---+---+
                                                                |   |   |
                                                               PG0 PG1 PG2
      
      In the example above, two netfs's can be seen to be backed: NFS and AFS.  These
      have different index hierarchies:
      
       (*) The NFS primary index will probably contain per-server indices.  Each
           server index is indexed by NFS file handles to get data file objects.
           Each data file objects can have an array of pages, but may also have
           further child objects, such as extended attributes and directory entries.
           Extended attribute objects themselves have page-array contents.
      
       (*) The AFS primary index contains per-cell indices.  Each cell index contains
           per-logical-volume indices.  Each of volume index contains up to three
           indices for the read-write, read-only and backup mirrors of those volumes.
           Each of these contains vnode data file objects, each of which contains an
           array of pages.
      
      The very top index is the FS-Cache master index in which individual netfs's
      have entries.
      
      Any index object may reside in more than one cache, provided it only has index
      children.  Any index with non-index object children will be assumed to only
      reside in one cache.
      
      The FS-Cache overview can be found in:
      
      	Documentation/filesystems/caching/fscache.txt
      
      The netfs API to FS-Cache can be found in:
      
      	Documentation/filesystems/caching/netfs-api.txt
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NSteve Dickson <steved@redhat.com>
      Acked-by: NTrond Myklebust <Trond.Myklebust@netapp.com>
      Acked-by: NAl Viro <viro@zeniv.linux.org.uk>
      Tested-by: NDaire Byrne <Daire.Byrne@framestore.com>
      2d6fff63