Skip to content

Commit 26c009d

Browse files
committed
Merge tag '6.4-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: - deferred close fix for an important case when cached file should be closed immediately - two fixes for missing locks - eight minor cleanup * tag '6.4-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module version number for cifs.ko smb3: move some common open context structs to smbfs_common smb3: make query_on_disk_id open context consistent and move to common code SMB3.1.1: add new tree connect ShareFlags cifs: missing lock when updating session status SMB3: Close deferred file handles in case of handle lease break SMB3: Add missing locks to protect deferred close file list cifs: Avoid a cast in add_lease_context() cifs: Simplify SMB2_open_init() cifs: Simplify SMB2_open_init() cifs: Simplify SMB2_open_init()
2 parents ed9a65e + 9be11a6 commit 26c009d

File tree

8 files changed

+109
-151
lines changed

8 files changed

+109
-151
lines changed

fs/cifs/cifsfs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ extern const struct export_operations cifs_export_ops;
162162
#endif /* CONFIG_CIFS_NFSD_EXPORT */
163163

164164
/* when changing internal version - update following two lines at same time */
165-
#define SMB3_PRODUCT_BUILD 41
166-
#define CIFS_VERSION "2.42"
165+
#define SMB3_PRODUCT_BUILD 43
166+
#define CIFS_VERSION "2.43"
167167
#endif /* _CIFSFS_H */

fs/cifs/connect.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,18 +1916,22 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
19161916
/* ses_count can never go negative */
19171917
WARN_ON(ses->ses_count < 0);
19181918

1919+
spin_lock(&ses->ses_lock);
19191920
if (ses->ses_status == SES_GOOD)
19201921
ses->ses_status = SES_EXITING;
19211922

1922-
cifs_free_ipc(ses);
1923-
19241923
if (ses->ses_status == SES_EXITING && server->ops->logoff) {
1924+
spin_unlock(&ses->ses_lock);
1925+
cifs_free_ipc(ses);
19251926
xid = get_xid();
19261927
rc = server->ops->logoff(xid, ses);
19271928
if (rc)
19281929
cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
19291930
__func__, rc);
19301931
_free_xid(xid);
1932+
} else {
1933+
spin_unlock(&ses->ses_lock);
1934+
cifs_free_ipc(ses);
19311935
}
19321936

19331937
spin_lock(&cifs_tcp_ses_lock);

fs/cifs/file.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4882,6 +4882,8 @@ void cifs_oplock_break(struct work_struct *work)
48824882
struct TCP_Server_Info *server = tcon->ses->server;
48834883
int rc = 0;
48844884
bool purge_cache = false;
4885+
struct cifs_deferred_close *dclose;
4886+
bool is_deferred = false;
48854887

48864888
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
48874889
TASK_UNINTERRUPTIBLE);
@@ -4917,6 +4919,20 @@ void cifs_oplock_break(struct work_struct *work)
49174919
cifs_dbg(VFS, "Push locks rc = %d\n", rc);
49184920

