1. 02 11月, 2011 1 次提交
    • S
      vfs: add d_prune dentry operation · f0023bc6
      Sage Weil 提交于
      This adds a d_prune dentry operation that is called by the VFS prior to
      pruning (i.e. unhashing and killing) a hashed dentry from the dcache.
      Wrap dentry_lru_del() and use the new _prune() helper in the cases where we
      are about to unhash and kill the dentry.
      
      This will be used by Ceph to maintain a flag indicating whether the
      complete contents of a directory are contained in the dcache, allowing it
      to satisfy lookups and readdir without addition server communication.
      
      Renumber a few DCACHE_* #defines to group DCACHE_OP_PRUNE with the other
      DCACHE_OP_ bits.
      Signed-off-by: NSage Weil <sage@newdream.net>
      Signed-off-by: NChristoph Hellwig <hch@lst.de>
      f0023bc6
  2. 07 8月, 2011 1 次提交
    • L
      vfs: renumber DCACHE_xyz flags, remove some stale ones · 830c0f0e
      Linus Torvalds 提交于
      Gcc tends to generate better code with small integers, including the
      DCACHE_xyz flag tests - so move the common ones to be first in the list.
      Also just remove the unused DCACHE_INOTIFY_PARENT_WATCHED and
      DCACHE_AUTOFS_PENDING values, their users no longer exists in the source
      tree.
      
      And add a "unlikely()" to the DCACHE_OP_COMPARE test, since we want the
      common case to be a nice straight-line fall-through.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      830c0f0e
  3. 04 8月, 2011 1 次提交
  4. 01 8月, 2011 3 次提交
    • D
      VFS: Reorganise shrink_dcache_for_umount_subtree() after demise of dcache_lock · 43c1c9cd
      David Howells 提交于
      Reorganise shrink_dcache_for_umount_subtree() in light of the demise of
      dcache_lock.  Without that dcache_lock, there is no need for the batching of
      removal of dentries from the system under it (we wanted to make intensive use
      of the locked data whilst we held it, but didn't want to hold it for long at a
      time).
      
      This works, provided the preceding patch is correct in its removal of locking
      on dentry->d_lock on the basis that no one should be locking these dentries any
      more as the whole superblock is defunct.
      
      With this patch, the calls to dentry_lru_del() and __d_shrink() are placed at
      the point where each dentry is detached handled.
      
      It is possible that, as an alternative, the batching should still be done -
      but only for dentry_lru_del() of all a dentry's children in one go.  In such a
      case, the batching would be done under dcache_lru_lock.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      43c1c9cd
    • D
      VFS: Remove dentry->d_lock locking from shrink_dcache_for_umount_subtree() · c6627c60
      David Howells 提交于
      Locks of the dcache_lock were replaced by locks of dentry->d_lock in commits
      such as:
      
      	23044507
      	2fd6b7f5
      
      as part of the RCU-based pathwalk changes, despite the fact that the caller
      (shrink_dcache_for_umount()) notes in the banner comment the reasons that
      d_lock is not necessary in these functions:
      
      /*
       * destroy the dentries attached to a superblock on unmounting
       * - we don't need to use dentry->d_lock because:
       *   - the superblock is detached from all mountings and open files, so the
       *     dentry trees will not be rearranged by the VFS
       *   - s_umount is write-locked, so the memory pressure shrinker will ignore
       *     any dentries belonging to this superblock that it comes across
       *   - the filesystem itself is no longer permitted to rearrange the dentries
       *     in this superblock
       */
      
      So remove these locks.  If the locks are actually necessary, then this banner
      comment should be altered instead.
      
      The hash table chains are protected by 1-bit locks in the hash table heads, so
      those shouldn't be a problem.
      
      Note that to make this work, __d_drop() has to be split so that the RCUwalk
      barrier can be avoided.  This causes problems otherwise as it has an assertion
      that dentry->d_lock is locked - but there is no need for that as no one else
      can be trying to access this dentry, except to step over it (and that should
      be handled by d_free(), I think).
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Cc: Nick Piggin <npiggin@kernel.dk>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      c6627c60
    • D
      VFS: Remove detached-dentry counter from shrink_dcache_for_umount_subtree() · 35f40ef0
      David Howells 提交于
      Remove the detached-dentry counter from shrink_dcache_for_umount_subtree() as
      the value it computes is no longer used as of commit
      312d3ca8 which made the nr_dentry counters
      summed per-CPU rather than global atomic.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      35f40ef0
  5. 27 7月, 2011 1 次提交
  6. 22 7月, 2011 1 次提交
  7. 21 7月, 2011 3 次提交
    • A
      Remove dead code in dget_parent() · 86c98e8c
      Al Viro 提交于
      ->d_parent is never NULL...
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      86c98e8c
    • A
    • D
      superblock: introduce per-sb cache shrinker infrastructure · b0d40c92
      Dave Chinner 提交于
      With context based shrinkers, we can implement a per-superblock
      shrinker that shrinks the caches attached to the superblock. We
      currently have global shrinkers for the inode and dentry caches that
      split up into per-superblock operations via a coarse proportioning
      method that does not batch very well.  The global shrinkers also
      have a dependency - dentries pin inodes - so we have to be very
      careful about how we register the global shrinkers so that the
      implicit call order is always correct.
      
      With a per-sb shrinker callout, we can encode this dependency
      directly into the per-sb shrinker, hence avoiding the need for
      strictly ordering shrinker registrations. We also have no need for
      any proportioning code for the shrinker subsystem already provides
      this functionality across all shrinkers. Allowing the shrinker to
      operate on a single superblock at a time means that we do less
      superblock list traversals and locking and reclaim should batch more
      effectively. This should result in less CPU overhead for reclaim and
      potentially faster reclaim of items from each filesystem.
      Signed-off-by: NDave Chinner <dchinner@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      b0d40c92
  8. 20 7月, 2011 3 次提交
    • A
      make d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err) · a9049376
      Al Viro 提交于
      ... and simplify the living hell out of callers
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      a9049376
    • A
      Make ->d_sb assign-once and always non-NULL · a4464dbc
      Al Viro 提交于
      New helper (non-exported, fs/internal.h-only): __d_alloc(sb, name).
      Allocates dentry, sets its ->d_sb to given superblock and sets
      ->d_op accordingly.  Old d_alloc(NULL, name) callers are converted
      to that (all of them know what superblock they want).  d_alloc()
      itself is left only for parent != NULl case; uses __d_alloc(),
      inserts result into the list of parent's children.
      
      Note that now ->d_sb is assign-once and never NULL *and*
      ->d_parent is never NULL either.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      a4464dbc
    • J
      fs: add a DCACHE_NEED_LOOKUP flag for d_flags · 44396f4b
      Josef Bacik 提交于
      Btrfs (and I'd venture most other fs's) stores its indexes in nice disk order
      for readdir, but unfortunately in the case of anything that stats the files in
      order that readdir spits back (like oh say ls) that means we still have to do
      the normal lookup of the file, which means looking up our other index and then
      looking up the inode.  What I want is a way to create dummy dentries when we
      find them in readdir so that when ls or anything else subsequently does a
      stat(), we already have the location information in the dentry and can go
      straight to the inode itself.  The lookup stuff just assumes that if it finds a
      dentry it is done, it doesn't perform a lookup.  So add a DCACHE_NEED_LOOKUP
      flag so that the lookup code knows it still needs to run i_op->lookup() on the
      parent to get the inode for the dentry.  I have tested this with btrfs and I
      went from something that looks like this
      
      http://people.redhat.com/jwhiter/ls-noreada.png
      
      To this
      
      http://people.redhat.com/jwhiter/ls-good.png
      
      Thats a savings of 1300 seconds, or 22 minutes.  That is a significant savings.
      Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      44396f4b
  9. 15 7月, 2011 1 次提交
    • A
      fix loop checks in d_materialise_unique() · 18367501
      Al Viro 提交于
      Both __d_unalias() and __d_materialise_dentry() need loop prevention.
      Grab rename_lock in caller, check for loops there...
      
      As a side benefit, we have dentry_lock_for_move() called only under
      rename_lock, which seriously reduces deadlock potential of the
      execrable "locking order" used for ->d_lock.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      18367501
  10. 25 5月, 2011 1 次提交
  11. 21 5月, 2011 1 次提交
    • L
      sanitize <linux/prefetch.h> usage · 268bb0ce
      Linus Torvalds 提交于
      Commit e66eed65 ("list: remove prefetching from regular list
      iterators") removed the include of prefetch.h from list.h, which
      uncovered several cases that had apparently relied on that rather
      obscure header file dependency.
      
      So this fixes things up a bit, using
      
         grep -L linux/prefetch.h $(git grep -l '[^a-z_]prefetchw*(' -- '*.[ch]')
         grep -L 'prefetchw*(' $(git grep -l 'linux/prefetch.h' -- '*.[ch]')
      
      to guide us in finding files that either need <linux/prefetch.h>
      inclusion, or have it despite not needing it.
      
      There are more of them around (mostly network drivers), but this gets
      many core ones.
      Reported-by: NStephen Rothwell <sfr@canb.auug.org.au>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      268bb0ce
  12. 26 4月, 2011 1 次提交
  13. 24 4月, 2011 2 次提交
    • L
      vfs: get rid of insane dentry hashing rules · dea3667b
      Linus Torvalds 提交于
      The dentry hashing rules have been really quite complicated for a long
      while, in odd ways.  That made functions like __d_drop() very fragile
      and non-obvious.
      
      In particular, whether a dentry was hashed or not was indicated with an
      explicit DCACHE_UNHASHED bit.  That's despite the fact that the hash
      abstraction that the dentries use actually have a 'is this entry hashed
      or not' model (which is a simple test of the 'pprev' pointer).
      
      The reason that was done is because we used the normal 'is this entry
      unhashed' model to mark whether the dentry had _ever_ been hashed in the
      dentry hash tables, and that logic goes back many years (commit
      b3423415: "dcache: avoid RCU for never-hashed dentries").
      
      That, in turn, meant that __d_drop had totally different unhashing logic
      for the dentry hash table case and for the anonymous dcache case,
      because in order to use the "is this dentry hashed" logic as a flag for
      whether it had ever been on the RCU hash table, we had to unhash such a
      dentry differently so that we'd never think that it wasn't 'unhashed'
      and wouldn't be free'd correctly.
      
      That's just insane.  It made the logic really hard to follow, when there
      were two different kinds of "unhashed" states, and one of them (the one
      that used "list_bl_unhashed()") really had nothing at all to do with
      being unhashed per se, but with a very subtle lifetime rule instead.
      
      So turn all of it around, and make it logical.
      
      Instead of having a DENTRY_UNHASHED bit in d_flags to indicate whether
      the dentry is on the hash chains or not, use the hash chain unhashed
      logic for that.  Suddenly "d_unhashed()" just uses "list_bl_unhashed()",
      and everything makes sense.
      
      And for the lifetime rule, just use an explicit DENTRY_RCUACCEES bit.
      If we ever insert the dentry into the dentry hash table so that it is
      visible to RCU lookup, we mark it DENTRY_RCUACCESS to show that it now
      needs the RCU lifetime rules.  Now suddently that test at dentry free
      time makes sense too.
      
      And because unhashing now is sane and doesn't depend on where the dentry
      got unhashed from (because the dentry hash chain details doesn't have
      some subtle side effects), we can re-unify the __d_drop() logic and use
      common code for the unhashing.
      
      Also fix one more open-coded hash chain bit_spin_lock() that I missed in
      the previous chain locking cleanup commit.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      dea3667b
    • L
      vfs: get rid of 'struct dcache_hash_bucket' abstraction · b07ad996
      Linus Torvalds 提交于
      It's a useless abstraction for 'hlist_bl_head', and it doesn't actually
      help anything - quite the reverse.  All the users end up having to know
      about the hlist_bl_head details anyway, using 'struct hlist_bl_node *'
      etc. So it just makes the code look confusing.
      
      And the cost of it is extra '&b->head' syntactic noise, but more
      importantly it spuriously makes the hash table dentry list look
      different from the per-superblock DCACHE_DISCONNECTED dentry list.
      
      As a result, the code ended up using ad-hoc locking for one case and
      special helper functions for what is really another totally identical
      case in the very same function.
      
      Make it all look and work the same.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      b07ad996
  14. 15 4月, 2011 1 次提交
    • L
      vfs: fix incorrect dentry_update_name_case() BUG_ON() test · 7ebfa57f
      Linus Torvalds 提交于
      The case we should be verifying when updating the dentry name is that
      the _parent_ inode (the directory) semaphore is held, not the semaphore
      for the dentry itself.  It's the directory locking that rename and
      readdir() etc all care about.
      
      The comment just above even says so - but then the BUG_ON() still
      checked the dentry inode itself.
      
      Very few people noticed, because this helper function really isn't used
      for very much, so you had to be using ncpfs to ever hit it.
      
      I think I should just remove the BUG_ON (the function really has just
      one user), but let's run with it fixed for a while before getting rid of
      it entirely.
      Reported-and-tested-by: NBongani Hlope <bonganih@bankservafrica.com>
      Reported-and-tested-by: NBernd Feige <bernd.feige@uniklinik-freiburg.de>
      Cc: Petr Vandrovec <petr@vandrovec.name>,
      Cc: Arnd Bergmann <arnd@arndb.de>
      Cc: Christoph Hellwig <hch@lst.de>
      Cc: Nick Piggin <npiggin@kernel.dk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      7ebfa57f
  15. 18 3月, 2011 1 次提交
    • J
      fs: call security_d_instantiate in d_obtain_alias V2 · 24ff6663
      Josef Bacik 提交于
      While trying to track down some NFS problems with BTRFS, I kept noticing I was
      getting -EACCESS for no apparent reason.  Eric Paris and printk() helped me
      figure out that it was SELinux that was giving me grief, with the following
      denial
      
      type=AVC msg=audit(1290013638.413:95): avc:  denied  { 0x800000 } for  pid=1772
      comm="nfsd" name="" dev=sda1 ino=256 scontext=system_u:system_r:kernel_t:s0
      tcontext=system_u:object_r:unlabeled_t:s0 tclass=file
      
      Turns out this is because in d_obtain_alias if we can't find an alias we create
      one and do all the normal instantiation stuff, but we don't do the
      security_d_instantiate.
      
      Usually we are protected from getting a hashed dentry that hasn't yet run
      security_d_instantiate() by the parent's i_mutex, but obviously this isn't an
      option there, so in order to deal with the case that a second thread comes in
      and finds our new dentry before we get to run security_d_instantiate(), we go
      ahead and call it if we find a dentry already.  Eric assures me that this is ok
      as the code checks to see if the dentry has been initialized already so calling
      security_d_instantiate() against the same dentry multiple times is ok.  With
      this patch I'm no longer getting errant -EACCESS values.
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      24ff6663
  16. 16 3月, 2011 2 次提交
    • T
      VFS: Fix the nfs sillyrename regression in kernel 2.6.38 · c83ce989
      Trond Myklebust 提交于
      The new vfs locking scheme introduced in 2.6.38 breaks NFS sillyrename
      because the latter relies on being able to determine the parent
      directory of the dentry in the ->iput() callback in order to send the
      appropriate unlink rpc call.
      
      Looking at the code that cares about races with dput(), there doesn't
      seem to be anything that specifically uses d_parent as a test for
      whether or not there is a race:
        - __d_lookup_rcu(), __d_lookup() all test for d_hashed() after d_parent
        - shrink_dcache_for_umount() is safe since nothing else can rearrange
          the dentries in that super block.
        - have_submount(), select_parent() and d_genocide() can test for a
          deletion if we set the DCACHE_DISCONNECTED flag when the dentry
          is removed from the parent's d_subdirs list.
      Signed-off-by: NTrond Myklebust <Trond.Myklebust@netapp.com>
      Cc: stable@kernel.org (2.6.38, needs commit c826cb7d "dcache.c:
      	create helper function for duplicated functionality" )
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      c83ce989
    • L
      dcache.c: create helper function for duplicated functionality · c826cb7d
      Linus Torvalds 提交于
      This creates a helper function for he "try to ascend into the parent
      directory" case, which was written out in triplicate before.  With all
      the locking and subtle sequence number stuff, we really don't want to
      duplicate that kind of code.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      c826cb7d
  17. 10 3月, 2011 1 次提交
    • J
      fs/dcache: allow d_obtain_alias() to return unhashed dentries · d891eedb
      J. Bruce Fields 提交于
      Without this patch, inodes are not promptly freed on last close of an
      unlinked file by an nfs client:
      
      	client$ mount -tnfs4 server:/export/ /mnt/
      	client$ tail -f /mnt/FOO
      	...
      	server$ df -i /export
      	server$ rm /export/FOO
      	(^C the tail -f)
      	server$ df -i /export
      	server$ echo 2 >/proc/sys/vm/drop_caches
      	server$ df -i /export
      
      the df's will show that the inode is not freed on the filesystem until
      the last step, when it could have been freed after killing the client's
      tail -f. On-disk data won't be deallocated either, leading to possible
      spurious ENOSPC.
      
      This occurs because when the client does the close, it arrives in a
      compound with a putfh and a close, processed like:
      
      	- putfh: look up the filehandle.  The only alias found for the
      	  inode will be DCACHE_UNHASHED alias referenced by the filp
      	  this, so it creates a new DCACHE_DISCONECTED dentry and
      	  returns that instead.
      	- close: closes the existing filp, which is destroyed
      	  immediately by dput() since it's DCACHE_UNHASHED.
      	- end of the compound: release the reference
      	  to the current filehandle, and dput() the new
      	  DCACHE_DISCONECTED dentry, which gets put on the
      	  unused list instead of being destroyed immediately.
      
      Nick Piggin suggested fixing this by allowing d_obtain_alias to return
      the unhashed dentry that is referenced by the filp, instead of making it
      create a new dentry.
      
      Leave __d_find_alias() alone to avoid changing behavior of other
      callers.
      
      Also nfsd doesn't need all the checks of __d_find_alias(); any dentry,
      hashed or unhashed, disconnected or not, should work.
      Signed-off-by: NJ. Bruce Fields <bfields@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      d891eedb
  18. 17 2月, 2011 1 次提交
  19. 23 1月, 2011 1 次提交
  20. 16 1月, 2011 1 次提交
    • D
      Add a dentry op to handle automounting rather than abusing follow_link() · 9875cf80
      David Howells 提交于
      Add a dentry op (d_automount) to handle automounting directories rather than
      abusing the follow_link() inode operation.  The operation is keyed off a new
      dentry flag (DCACHE_NEED_AUTOMOUNT).
      
      This also makes it easier to add an AT_ flag to suppress terminal segment
      automount during pathwalk and removes the need for the kludge code in the
      pathwalk algorithm to handle directories with follow_link() semantics.
      
      The ->d_automount() dentry operation:
      
      	struct vfsmount *(*d_automount)(struct path *mountpoint);
      
      takes a pointer to the directory to be mounted upon, which is expected to
      provide sufficient data to determine what should be mounted.  If successful, it
      should return the vfsmount struct it creates (which it should also have added
      to the namespace using do_add_mount() or similar).  If there's a collision with
      another automount attempt, NULL should be returned.  If the directory specified
      by the parameter should be used directly rather than being mounted upon,
      -EISDIR should be returned.  In any other case, an error code should be
      returned.
      
      The ->d_automount() operation is called with no locks held and may sleep.  At
      this point the pathwalk algorithm will be in ref-walk mode.
      
      Within fs/namei.c itself, a new pathwalk subroutine (follow_automount()) is
      added to handle mountpoints.  It will return -EREMOTE if the automount flag was
      set, but no d_automount() op was supplied, -ELOOP if we've encountered too many
      symlinks or mountpoints, -EISDIR if the walk point should be used without
      mounting and 0 if successful.  The path will be updated to point to the mounted
      filesystem if a successful automount took place.
      
      __follow_mount() is replaced by follow_managed() which is more generic
      (especially with the patch that adds ->d_manage()).  This handles transits from
      directories during pathwalk, including automounting and skipping over
      mountpoints (and holding processes with the next patch).
      
      __follow_mount_rcu() will jump out of RCU-walk mode if it encounters an
      automount point with nothing mounted on it.
      
      follow_dotdot*() does not handle automounts as you don't want to trigger them
      whilst following "..".
      
      I've also extracted the mount/don't-mount logic from autofs4 and included it
      here.  It makes the mount go ahead anyway if someone calls open() or creat(),
      tries to traverse the directory, tries to chdir/chroot/etc. into the directory,
      or sticks a '/' on the end of the pathname.  If they do a stat(), however,
      they'll only trigger the automount if they didn't also say O_NOFOLLOW.
      
      I've also added an inode flag (S_AUTOMOUNT) so that filesystems can mark their
      inodes as automount points.  This flag is automatically propagated to the
      dentry as DCACHE_NEED_AUTOMOUNT by __d_instantiate().  This saves NFS and could
      save AFS a private flag bit apiece, but is not strictly necessary.  It would be
      preferable to do the propagation in d_set_d_op(), but that doesn't normally
      have access to the inode.
      
      [AV: fixed breakage in case if __follow_mount_rcu() fails and nameidata_drop_rcu()
      succeeds in RCU case of do_lookup(); we need to fall through to non-RCU case after
      that, rather than just returning with ungrabbed *path]
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Was-Acked-by: NIan Kent <raven@themaw.net>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      9875cf80
  21. 15 1月, 2011 1 次提交
  22. 13 1月, 2011 3 次提交
  23. 07 1月, 2011 8 次提交
    • N
      fs: implement faster dentry memcmp · 9d55c369
      Nick Piggin 提交于
      The standard memcmp function on a Westmere system shows up hot in
      profiles in the `git diff` workload (both parallel and single threaded),
      and it is likely due to the costs associated with trapping into
      microcode, and little opportunity to improve memory access (dentry
      name is not likely to take up more than a cacheline).
      
      So replace it with an open-coded byte comparison. This increases code
      size by 8 bytes in the critical __d_lookup_rcu function, but the
      speedup is huge, averaging 10 runs of each:
      
      git diff st   user   sys   elapsed  CPU
      before        1.15   2.57  3.82      97.1
      after         1.14   2.35  3.61      96.8
      
      git diff mt   user   sys   elapsed  CPU
      before        1.27   3.85  1.46     349
      after         1.26   3.54  1.43     333
      
      Elapsed time for single threaded git diff at 95.0% confidence:
              -0.21  +/- 0.01
              -5.45% +/- 0.24%
      
      It's -0.66% +/- 0.06% elapsed time on my Opteron, so rep cmp costs on the
      fam10h seem to be relatively smaller, but there is still a win.
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      9d55c369
    • N
      fs: prefetch inode data in dcache lookup · e1bb5782
      Nick Piggin 提交于
      This makes single threaded git diff -1.25% +/- 0.05% elapsed time on my
      2s12c24t Westmere system, and -0.86% +/- 0.05% on my 2s8c Barcelona, by
      prefetching the important first cacheline of the inode in while we do the
      actual name compare and other operations on the dentry.
      
      There was no measurable slowdown in the single file stat case, or the creat
      case (where negative dentries would be common).
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      e1bb5782
    • N
      fs: improve scalability of pseudo filesystems · 4b936885
      Nick Piggin 提交于
      Regardless of how much we possibly try to scale dcache, there is likely
      always going to be some fundamental contention when adding or removing children
      under the same parent. Pseudo filesystems do not seem need to have connected
      dentries because by definition they are disconnected.
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      4b936885
    • N
      fs: dcache per-inode inode alias locking · 873feea0
      Nick Piggin 提交于
      dcache_inode_lock can be replaced with per-inode locking. Use existing
      inode->i_lock for this. This is slightly non-trivial because we sometimes
      need to find the inode from the dentry, which requires d_inode to be
      stabilised (either with refcount or d_lock).
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      873feea0
    • N
      fs: dcache per-bucket dcache hash locking · ceb5bdc2
      Nick Piggin 提交于
      We can turn the dcache hash locking from a global dcache_hash_lock into
      per-bucket locking.
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      ceb5bdc2
    • N
      fs: cache optimise dentry and inode for rcu-walk · 44a7d7a8
      Nick Piggin 提交于
      Put dentry and inode fields into top of data structure.  This allows RCU path
      traversal to perform an RCU dentry lookup in a path walk by touching only the
      first 56 bytes of the dentry.
      
      We also fit in 8 bytes of inline name in the first 64 bytes, so for short
      names, only 64 bytes needs to be touched to perform the lookup. We should
      get rid of the hash->prev pointer from the first 64 bytes, and fit 16 bytes
      of name in there, which will take care of 81% rather than 32% of the kernel
      tree.
      
      inode is also rearranged so that RCU lookup will only touch a single cacheline
      in the inode, plus one in the i_ops structure.
      
      This is important for directory component lookups in RCU path walking. In the
      kernel source, directory names average is around 6 chars, so this works.
      
      When we reach the last element of the lookup, we need to lock it and take its
      refcount which requires another cacheline access.
      
      Align dentry and inode operations structs, so members will be at predictable
      offsets and we can group common operations into head of structure.
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      44a7d7a8
    • N
      fs: dcache reduce branches in lookup path · fb045adb
      Nick Piggin 提交于
      Reduce some branches and memory accesses in dcache lookup by adding dentry
      flags to indicate common d_ops are set, rather than having to check them.
      This saves a pointer memory access (dentry->d_op) in common path lookup
      situations, and saves another pointer load and branch in cases where we
      have d_op but not the particular operation.
      
      Patched with:
      
      git grep -E '[.>]([[:space:]])*d_op([[:space:]])*=' | xargs sed -e 's/\([^\t ]*\)->d_op = \(.*\);/d_set_d_op(\1, \2);/' -e 's/\([^\t ]*\)\.d_op = \(.*\);/d_set_d_op(\&\1, \2);/' -i
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      fb045adb
    • N
      fs: dcache remove d_mounted · 5f57cbcc
      Nick Piggin 提交于
      Rather than keep a d_mounted count in the dentry, set a dentry flag instead.
      The flag can be cleared by checking the hash table to see if there are any
      mounts left, which is not time critical because it is performed at detach time.
      
      The mounted state of a dentry is only used to speculatively take a look in the
      mount hash table if it is set -- before following the mount, vfsmount lock is
      taken and mount re-checked without races.
      
      This saves 4 bytes on 32-bit, nothing on 64-bit but it does provide a hole I
      might use later (and some configs have larger than 32-bit spinlocks which might
      make use of the hole).
      
      Autofs4 conversion and changelog by Ian Kent <raven@themaw.net>:
      In autofs4, when expring direct (or offset) mounts we need to ensure that we
      block user path walks into the autofs mount, which is covered by another mount.
      To do this we clear the mounted status so that follows stop before walking into
      the mount and are essentially blocked until the expire is completed. The
      automount daemon still finds the correct dentry for the umount due to the
      follow mount logic in fs/autofs4/root.c:autofs4_follow_link(), which is set as
      an inode operation for direct and offset mounts only and is called following
      the lookup that stopped at the covered mount.
      
      At the end of the expire the covering mount probably has gone away so the
      mounted status need not be restored. But we need to check this and only restore
      the mounted status if the expire failed.
      
      XXX: autofs may not work right if we have other mounts go over the top of it?
      Signed-off-by: NNick Piggin <npiggin@kernel.dk>
      5f57cbcc