1. 03 5月, 2016 5 次提交
    • A
      parallel lookups: actual switch to rwsem · 9902af79
      Al Viro 提交于
      ta-da!
      
      The main issue is the lack of down_write_killable(), so the places
      like readdir.c switched to plain inode_lock(); once killable
      variants of rwsem primitives appear, that'll be dealt with.
      
      lockdep side also might need more work
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      9902af79
    • A
      parallel lookups machinery, part 4 (and last) · d9171b93
      Al Viro 提交于
      If we *do* run into an in-lookup match, we need to wait for it to
      cease being in-lookup.  Fortunately, we do have unused space in
      in-lookup dentries - d_lru is never looked at until it stops being
      in-lookup.
      
      So we can stash a pointer to wait_queue_head from stack frame of
      the caller of ->lookup().  Some precautions are needed while
      waiting, but it's not that hard - we do hold a reference to dentry
      we are waiting for, so it can't go away.  If it's found to be
      in-lookup the wait_queue_head is still alive and will remain so
      at least while ->d_lock is held.  Moreover, the condition we
      are waiting for becomes true at the same point where everything
      on that wq gets woken up, so we can just add ourselves to the
      queue once.
      
      d_alloc_parallel() gets a pointer to wait_queue_head_t from its
      caller; lookup_slow() adjusted, d_add_ci() taught to use
      d_alloc_parallel() if the dentry passed to it happens to be
      in-lookup one (i.e. if it's been called from the parallel lookup).
      
      That's pretty much it - all that remains is to switch ->i_mutex
      to rwsem and have lookup_slow() take it shared.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      d9171b93
    • A
      parallel lookups machinery, part 3 · 94bdd655
      Al Viro 提交于
      We will need to be able to check if there is an in-lookup
      dentry with matching parent/name.  Right now it's impossible,
      but as soon as start locking directories shared such beasts
      will appear.
      
      Add a secondary hash for locating those.  Hash chains go through
      the same space where d_alias will be once it's not in-lookup anymore.
      Search is done under the same bitlock we use for modifications -
      with the primary hash we can rely on d_rehash() into the wrong
      chain being the worst that could happen, but here the pointers are
      buggered once it's removed from the chain.  On the other hand,
      the chains are not going to be long and normally we'll end up
      adding to the chain anyway.  That allows us to avoid bothering with
      ->d_lock when doing the comparisons - everything is stable until
      removed from chain.
      
      New helper: d_alloc_parallel().  Right now it allocates, verifies
      that no hashed and in-lookup matches exist and adds to in-lookup
      hash.
      
      Returns ERR_PTR() for error, hashed match (in the unlikely case it's
      been found) or new dentry.  In-lookup matches trigger BUG() for
      now; that will change in the next commit when we introduce waiting
      for ongoing lookup to finish.  Note that in-lookup matches won't be
      possible until we actually go for shared locking.
      
      lookup_slow() switched to use of d_alloc_parallel().
      
      Again, these commits are separated only for making it easier to
      review.  All this machinery will start doing something useful only
      when we go for shared locking; it's just that the combination is
      too large for my taste.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      94bdd655
    • A
      beginning of transition to parallel lookups - marking in-lookup dentries · 85c7f810
      Al Viro 提交于
      marked as such when (would be) parallel lookup is about to pass them
      to actual ->lookup(); unmarked when
      	* __d_add() is about to make it hashed, positive or not.
      	* __d_move() (from d_splice_alias(), directly or via
      __d_unalias()) puts a preexisting dentry in its place
      	* in caller of ->lookup() if it has escaped all of the
      above.  Bug (WARN_ON, actually) if it reaches the final dput()
      or d_instantiate() while still marked such.
      
      As the result, we are guaranteed that for as long as the flag is
      set, dentry will
      	* remain negative unhashed with positive refcount
      	* never have its ->d_alias looked at
      	* never have its ->d_lru looked at
      	* never have its ->d_parent and ->d_name changed
      
      Right now we have at most one such for any given parent directory.
      With parallel lookups that restriction will weaken to
      	* only exist when parent is locked shared
      	* at most one with given (parent,name) pair (comparison of
      names is according to ->d_compare())
      	* only exist when there's no hashed dentry with the same
      (parent,name)
      
      Transition will take the next several commits; unfortunately, we'll
      only be able to switch to rwsem at the end of this series.  The
      reason for not making it a single patch is to simplify review.
      
      New primitives: d_in_lookup() (a predicate checking if dentry is in
      the in-lookup state) and d_lookup_done() (tells the system that
      we are done with lookup and if it's still marked as in-lookup, it
      should cease to be such).
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      85c7f810
    • A
      1936386e
  2. 11 4月, 2016 1 次提交
  3. 31 3月, 2016 2 次提交
  4. 14 3月, 2016 7 次提交
  5. 06 3月, 2016 2 次提交
  6. 28 2月, 2016 4 次提交
  7. 23 1月, 2016 1 次提交
    • A
      wrappers for ->i_mutex access · 5955102c
      Al Viro 提交于
      parallel to mutex_{lock,unlock,trylock,is_locked,lock_nested},
      inode_foo(inode) being mutex_foo(&inode->i_mutex).
      
      Please, use those for access to ->i_mutex; over the coming cycle
      ->i_mutex will become rwsem, with ->lookup() done with it held
      only shared.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      5955102c
  8. 09 1月, 2016 1 次提交
    • N
      nfsd: don't hold i_mutex over userspace upcalls · bbddca8e
      NeilBrown 提交于
      We need information about exports when crossing mountpoints during
      lookup or NFSv4 readdir.  If we don't already have that information
      cached, we may have to ask (and wait for) rpc.mountd.
      
      In both cases we currently hold the i_mutex on the parent of the
      directory we're asking rpc.mountd about.  We've seen situations where
      rpc.mountd performs some operation on that directory that tries to take
      the i_mutex again, resulting in deadlock.
      
      With some care, we may be able to avoid that in rpc.mountd.  But it
      seems better just to avoid holding a mutex while waiting on userspace.
      
      It appears that lookup_one_len is pretty much the only operation that
      needs the i_mutex.  So we could just drop the i_mutex elsewhere and do
      something like
      
      	mutex_lock()
      	lookup_one_len()
      	mutex_unlock()
      
      In many cases though the lookup would have been cached and not required
      the i_mutex, so it's more efficient to create a lookup_one_len() variant
      that only takes the i_mutex when necessary.
      Signed-off-by: NNeilBrown <neilb@suse.de>
      Signed-off-by: NJ. Bruce Fields <bfields@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      bbddca8e
  9. 04 1月, 2016 1 次提交
  10. 31 12月, 2015 1 次提交
  11. 09 12月, 2015 3 次提交
    • A
      teach page_get_link() to work in RCU mode · d3883d4f
      Al Viro 提交于
      more or less along the lines of Neil's patchset, sans the insanity
      around kmap().
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      d3883d4f
    • A
      replace ->follow_link() with new method that could stay in RCU mode · 6b255391
      Al Viro 提交于
      new method: ->get_link(); replacement of ->follow_link().  The differences
      are:
      	* inode and dentry are passed separately
      	* might be called both in RCU and non-RCU mode;
      the former is indicated by passing it a NULL dentry.
      	* when called that way it isn't allowed to block
      and should return ERR_PTR(-ECHILD) if it needs to be called
      in non-RCU mode.
      
      It's a flagday change - the old method is gone, all in-tree instances
      converted.  Conversion isn't hard; said that, so far very few instances
      do not immediately bail out when called in RCU mode.  That'll change
      in the next commits.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      6b255391
    • A
      don't put symlink bodies in pagecache into highmem · 21fc61c7
      Al Viro 提交于
      kmap() in page_follow_link_light() needed to go - allowing to hold
      an arbitrary number of kmaps for long is a great way to deadlocking
      the system.
      
      new helper (inode_nohighmem(inode)) needs to be used for pagecache
      symlinks inodes; done for all in-tree cases.  page_follow_link_light()
      instrumented to yell about anything missed.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      21fc61c7
  12. 07 12月, 2015 7 次提交
  13. 07 11月, 2015 1 次提交
  14. 28 10月, 2015 1 次提交
    • D
      namei: permit linking with CAP_FOWNER in userns · f2ca3796
      Dirk Steinmetz 提交于
      Attempting to hardlink to an unsafe file (e.g. a setuid binary) from
      within an unprivileged user namespace fails, even if CAP_FOWNER is held
      within the namespace. This may cause various failures, such as a gentoo
      installation within a lxc container failing to build and install specific
      packages.
      
      This change permits hardlinking of files owned by mapped uids, if
      CAP_FOWNER is held for that namespace. Furthermore, it improves consistency
      by using the existing inode_owner_or_capable(), which is aware of
      namespaced capabilities as of 23adbe12 ("fs,userns: Change
      inode_capable to capable_wrt_inode_uidgid").
      Signed-off-by: NDirk Steinmetz <public@rsjtdrjgfuzkfg.com>
      
      This is hitting us in Ubuntu during some dpkg upgrades in containers.
      When upgrading a file dpkg creates a hard link to the old file to back
      it up before overwriting it. When packages upgrade suid files owned by a
      non-root user the link isn't permitted, and the package upgrade fails.
      This patch fixes our problem.
      Tested-by: NSeth Forshee <seth.forshee@canonical.com>
      Signed-off-by: NEric W. Biederman <ebiederm@xmission.com>
      f2ca3796
  15. 11 10月, 2015 1 次提交
    • T
      namei: results of d_is_negative() should be checked after dentry revalidation · daf3761c
      Trond Myklebust 提交于
      Leandro Awa writes:
       "After switching to version 4.1.6, our parallelized and distributed
        workflows now fail consistently with errors of the form:
      
        T34: ./regex.c:39:22: error: config.h: No such file or directory
      
        From our 'git bisect' testing, the following commit appears to be the
        possible cause of the behavior we've been seeing: commit 766c4cbf"
      
      Al Viro says:
       "What happens is that 766c4cbf got the things subtly wrong.
      
        We used to treat d_is_negative() after lookup_fast() as "fall with
        ENOENT".  That was wrong - checking ->d_flags outside of ->d_seq
        protection is unreliable and failing with hard error on what should've
        fallen back to non-RCU pathname resolution is a bug.
      
        Unfortunately, we'd pulled the test too far up and ran afoul of
        another kind of staleness.  The dentry might have been absolutely
        stable from the RCU point of view (and we might be on UP, etc), but
        stale from the remote fs point of view.  If ->d_revalidate() returns
        "it's actually stale", dentry gets thrown away and the original code
        wouldn't even have looked at its ->d_flags.
      
        What we need is to check ->d_flags where 766c4cbf does (prior to
        ->d_seq validation) but only use the result in cases where we do not
        discard this dentry outright"
      Reported-by: NLeandro Awa <lawa@nvidia.com>
      Link: https://bugzilla.kernel.org/show_bug.cgi?id=104911
      Fixes: 766c4cbf ("namei: d_is_negative() should be checked...")
      Tested-by: NLeandro Awa <lawa@nvidia.com>
      Cc: stable@vger.kernel.org # v4.1+
      Signed-off-by: NTrond Myklebust <trond.myklebust@primarydata.com>
      Acked-by: NAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      daf3761c
  16. 29 9月, 2015 1 次提交
  17. 11 9月, 2015 1 次提交