[PATCH 1/9] smb/client: factor out cifs_new_dir_fileinfo()

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.

Both readdir and notify can need directory private data before a
search handle exists. Move the common cifsFileInfo allocation and
initialization into a helper so those paths share the same setup.

Signed-off-by: ChenXiaoSong <[email protected]>
---
 fs/smb/client/cifsproto.h |  2 ++
 fs/smb/client/file.c      | 24 ++++++++++++++++++++++++
 fs/smb/client/readdir.c   | 14 ++++++--------
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index c4ababcb51a3..dfbad6bc0a9b 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -267,6 +267,8 @@ void cifs_close_all_deferred_files(struct cifs_tcon *tcon);
 void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb);
 void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
 					   struct dentry *dentry);
+struct cifsFileInfo *cifs_new_dir_fileinfo(struct file *file,
+					   struct tcon_link *tlink);
 
 void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
 					     const char *path);
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 8b25d6c9ec5e..f1e854f381d9 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -660,6 +660,30 @@ cifs_down_write(struct rw_semaphore *sem)
 static void cifsFileInfo_put_work(struct work_struct *work);
 void serverclose_work(struct work_struct *work);
 
+struct cifsFileInfo *cifs_new_dir_fileinfo(struct file *file,
+					   struct tcon_link *tlink)
+{
+	struct cifsFileInfo *cfile, *old;
+
+	cfile = kzalloc_obj(struct cifsFileInfo);
+	if (!cfile)
+		return NULL;
+
+	spin_lock_init(&cfile->file_info_lock);
+	mutex_init(&cfile->fh_mutex);
+	cfile->invalidHandle = true;
+	cfile->tlink = cifs_get_tlink(tlink);
+
+	old = cmpxchg(&file->private_data, NULL, cfile);
+	if (old) {
+		cifs_put_tlink(cfile->tlink);
+		kfree(cfile);
+		return old;
+	}
+
+	return cfile;
+}
+
 struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
 				       struct tcon_link *tlink, __u32 oplock,
 				       const char *symlink_target)
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index a50c86bbe60f..f108e719e683 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -355,20 +355,17 @@ _initiate_cifs_search(const unsigned int xid, struct file *file,
 	__u16 search_flags;
 	int rc = 0;
 
-	if (file->private_data == NULL) {
+	if (!file->private_data) {
 		tlink = cifs_sb_tlink(cifs_sb);
 		if (IS_ERR(tlink))
 			return PTR_ERR(tlink);
 
-		cifsFile = kzalloc_obj(struct cifsFileInfo);
-		if (cifsFile == NULL) {
+		cifsFile = cifs_new_dir_fileinfo(file, tlink);
+		if (!cifsFile) {
 			rc = -ENOMEM;
 			goto error_exit;
 		}
-		spin_lock_init(&cifsFile->file_info_lock);
-		file->private_data = cifsFile;
-		cifsFile->tlink = cifs_get_tlink(tlink);
-		tcon = tlink_tcon(tlink);
+		tcon = tlink_tcon(cifsFile->tlink);
 	} else {
 		cifsFile = file->private_data;
 		tcon = tlink_tcon(cifsFile->tlink);
@@ -1125,7 +1122,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 	 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
 	 * '..'. Otherwise we won't be able to notify VFS in case of failure.
 	 */
-	if (file->private_data == NULL) {
+	cifsFile = file->private_data;
+	if (!cifsFile || cifsFile->invalidHandle) {
 		rc = initiate_cifs_search(xid, file, full_path);
 		cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
 		if (rc)
-- 
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.