[PATCH 2/9] smb/client: close cached notify handles on closedir
ChenXiaoSong <[email protected]>
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
From: ChenXiaoSong <[email protected]> This patch was split out to make it easier to review. Add storage for a change-notify FID in cifsFileInfo and close it from the directory release path. This gives notify users a per-open lifetime for the extra handle without changing how smb3_notify opens it yet. Signed-off-by: ChenXiaoSong <[email protected]> --- fs/smb/client/cifsglob.h | 4 ++++ fs/smb/client/file.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 99f9e6dca62b..1250518997fb 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1459,6 +1459,10 @@ struct cifsFileInfo { int count; spinlock_t file_info_lock; /* protects four flag/count fields above */ struct mutex fh_mutex; /* prevents reopen race after dead ses*/ + struct mutex notify_fid_mutex; + struct cifs_fid notify_fid; + struct tcon_link *notify_tlink; + bool has_notify_fid:1; struct cifs_search_info srch_inf; struct work_struct oplock_break; /* work for oplock breaks */ struct work_struct put; /* work for the final part of _put */ diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index f1e854f381d9..6cb4068fe06e 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -671,6 +671,7 @@ struct cifsFileInfo *cifs_new_dir_fileinfo(struct file *file, spin_lock_init(&cfile->file_info_lock); mutex_init(&cfile->fh_mutex); + mutex_init(&cfile->notify_fid_mutex); cfile->invalidHandle = true; cfile->tlink = cifs_get_tlink(tlink); @@ -733,6 +734,7 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, INIT_WORK(&cfile->serverclose, serverclose_work); INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close); mutex_init(&cfile->fh_mutex); + mutex_init(&cfile->notify_fid_mutex); spin_lock_init(&cfile->file_info_lock); /* @@ -1548,6 +1550,32 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) } } +static void cifs_close_notify_fid(unsigned int xid, struct cifsFileInfo *cfile) +{ + struct cifs_tcon *tcon; + struct TCP_Server_Info *server; + int rc = 0; + + mutex_lock(&cfile->notify_fid_mutex); + if (!cfile->has_notify_fid) + goto unlock; + + tcon = tlink_tcon(cfile->notify_tlink); + server = tcon->ses->server; + if (server->ops->close_dir) + rc = server->ops->close_dir(xid, tcon, &cfile->notify_fid); + else if (server->ops->close) + rc = server->ops->close(xid, tcon, &cfile->notify_fid); + + cifs_dbg(FYI, "Closing cached notify handle with rc %d\n", rc); + cfile->has_notify_fid = false; + cifs_put_tlink(cfile->notify_tlink); + cfile->notify_tlink = NULL; + +unlock: + mutex_unlock(&cfile->notify_fid_mutex); +} + int cifs_closedir(struct inode *inode, struct file *file) { int rc = 0; @@ -1567,6 +1595,8 @@ int cifs_closedir(struct inode *inode, struct file *file) server = tcon->ses->server; cifs_dbg(FYI, "Freeing private data in close dir\n"); + cifs_close_notify_fid(xid, cfile); + spin_lock(&cfile->file_info_lock); if (server->ops->dir_needs_close(cfile)) { cfile->invalidHandle = true; -- 2.54.0