08 Jul, 2011

1 commit

  • 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: Jeff Layton
    Signed-off-by: David Howells
    Reviewed-and-Tested-by: Suresh Jayaraman
    cc: stable@kernel.org
    Signed-off-by: Linus Torvalds

    David Howells
     

15 May, 2010

1 commit

  • Seen with -Wextra:

    /home/cel/linux/fs/nfs/fscache.c: In function ‘__nfs_readpages_from_fscache’:
    /home/cel/linux/fs/nfs/fscache.c:479: warning: comparison between signed and unsigned integer expressions

    The comparison implicitly converts "int" to "unsigned", making it
    safe. But there's no need for the implicit type conversions here, and
    the dfprintk() already uses a "%u" formatter for "npages." Better to
    reduce confusion.

    Signed-off-by: Chuck Lever
    Signed-off-by: Trond Myklebust

    Chuck Lever
     

30 Mar, 2010

1 commit

  • …it slab.h inclusion from percpu.h

    percpu.h is included by sched.h and module.h and thus ends up being
    included when building most .c files. percpu.h includes slab.h which
    in turn includes gfp.h making everything defined by the two files
    universally available and complicating inclusion dependencies.

    percpu.h -> slab.h dependency is about to be removed. Prepare for
    this change by updating users of gfp and slab facilities include those
    headers directly instead of assuming availability. As this conversion
    needs to touch large number of source files, the following script is
    used as the basis of conversion.

    http://userweb.kernel.org/~tj/misc/slabh-sweep.py

    The script does the followings.

    * Scan files for gfp and slab usages and update includes such that
    only the necessary includes are there. ie. if only gfp is used,
    gfp.h, if slab is used, slab.h.

    * When the script inserts a new include, it looks at the include
    blocks and try to put the new include such that its order conforms
    to its surrounding. It's put in the include block which contains
    core kernel includes, in the same order that the rest are ordered -
    alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
    doesn't seem to be any matching order.

    * If the script can't find a place to put a new include (mostly
    because the file doesn't have fitting include block), it prints out
    an error message indicating which .h file needs to be added to the
    file.

    The conversion was done in the following steps.

    1. The initial automatic conversion of all .c files updated slightly
    over 4000 files, deleting around 700 includes and adding ~480 gfp.h
    and ~3000 slab.h inclusions. The script emitted errors for ~400
    files.

    2. Each error was manually checked. Some didn't need the inclusion,
    some needed manual addition while adding it to implementation .h or
    embedding .c file was more appropriate for others. This step added
    inclusions to around 150 files.

    3. The script was run again and the output was compared to the edits
    from #2 to make sure no file was left behind.

    4. Several build tests were done and a couple of problems were fixed.
    e.g. lib/decompress_*.c used malloc/free() wrappers around slab
    APIs requiring slab.h to be added manually.

    5. The script was run on all .h files but without automatically
    editing them as sprinkling gfp.h and slab.h inclusions around .h
    files could easily lead to inclusion dependency hell. Most gfp.h
    inclusion directives were ignored as stuff from gfp.h was usually
    wildly available and often used in preprocessor macros. Each
    slab.h inclusion directive was examined and added manually as
    necessary.

    6. percpu.h was updated not to include slab.h.

    7. Build test were done on the following configurations and failures
    were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
    distributed build env didn't work with gcov compiles) and a few
    more options had to be turned off depending on archs to make things
    build (like ipr on powerpc/64 which failed due to missing writeq).

    * x86 and x86_64 UP and SMP allmodconfig and a custom test config.
    * powerpc and powerpc64 SMP allmodconfig
    * sparc and sparc64 SMP allmodconfig
    * ia64 SMP allmodconfig
    * s390 SMP allmodconfig
    * alpha SMP allmodconfig
    * um on x86_64 SMP allmodconfig

    8. percpu.h modifications were reverted so that it could be applied as
    a separate patch and serve as bisection point.

    Given the fact that I had only a couple of failures from tests on step
    6, I'm fairly confident about the coverage of this conversion patch.
    If there is a breakage, it's likely to be something in one of the arch
    headers which should be easily discoverable easily on most builds of
    the specific arch.

    Signed-off-by: Tejun Heo <tj@kernel.org>
    Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>

    Tejun Heo
     

10 Feb, 2010

1 commit


20 Nov, 2009

