Skip to content

Commit 27b2eaa

Browse files
committed
Merge tag '5.14-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Four CIFS/SMB3 Fixes, all for stable, two relating to deferred close, and one for the 'modefromsid' mount option (when 'idsfromsid' not specified)" * tag '5.14-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: Call close synchronously during unlink/rename/lease break. cifs: Handle race conditions during rename cifs: use the correct max-length for dentry_path_raw() cifs: create sd context must be a multiple of 8
2 parents a83ed22 + 9e99275 commit 27b2eaa

File tree

6 files changed

+80
-33
lines changed

6 files changed

+80
-33
lines changed

fs/cifs/cifsglob.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,11 @@ struct dfs_info3_param {
16111611
int ttl;
16121612
};
16131613

1614+
struct file_list {
1615+
struct list_head list;
1616+
struct cifsFileInfo *cfile;
1617+
};
1618+
16141619
/*
16151620
* common struct for holding inode info when searching for or updating an
16161621
* inode with new info

fs/cifs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
100100
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
101101
pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
102102

103-
s = dentry_path_raw(direntry, page, PAGE_SIZE);
103+
s = dentry_path_raw(direntry, page, PATH_MAX);
104104
if (IS_ERR(s))
105105
return s;
106106
if (!s[1]) // for root we want "", not "/"

fs/cifs/file.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4847,35 +4847,34 @@ void cifs_oplock_break(struct work_struct *work)
48474847
cifs_dbg(VFS, "Push locks rc = %d\n", rc);
48484848

48494849
oplock_break_ack:
4850-
/*
4851-
* releasing stale oplock after recent reconnect of smb session using
4852-
* a now incorrect file handle is not a data integrity issue but do
4853-
* not bother sending an oplock release if session to server still is
4854-
* disconnected since oplock already released by the server
4855-
*/
4856-
if (!cfile->oplock_break_cancelled) {
4857-
rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
4858-
cinode);
4859-
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
4860-
}
48614850
/*
48624851
* When oplock break is received and there are no active
48634852
* file handles but cached, then schedule deferred close immediately.
48644853
* So, new open will not use cached handle.
48654854
*/
48664855
spin_lock(&CIFS_I(inode)->deferred_lock);
48674856
is_deferred = cifs_is_deferred_close(cfile, &dclose);
4857+
spin_unlock(&CIFS_I(inode)->deferred_lock);
48684858
if (is_deferred &&
48694859
cfile->deferred_close_scheduled &&
48704860
delayed_work_pending(&cfile->deferred)) {
4871-
/*
4872-
* If there is no pending work, mod_delayed_work queues new work.
4873-
* So, Increase the ref count to avoid use-after-free.
4874-
*/
4875-
if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
4876-
cifsFileInfo_get(cfile);
4861+
if (cancel_delayed_work(&cfile->deferred)) {
4862+
_cifsFileInfo_put(cfile, false, false);
4863+
goto oplock_break_done;
4864+
}
48774865
}
4878-
spin_unlock(&CIFS_I(inode)->deferred_lock);
4866+
/*
4867+
* releasing stale oplock after recent reconnect of smb session using
4868+
* a now incorrect file handle is not a data integrity issue but do
4869+
* not bother sending an oplock release if session to server still is
4870+
* disconnected since oplock already released by the server
4871+
*/
4872+
if (!cfile->oplock_break_cancelled) {
4873+
rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
4874+
cinode);
4875+
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
4876+
}
4877+
oplock_break_done:
48794878
_cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
48804879
cifs_done_oplock_break(cinode);
48814880
}

fs/cifs/inode.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
16251625
goto unlink_out;
16261626
}
16271627

1628-
cifs_close_all_deferred_files(tcon);
1628+
cifs_close_deferred_file(CIFS_I(inode));
16291629
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
16301630
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
16311631
rc = CIFSPOSIXDelFile(xid, tcon, full_path,
@@ -2084,6 +2084,7 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
20842084
FILE_UNIX_BASIC_INFO *info_buf_target;
20852085
unsigned int xid;
20862086
int rc, tmprc;
2087+
int retry_count = 0;
20872088

20882089
if (flags & ~RENAME_NOREPLACE)
20892090
return -EINVAL;
@@ -2113,10 +2114,24 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
21132114
goto cifs_rename_exit;
21142115
}
21152116

