ср, 27 июн. 2018 г. в 5:39, Pavel Shilovsky <piastryyy@xxxxxxxxx>: > > вт, 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? Sorry, didn't noticed the next version of the patch where this problem was fixed. -- 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