Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2cca6a7 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French
Browse files

CIFS: Fix persistent handles re-opening on reconnect



openFileList of tcon can be changed while cifs_reopen_file() is called
that can lead to an unexpected behavior when we return to the loop.
Fix this by introducing a temp list for keeping all file handles that
need to be reopen.

Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 166cea4d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1065,6 +1065,7 @@ struct cifsFileInfo {
	kuid_t uid;		/* allows finding which FileInfo structure */
	__u32 pid;		/* process id who opened file */
	struct cifs_fid fid;	/* file id from remote */
	struct list_head rlist; /* reconnect list */
	/* BB add lock scope info here if needed */ ;
	/* lock scope id (0 if none) */
	struct dentry *dentry;
+17 −5
Original line number Diff line number Diff line
@@ -763,19 +763,31 @@ int cifs_close(struct inode *inode, struct file *file)
void
cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
{
	struct cifsFileInfo *open_file = NULL;
	struct cifsFileInfo *open_file;
	struct list_head *tmp;
	struct list_head *tmp1;
	struct list_head tmp_list;

	cifs_dbg(FYI, "Reopen persistent handles");
	INIT_LIST_HEAD(&tmp_list);

	/* list all files open on tree connection, reopen resilient handles  */
	spin_lock(&tcon->open_file_lock);
	list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
	list_for_each(tmp, &tcon->openFileList) {
		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
		if (!open_file->invalidHandle)
			continue;
		cifsFileInfo_get(open_file);
		list_add_tail(&open_file->rlist, &tmp_list);
	}
	spin_unlock(&tcon->open_file_lock);

	list_for_each_safe(tmp, tmp1, &tmp_list) {
		open_file = list_entry(tmp, struct cifsFileInfo, rlist);
		cifs_reopen_file(open_file, false /* do not flush */);
		spin_lock(&tcon->open_file_lock);
		list_del_init(&open_file->rlist);
		cifsFileInfo_put(open_file);
	}
	spin_unlock(&tcon->open_file_lock);
}

int cifs_closedir(struct inode *inode, struct file *file)