4.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> commit 9da6ec7775d2cd76df53fbf4f1f35f6d490204f5 upstream. Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> Reviewed-by: Pavel Shilovsky <pshilov@xxxxxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/cifs/cifsglob.h | 1 + fs/cifs/smb2inode.c | 4 +++- fs/cifs/smb2ops.c | 31 ++++++++++++++++++++++++++----- fs/cifs/smb2proto.h | 1 + 4 files changed, 31 insertions(+), 6 deletions(-) --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -913,6 +913,7 @@ cap_unix(struct cifs_ses *ses) struct cached_fid { bool is_valid:1; /* Do we have a useable root fid */ + struct kref refcount; struct cifs_fid *fid; struct mutex fid_mutex; struct cifs_tcon *tcon; --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -120,7 +120,9 @@ smb2_open_op_close(const unsigned int xi break; } - if (use_cached_root_handle == false) + if (use_cached_root_handle) + close_shroot(&tcon->crfid); + else rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); if (tmprc) rc = tmprc; --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -466,21 +466,36 @@ out: return rc; } -void -smb2_cached_lease_break(struct work_struct *work) +static void +smb2_close_cached_fid(struct kref *ref) { - struct cached_fid *cfid = container_of(work, - struct cached_fid, lease_break); - mutex_lock(&cfid->fid_mutex); + struct cached_fid *cfid = container_of(ref, struct cached_fid, + refcount); + if (cfid->is_valid) { cifs_dbg(FYI, "clear cached root file handle\n"); SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid, cfid->fid->volatile_fid); cfid->is_valid = false; } +} + +void close_shroot(struct cached_fid *cfid) +{ + mutex_lock(&cfid->fid_mutex); + kref_put(&cfid->refcount, smb2_close_cached_fid); mutex_unlock(&cfid->fid_mutex); } +void +smb2_cached_lease_break(struct work_struct *work) +{ + struct cached_fid *cfid = container_of(work, + struct cached_fid, lease_break); + + close_shroot(cfid); +} + /* * Open the directory at the root of a share */ @@ -495,6 +510,7 @@ int open_shroot(unsigned int xid, struct if (tcon->crfid.is_valid) { cifs_dbg(FYI, "found a cached root file handle\n"); memcpy(pfid, tcon->crfid.fid, sizeof(struct cifs_fid)); + kref_get(&tcon->crfid.refcount); mutex_unlock(&tcon->crfid.fid_mutex); return 0; } @@ -511,6 +527,8 @@ int open_shroot(unsigned int xid, struct memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid)); tcon->crfid.tcon = tcon; tcon->crfid.is_valid = true; + kref_init(&tcon->crfid.refcount); + kref_get(&tcon->crfid.refcount); } mutex_unlock(&tcon->crfid.fid_mutex); return rc; @@ -552,6 +570,9 @@ smb3_qfs_tcon(const unsigned int xid, st FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */ if (no_cached_open) SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); + else + close_shroot(&tcon->crfid); + return; } --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -68,6 +68,7 @@ extern int smb3_handle_read_data(struct extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid); +extern void close_shroot(struct cached_fid *cfid); extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src); extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,