вт, 12 июн. 2018 г. в 21:50, Ronnie Sahlberg <lsahlber@xxxxxxxxxx>: > > Use a read lease for the cached root fid so that we can detect > when the content of the directory changes (via a break) at which time > we close the handle. On next access to the root the handle will be reopened > and cached again. > > Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > --- > fs/cifs/cifsglob.h | 12 +++++++++--- > fs/cifs/cifsproto.h | 1 + > fs/cifs/cifssmb.c | 8 ++++---- > fs/cifs/misc.c | 7 ++++--- > fs/cifs/smb2misc.c | 16 +++++++++++++++- > fs/cifs/smb2ops.c | 32 +++++++++++++++++++++++--------- > 6 files changed, 56 insertions(+), 20 deletions(-) > > diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h > index 1efa2e65bc1a..ff71fbd619bf 100644 > --- a/fs/cifs/cifsglob.h > +++ b/fs/cifs/cifsglob.h > @@ -883,6 +883,14 @@ cap_unix(struct cifs_ses *ses) > return ses->server->vals->cap_unix & ses->capabilities; > } > > +struct cached_fid { > + bool is_valid:1; /* Do we have a useable root fid */ > + struct cifs_fid *fid; > + struct mutex fid_mutex; > + struct cifs_tcon *tcon; > + struct work_struct lease_break; > +}; > + > /* > * there is one of these for each connection to a resource on a particular > * session > @@ -987,9 +995,7 @@ struct cifs_tcon { > struct fscache_cookie *fscache; /* cookie for share */ > #endif > struct list_head pending_opens; /* list of incomplete opens */ > - bool valid_root_fid:1; /* Do we have a useable root fid */ > - struct mutex prfid_mutex; /* prevents reopen race after dead ses*/ > - struct cifs_fid *prfid; /* handle to the directory at top of share */ > + struct cached_fid crfid; /* Cached root fid */ > /* BB add field for back pointer to sb struct(s)? */ > }; > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index e19c27196182..03018be17283 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -548,6 +548,7 @@ enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, > struct cifs_aio_ctx *cifs_aio_ctx_alloc(void); > void cifs_aio_ctx_release(struct kref *refcount); > int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw); > +void smb2_cached_lease_break(struct work_struct *work); > > int cifs_alloc_hash(const char *name, struct crypto_shash **shash, > struct sdesc **sdesc); > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c > index 5aca336642c0..c23cd2c9cc25 100644 > --- a/fs/cifs/cifssmb.c > +++ b/fs/cifs/cifssmb.c > @@ -107,10 +107,10 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) > } > spin_unlock(&tcon->open_file_lock); > > - mutex_lock(&tcon->prfid_mutex); > - tcon->valid_root_fid = false; > - memset(tcon->prfid, 0, sizeof(struct cifs_fid)); > - mutex_unlock(&tcon->prfid_mutex); > + mutex_lock(&tcon->crfid.fid_mutex); > + tcon->crfid.is_valid = false; > + memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid)); > + mutex_unlock(&tcon->crfid.fid_mutex); > > /* > * BB Add call to invalidate_inodes(sb) for all superblocks mounted > diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c > index f90d4ad6624c..0da609cfac95 100644 > --- a/fs/cifs/misc.c > +++ b/fs/cifs/misc.c > @@ -117,8 +117,9 @@ tconInfoAlloc(void) > INIT_LIST_HEAD(&ret_buf->openFileList); > INIT_LIST_HEAD(&ret_buf->tcon_list); > spin_lock_init(&ret_buf->open_file_lock); > - mutex_init(&ret_buf->prfid_mutex); > - ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL); > + mutex_init(&ret_buf->crfid.fid_mutex); > + ret_buf->crfid.fid = kzalloc(sizeof(struct cifs_fid), > + GFP_KERNEL); > #ifdef CONFIG_CIFS_STATS > spin_lock_init(&ret_buf->stat_lock); > #endif > @@ -136,7 +137,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) > atomic_dec(&tconInfoAllocCount); > kfree(buf_to_free->nativeFileSystem); > kzfree(buf_to_free->password); > - kfree(buf_to_free->prfid); > + kfree(buf_to_free->crfid.fid); > kfree(buf_to_free); > } > > diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c > index e2bec47c6845..0de87ca33e2e 100644 > --- a/fs/cifs/smb2misc.c > +++ b/fs/cifs/smb2misc.c > @@ -492,10 +492,11 @@ cifs_ses_oplock_break(struct work_struct *work) > { > struct smb2_lease_break_work *lw = container_of(work, > struct smb2_lease_break_work, lease_break); > - int rc; > + int rc = 0; > > rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key, > lw->lease_state); > + > cifs_dbg(FYI, "Lease release rc %d\n", rc); > cifs_put_tlink(lw->tlink); > kfree(lw); > @@ -561,6 +562,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp, > > open->oplock = lease_state; > } > + > return found; > } > > @@ -603,6 +605,18 @@ smb2_is_valid_lease_break(char *buffer) > return true; > } > spin_unlock(&tcon->open_file_lock); > + > + if (tcon->crfid.is_valid && > + !memcmp(rsp->LeaseKey, > + tcon->crfid.fid->lease_key, > + SMB2_LEASE_KEY_SIZE)) { > + INIT_WORK(&tcon->crfid.lease_break, > + smb2_cached_lease_break); > + queue_work(cifsiod_wq, > + &tcon->crfid.lease_break); > + spin_unlock(&cifs_tcp_ses_lock); > + return true; > + } > } > } > } > diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c > index d1648a9753d0..a6cd0f6c053b 100644 > --- a/fs/cifs/smb2ops.c > +++ b/fs/cifs/smb2ops.c > @@ -323,6 +323,19 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) > } > #endif /* STATS2 */ > > +void > +smb2_cached_lease_break(struct work_struct *work) > +{ > + struct cached_fid *cfid = container_of(work, > + struct cached_fid, lease_break); > + 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; > + } > +} What will prevent another thread to use the cached FID while it is being closed? -- Best regards, Pavel Shilovsky -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html