49194921
oplock_break_ack:
4922+
/*
4923+
* When oplock break is received and there are no active
4924+
* file handles but cached, then schedule deferred close immediately.
4925+
* So, new open will not use cached handle.
4926+
*/
4927+
spin_lock(&CIFS_I(inode)->deferred_lock);
4928+
is_deferred = cifs_is_deferred_close(cfile, &dclose);
4929+
spin_unlock(&CIFS_I(inode)->deferred_lock);
4930+
4931+
if (!CIFS_CACHE_HANDLE(cinode) && is_deferred &&
4932+
cfile->deferred_close_scheduled && delayed_work_pending(&cfile->deferred)) {
4933+
cifs_close_deferred_file(cinode);
4934+
}
4935+
49204936
/*
49214937
* releasing stale oplock after recent reconnect of smb session using
49224938
* a now incorrect file handle is not a data integrity issue but do

fs/cifs/misc.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,9 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
749749
list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
750750
if (delayed_work_pending(&cfile->deferred)) {
751751
if (cancel_delayed_work(&cfile->deferred)) {
752+
spin_lock(&cifs_inode->deferred_lock);
752753
cifs_del_deferred_close(cfile);
754+
spin_unlock(&cifs_inode->deferred_lock);
753755

754756
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
755757
if (tmp_list == NULL)
@@ -762,7 +764,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
762764
spin_unlock(&cifs_inode->open_file_lock);
763765

764766
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
765-
_cifsFileInfo_put(tmp_list->cfile, true, false);
767+
_cifsFileInfo_put(tmp_list->cfile, false, false);
766768
list_del(&tmp_list->list);
767769
kfree(tmp_list);
768770
}
@@ -780,7 +782,9 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
780782
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
781783
if (delayed_work_pending(&cfile->deferred)) {
782784
if (cancel_delayed_work(&cfile->deferred)) {
785+
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
783786
cifs_del_deferred_close(cfile);
787+
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
784788

785789
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
786790
if (tmp_list == NULL)
@@ -815,7 +819,9 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
815819
if (strstr(full_path, path)) {
816820
if (delayed_work_pending(&cfile->deferred)) {
817821
if (cancel_delayed_work(&cfile->deferred)) {
822+
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
818823
cifs_del_deferred_close(cfile);
824+
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
819825

820826
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
821827
if (tmp_list == NULL)

fs/cifs/smb2pdu.c

Lines changed: 30 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,6 @@ create_posix_buf(umode_t mode)
821821
static int
822822
add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
823823
{
824-
struct smb2_create_req *req = iov[0].iov_base;
825824
unsigned int num = *num_iovec;
826825

827826
iov[num].iov_base = create_posix_buf(mode);
@@ -830,11 +829,6 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
830829
if (iov[num].iov_base == NULL)
831830
return -ENOMEM;
832831
iov[num].iov_len = sizeof(struct create_posix);
833-
if (!req->CreateContextsOffset)
834-
req->CreateContextsOffset = cpu_to_le32(
835-
sizeof(struct smb2_create_req) +
836-
iov[num - 1].iov_len);
837-
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
838832
*num_iovec = num + 1;
839833
return 0;
840834
}
@@ -2069,7 +2063,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
20692063
static void
20702064
parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
20712065
{
2072-
struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc;
2066+
struct create_disk_id_rsp *pdisk_id = (struct create_disk_id_rsp *)cc;
20732067

20742068
cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n",
20752069
pdisk_id->DiskFileId, pdisk_id->VolumeId);
@@ -2172,23 +2166,18 @@ smb2_parse_contexts(struct TCP_Server_Info *server,
21722166
}
21732167

21742168
static int
2175-
add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
2169+
add_lease_context(struct TCP_Server_Info *server,
2170+
struct smb2_create_req *req,
2171+
struct kvec *iov,
21762172
unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
21772173
{
2178-
struct smb2_create_req *req = iov[0].iov_base;
21792174
unsigned int num = *num_iovec;
21802175

21812176
iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
21822177
if (iov[num].iov_base == NULL)
21832178
return -ENOMEM;
21842179
iov[num].iov_len = server->vals->create_lease_size;
21852180
req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
2186-
if (!req->CreateContextsOffset)
2187-
req->CreateContextsOffset = cpu_to_le32(
2188-
sizeof(struct smb2_create_req) +
2189-
iov[num - 1].iov_len);
2190-
le32_add_cpu(&req->CreateContextsLength,
2191-
server->vals->create_lease_size);
21922181
*num_iovec = num + 1;
21932182
return 0;
21942183
}
@@ -2267,18 +2256,12 @@ static int
22672256
add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
22682257
struct cifs_open_parms *oparms)
22692258
{
2270-
struct smb2_create_req *req = iov[0].iov_base;
22712259
unsigned int num = *num_iovec;
22722260

22732261
iov[num].iov_base = create_durable_v2_buf(oparms);
22742262
if (iov[num].iov_base == NULL)
22752263
return -ENOMEM;
22762264
iov[num].iov_len = sizeof(struct create_durable_v2);
2277-
if (!req->CreateContextsOffset)
2278-
req->CreateContextsOffset =
2279-
cpu_to_le32(sizeof(struct smb2_create_req) +
2280-
iov[1].iov_len);
2281-
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
22822265
*num_iovec = num + 1;
22832266
return 0;
22842267
}
@@ -2287,7 +2270,6 @@ static int
22872270
add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
22882271
struct cifs_open_parms *oparms)
22892272
{
2290-
struct smb2_create_req *req = iov[0].iov_base;
22912273
unsigned int num = *num_iovec;
22922274

22932275
/* indicate that we don't need to relock the file */
@@ -2297,12 +2279,6 @@ add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
22972279
if (iov[num].iov_base == NULL)
22982280
return -ENOMEM;
22992281
iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
2300-
if (!req->CreateContextsOffset)
2301-
req->CreateContextsOffset =
2302-
cpu_to_le32(sizeof(struct smb2_create_req) +
2303-
iov[1].iov_len);
2304-
le32_add_cpu(&req->CreateContextsLength,
2305-
sizeof(struct create_durable_handle_reconnect_v2));
23062282
*num_iovec = num + 1;
23072283
return 0;
23082284
}
@@ -2311,7 +2287,6 @@ static int
23112287
add_durable_context(struct kvec *iov, unsigned int *num_iovec,
23122288
struct cifs_open_parms *oparms, bool use_persistent)
23132289
{
2314-
struct smb2_create_req *req = iov[0].iov_base;
23152290
unsigned int num = *num_iovec;
23162291

23172292
if (use_persistent) {
@@ -2331,11 +2306,6 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
23312306
if (iov[num].iov_base == NULL)
23322307
return -ENOMEM;
23332308
iov[num].iov_len = sizeof(struct create_durable);
2334-
if (!req->CreateContextsOffset)
2335-
req->CreateContextsOffset =
2336-
cpu_to_le32(sizeof(struct smb2_create_req) +
2337-
iov[1].iov_len);
2338-
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
23392309
*num_iovec = num + 1;
23402310
return 0;
23412311
}
@@ -2369,18 +2339,12 @@ create_twarp_buf(__u64 timewarp)
23692339
static int
23702340
add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
23712341
{
2372-
struct smb2_create_req *req = iov[0].iov_base;
23732342
unsigned int num = *num_iovec;
23742343

23752344
iov[num].iov_base = create_twarp_buf(timewarp);
23762345
if (iov[num].iov_base == NULL)
23772346
return -ENOMEM;
23782347
iov[num].iov_len = sizeof(struct crt_twarp_ctxt);
2379-
if (!req->CreateContextsOffset)
2380-
req->CreateContextsOffset = cpu_to_le32(
2381-
sizeof(struct smb2_create_req) +
2382-
iov[num - 1].iov_len);
2383-
le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt));
23842348
*num_iovec = num + 1;
23852349
return 0;
23862350
}
@@ -2503,19 +2467,13 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
25032467
static int
25042468
add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
25052469
{
2506-
struct smb2_create_req *req = iov[0].iov_base;
25072470
unsigned int num = *num_iovec;
25082471
unsigned int len = 0;
25092472

25102473
iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
25112474
if (iov[num].iov_base == NULL)
25122475
return -ENOMEM;
25132476
iov[num].iov_len = len;
2514-
if (!req->CreateContextsOffset)
2515-
req->CreateContextsOffset = cpu_to_le32(
2516-
sizeof(struct smb2_create_req) +
2517-
iov[num - 1].iov_len);
2518-
le32_add_cpu(&req->CreateContextsLength, len);
25192477
*num_iovec = num + 1;
25202478
return 0;
25212479
}
@@ -2546,18 +2504,12 @@ create_query_id_buf(void)
25462504
static int
25472505
add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
25482506
{
2549-
struct smb2_create_req *req = iov[0].iov_base;
25502507
unsigned int num = *num_iovec;
25512508

25522509
iov[num].iov_base = create_query_id_buf();
25532510
if (iov[num].iov_base == NULL)
25542511
return -ENOMEM;
25552512
iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
2556-
if (!req->CreateContextsOffset)
2557-
req->CreateContextsOffset = cpu_to_le32(
2558-
sizeof(struct smb2_create_req) +
2559-
iov[num - 1].iov_len);
2560-
le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
25612513
*num_iovec = num + 1;
25622514
return 0;
25632515
}
@@ -2720,6 +2672,9 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
27202672
rc = add_posix_context(iov, &n_iov, mode);
27212673
if (rc)
27222674
goto err_free_req;
2675+
req->CreateContextsOffset = cpu_to_le32(
2676+
sizeof(struct smb2_create_req) +
2677+
iov[1].iov_len);
27232678
pc_buf = iov[n_iov-1].iov_base;
27242679
}
27252680