1 commit

  • 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:
    [] __fscache_wait_on_page_write+0x8b/0xa7 [fscache]
    [] ? autoremove_wake_function+0x0/0x34
    [] ? __fscache_check_page_write+0x63/0x70 [fscache]
    [] nfs_fscache_release_page+0x4e/0xc4 [nfs]
    [] nfs_release_page+0x3c/0x41 [nfs]
    [] try_to_release_page+0x32/0x3b
    [] shrink_page_list+0x316/0x4ac
    [] shrink_inactive_list+0x392/0x67c
    [] ? __mutex_unlock_slowpath+0x100/0x10b
    [] ? trace_hardirqs_on_caller+0x10c/0x130
    [] ? mutex_unlock+0x9/0xb
    [] shrink_list+0x8d/0x8f
    [] shrink_zone+0x278/0x33c
    [] ? ktime_get_ts+0xad/0xba
    [] try_to_free_pages+0x22e/0x392
    [] ? isolate_pages_global+0x0/0x212
    [] __alloc_pages_nodemask+0x3dc/0x5cf
    [] grab_cache_page_write_begin+0x65/0xaa
    [] ext3_write_begin+0x78/0x1eb
    [] generic_file_buffered_write+0x109/0x28c
    [] ? current_fs_time+0x22/0x29
    [] __generic_file_aio_write+0x350/0x385
    [] ? generic_file_aio_write+0x4a/0xae
    [] generic_file_aio_write+0x60/0xae
    [] do_sync_write+0xe3/0x120
    [] ? autoremove_wake_function+0x0/0x34
    [] ? __dentry_open+0x1a5/0x2b8
    [] ? dentry_open+0x82/0x89
    [] cachefiles_write_page+0x298/0x335 [cachefiles]
    [] fscache_write_op+0x178/0x2c2 [fscache]
    [] fscache_op_execute+0x7a/0xd1 [fscache]
    [] slow_work_execute+0x18f/0x2d1
    [] slow_work_thread+0x1c5/0x308
    [] ? autoremove_wake_function+0x0/0x34
    [] ? slow_work_thread+0x0/0x308
    [] kthread+0x7a/0x82
    [] child_rip+0xa/0x20
    [] ? restore_args+0x0/0x30
    [] ? tg_shares_up+0x171/0x227
    [] ? kthread+0x0/0x82
    [] ? 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: David Howells

    David Howells
     

24 Sep, 2009

1 commit

  • Propagate the NFS 'fsc' mount option through NFS automounts of various types.

    This is now required as commit:

    commit c02d7adf8c5429727a98bad1d039bccad4c61c50
    Author: Trond Myklebust
    Date: Mon Jun 22 15:09:14 2009 -0400

    NFSv4: Replace nfs4_path_walk() with VFS path lookup in a private namespace

    uses VFS-driven automounting to reach all submounts barring the root, thus
    preventing fscaching from being enabled on any submount other than the root.

    This patch gets around that by propagating the NFS_OPTION_FSCACHE flag across
    automounts. If a uniquifier is supplied to a mount then this is propagated to
    all automounts of that mount too.

    Signed-off-by: David Howells
    [Trond: Fixed up the definition of nfs_fscache_get_super_cookie for the
    case of #undef CONFIG_NFS_FSCACHE]
    Signed-off-by: Trond Myklebust

    David Howells
     

03 Apr, 2009

6 commits

  • Store pages from an NFS inode into the cache data storage object associated
    with that inode.

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells
     
  • Read pages from an FS-Cache data storage object representing an inode into an
    NFS inode.

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells
     
  • FS-Cache page management for NFS. This includes hooking the releasing and
    invalidation of pages marked with PG_fscache (aka PG_private_2) and waiting for
    completion of the write-to-cache flag (PG_fscache_write aka PG_owner_priv_2).

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells
     
  • Bind data storage objects in the local cache to NFS inodes.

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells
     
  • Define and create superblock-level cache index objects (as managed by
    nfs_server structs).

    Each superblock object is created in a server level index object and is itself
    an index into which inode-level objects are inserted.

    Ideally there would be one superblock-level object per server, and the former
    would be folded into the latter; however, since the "nosharecache" option
    exists this isn't possible.

    The superblock object key is a sequence consisting of:

    (1) Certain superblock s_flags.

    (2) Various connection parameters that serve to distinguish superblocks for
    sget().

    (3) The volume FSID.

    (4) The security flavour.

    (5) The uniquifier length.

    (6) The uniquifier text. This is normally an empty string, unless the fsc=xyz
    mount option was used to explicitly specify a uniquifier.

    The key blob is of variable length, depending on the length of (6).

    The superblock object is given no coherency data to carry in the auxiliary data
    permitted by the cache. It is assumed that the superblock is always coherent.

    This patch also adds uniquification handling such that two otherwise identical
    superblocks, at least one of which is marked "nosharecache", won't end up
    trying to share the on-disk cache. It will be possible to manually provide a
    uniquifier through a mount option with a later patch to avoid the error
    otherwise produced.

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells
     
  • Define and create server-level cache index objects (as managed by nfs_client
    structs).

    Each server object is created in the NFS top-level index object and is itself
    an index into which superblock-level objects are inserted.

    Ideally there would be one superblock-level object per server, and the former
    would be folded into the latter; however, since the "nosharecache" option
    exists this isn't possible.

    The server object key is a sequence consisting of:

    (1) NFS version

    (2) Server address family (eg: AF_INET or AF_INET6)

    (3) Server port.

    (4) Server IP address.

    The key blob is of variable length, depending on the length of (4).

    The server object is given no coherency data to carry in the auxiliary data
    permitted by the cache.

    Signed-off-by: David Howells
    Acked-by: Steve Dickson
    Acked-by: Trond Myklebust
    Acked-by: Al Viro
    Tested-by: Daire Byrne

    David Howells