[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.