• Ronnie Sahlberg's avatar
    cifs: enable caching of directories for which a lease is held · ebe98f14
    Ronnie Sahlberg authored
    This expands the directory caching to now cache an open handle for all
    directories (up to a maximum) and not just the root directory.
    
    In this patch, locking and refcounting is intended to work as so:
    
    The main function to get a reference to a cached handle is
    find_or_create_cached_dir() called from open_cached_dir()
    These functions are protected under the cfid_list_lock spin-lock
    to make sure we do not race creating new references for cached dirs
    with deletion of expired ones.
    
    An successful open_cached_dir() will take out 2 references to the cfid if
    this was the very first and successful call to open the directory and
    it acquired a lease from the server.
    One reference is for the lease  and the other is for the cfid that we
    return. The is lease reference is tracked by cfid->has_lease.
    If the directory already has a handle with an active lease, then we just
    take out one new reference for the cfid and return it.
    It can happen that we have a thread that tries to open a cached directory
    where we have a cfid already but we do not, yet, have a working lease. In
    this case we will just return NULL, and this the caller will fall back to
    the case when no handle was available.
    
    In this model the total number of references we have on a cfid is
    1 for while the handle is open and we have a lease, and one additional
    reference for each open instance of a cfid.
    
    Once we get a lease break (cached_dir_lease_break()) we remove the
    cfid from the list under the spinlock. This prevents any new threads to
    use it, and we also call smb2_cached_lease_break() via the work_queue
    in order to drop the reference we got for the lease (we drop it outside
    of the spin-lock.)
    Anytime a thread calls close_cached_dir() we also drop a reference to the
    cfid.
    When the last reference to the cfid is released smb2_close_cached_fid()
    will be invoked which will drop the reference ot the dentry we held for
    this cfid and it will also, if we the handle is open/has a lease
    also call SMB2_close() to close the handle on the server.
    
    Two events require special handling:
    invalidate_all_cached_dirs() this function is called from SMB2_tdis()
    and cifs_mark_open_files_invalid().
    In both cases the tcon is either gone already or will be shortly so
    we do not need to actually close the handles. They will be dropped
    server side as part of the tcon dropping.
    But we have to be careful about a potential race with a concurrent
    lease break so we need to take out additional refences to avoid the
    cfid from being freed while we are still referencing it.
    
    free_cached_dirs() which is called from tconInfoFree().
    This is called quite late in the umount process so there should no longer
    be any open handles or files and we can just free all the remaining data.
    Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
    Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
    ebe98f14
inode.c 82.1 KB