2116-
cifs_close_all_deferred_files(tcon);
2117+
cifs_close_deferred_file(CIFS_I(d_inode(source_dentry)));
2118+
if (d_inode(target_dentry) != NULL)
2119+
cifs_close_deferred_file(CIFS_I(d_inode(target_dentry)));
2120+
21172121
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
21182122
to_name);
21192123

2124+
if (rc == -EACCES) {
2125+
while (retry_count < 3) {
2126+
cifs_close_all_deferred_files(tcon);
2127+
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2128+
to_name);
2129+
if (rc != -EACCES)
2130+
break;
2131+
retry_count++;
2132+
}
2133+
}
2134+
21202135
/*
21212136
* No-replace is the natural behavior for CIFS, so skip unlink hacks.
21222137
*/

fs/cifs/misc.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -723,13 +723,31 @@ void
723723
cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
724724
{
725725
struct cifsFileInfo *cfile = NULL;
726-
struct cifs_deferred_close *dclose;
726+
struct file_list *tmp_list, *tmp_next_list;
727+
struct list_head file_head;
728+
729+
if (cifs_inode == NULL)
730+
return;
727731

732+
INIT_LIST_HEAD(&file_head);
733+
spin_lock(&cifs_inode->open_file_lock);
728734
list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
729-
spin_lock(&cifs_inode->deferred_lock);
730-
if (cifs_is_deferred_close(cfile, &dclose))
731-
mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
732-
spin_unlock(&cifs_inode->deferred_lock);
735+
if (delayed_work_pending(&cfile->deferred)) {
736+
if (cancel_delayed_work(&cfile->deferred)) {
737+
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
738+
if (tmp_list == NULL)
739+
continue;
740+
tmp_list->cfile = cfile;
741+
list_add_tail(&tmp_list->list, &file_head);
742+
}
743+
}
744+
}
745+
spin_unlock(&cifs_inode->open_file_lock);
746+
747+
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
748+
_cifsFileInfo_put(tmp_list->cfile, true, false);
749+
list_del(&tmp_list->list);
750+
kfree(tmp_list);
733751
}
734752
}
735753

@@ -738,20 +756,30 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
738756
{
739757
struct cifsFileInfo *cfile;
740758
struct list_head *tmp;
759+
struct file_list *tmp_list, *tmp_next_list;
760+
struct list_head file_head;
741761

762+
INIT_LIST_HEAD(&file_head);
742763
spin_lock(&tcon->open_file_lock);
743764
list_for_each(tmp, &tcon->openFileList) {
744765
cfile = list_entry(tmp, struct cifsFileInfo, tlist);
745766
if (delayed_work_pending(&cfile->deferred)) {
746-
/*
747-
* If there is no pending work, mod_delayed_work queues new work.
748-
* So, Increase the ref count to avoid use-after-free.
749-
*/
750-
if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
751-
cifsFileInfo_get(cfile);
767+
if (cancel_delayed_work(&cfile->deferred)) {
768+
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
769+
if (tmp_list == NULL)
770+
continue;
771+
tmp_list->cfile = cfile;
772+
list_add_tail(&tmp_list->list, &file_head);
773+
}
752774
}
753775
}
754776
spin_unlock(&tcon->open_file_lock);
777+
778+
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
779+
_cifsFileInfo_put(tmp_list->cfile, true, false);
780+
list_del(&tmp_list->list);
781+
kfree(tmp_list);
782+
}
755783
}
756784

757785
/* parses DFS refferal V3 structure

fs/cifs/smb2pdu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2426,7 +2426,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
24262426
memcpy(aclptr, &acl, sizeof(struct cifs_acl));
24272427

24282428
buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
2429-
*len = ptr - (__u8 *)buf;
2429+
*len = roundup(ptr - (__u8 *)buf, 8);
24302430

24312431
return buf;
24322432
}

0 commit comments

Comments
 (0)