@@ -2857,49 +2812,27 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
28572812
(oparms->create_options & CREATE_NOT_FILE))
28582813
req->RequestedOplockLevel = *oplock; /* no srv lease support */
28592814
else {
2860-
rc = add_lease_context(server, iov, &n_iov,
2815+
rc = add_lease_context(server, req, iov, &n_iov,
28612816
oparms->fid->lease_key, oplock);
28622817
if (rc)
28632818
return rc;
28642819
}
28652820

28662821
if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
2867-
/* need to set Next field of lease context if we request it */
2868-
if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
2869-
struct create_context *ccontext =
2870-
(struct create_context *)iov[n_iov-1].iov_base;
2871-
ccontext->Next =
2872-
cpu_to_le32(server->vals->create_lease_size);
2873-
}
2874-
28752822
rc = add_durable_context(iov, &n_iov, oparms,
28762823
tcon->use_persistent);
28772824
if (rc)
28782825
return rc;
28792826
}
28802827

28812828
if (tcon->posix_extensions) {
2882-
if (n_iov > 2) {
2883-
struct create_context *ccontext =
2884-
(struct create_context *)iov[n_iov-1].iov_base;
2885-
ccontext->Next =
2886-
cpu_to_le32(iov[n_iov-1].iov_len);
2887-
}
2888-
28892829
rc = add_posix_context(iov, &n_iov, oparms->mode);
28902830
if (rc)
28912831
return rc;
28922832
}
28932833

