• N
    NFS: Avoid quadratic search when freeing delegations. · e04bbf6b
    NeilBrown 提交于
    There are three places that walk all delegation for an nfs_client and
    restart whenever they find something interesting - potentially
    resulting in a quadratic search:  If there are 10,000 uninteresting
    delegations followed by 10,000 interesting one, then the code
    skips over 100,000,000 delegations, which can take a noticeable amount
    of time.
    
    Of these nfs_delegation_reap_unclaimed() and
    nfs_reap_expired_delegations() are only called during unusual events:
    a server reboots or reports expired delegations, probably due to a
    network partition.  Optimizing these is not particularly important.
    
    The third, nfs_client_return_marked_delegations(), is called
    periodically via nfs_expire_unreferenced_delegations().  It could
    cause periodic problems on a busy server.
    
    New delegations are added to the end of the list, so if there are
    10,000 open files with delegations, and 10,000 more recently opened files
    that received delegations but are now closed, then
    nfs_client_return_marked_delegations() can take seconds to skip over
    the 10,000 open files 10,000 times.  That is a waste of time.
    
    The avoid this waste a place-holder (an inode) is kept when locks are
    dropped, so that the place can usually be found again after taking
    rcu_readlock().  This place holder ensure that we find the right
    starting point in the list of nfs_servers, and makes is probable that
    we find the right starting point in the list of delegations.
    We might need to occasionally restart at the head of that list.
    
    It might be possible that the place_holder inode could lose its
    delegation separately, and then get a new one using the same (freed
    and then reallocated) 'struct nfs_delegation'.  Were this to happen,
    the new delegation would be at the end of the list and we would miss
    returning some other delegations.  This would have the effect of
    unnecessarily delaying the return of some unused delegations until the
    next time this function is called - typically 90 seconds later.  As
    this is not a correctness issue and is vanishingly unlikely to happen,
    it does not seem worth addressing.
    Signed-off-by: NNeilBrown <neilb@suse.com>
    Signed-off-by: NTrond Myklebust <trond.myklebust@hammerspace.com>
    e04bbf6b
delegation.c 31.8 KB