28942834
if (tcon->snapshot_time) {
28952835
cifs_dbg(FYI, "adding snapshot context\n");
2896-
if (n_iov > 2) {
2897-
struct create_context *ccontext =
2898-
(struct create_context *)iov[n_iov-1].iov_base;
2899-
ccontext->Next =
2900-
cpu_to_le32(iov[n_iov-1].iov_len);
2901-
}
2902-
29032836
rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time);
29042837
if (rc)
29052838
return rc;
@@ -2923,25 +2856,37 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
29232856
set_owner = false;
29242857

29252858
if (set_owner | set_mode) {
2926-
if (n_iov > 2) {
2927-
struct create_context *ccontext =
2928-
(struct create_context *)iov[n_iov-1].iov_base;
2929-
ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
2930-
}
2931-
29322859
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
29332860
rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
29342861
if (rc)
29352862
return rc;
29362863
}
29372864
}
29382865

2866+
add_query_id_context(iov, &n_iov);
2867+
29392868
if (n_iov > 2) {
2940-
struct create_context *ccontext =
2941-
(struct create_context *)iov[n_iov-1].iov_base;
2942-
ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
2869+
/*
2870+
* We have create contexts behind iov[1] (the file
2871+
* name), point at them from the main create request
2872+
*/
2873+
req->CreateContextsOffset = cpu_to_le32(
2874+
sizeof(struct smb2_create_req) +
2875+
iov[1].iov_len);
2876+
req->CreateContextsLength = 0;
2877+
2878+
for (unsigned int i = 2; i < (n_iov-1); i++) {
2879+
struct kvec *v = &iov[i];
2880+
size_t len = v->iov_len;
2881+
struct create_context *cctx =
2882+
(struct create_context *)v->iov_base;
2883+
2884+
cctx->Next = cpu_to_le32(len);
2885+
le32_add_cpu(&req->CreateContextsLength, len);
2886+
}
2887+
le32_add_cpu(&req->CreateContextsLength,
2888+
iov[n_iov-1].iov_len);
29432889
}
2944-
add_query_id_context(iov, &n_iov);
29452890

29462891
rqst->rq_nvec = n_iov;
29472892
return 0;

0 commit comments

Comments
 (0)