Merge tag '5.5-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Nine cifs/smb3 fixes:

- one fix for stable (oops during oplock break)

- two timestamp fixes including important one for updating mtime at
close to avoid stale metadata caching issue on dirty files (also
improves perf by using SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB over the
wire)

- two fixes for "modefromsid" mount option for file create (now
allows mode bits to be set more atomically and accurately on create
by adding "sd_context" on create when modefromsid specified on
mount)

- two fixes for multichannel found in testing this week against
different servers

- two small cleanup patches"

* tag '5.5-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
smb3: improve check for when we send the security descriptor context on create
smb3: fix mode passed in on create for modetosid mount option
cifs: fix possible uninitialized access and race on iface_list
cifs: Fix lookup of SMB connections on multichannel
smb3: query attributes on file close
smb3: remove unused flag passed into close functions
cifs: remove redundant assignment to pointer pneg_ctxt
fs: cifs: Fix atime update check vs mtime
CIFS: Fix NULL-pointer dereference in smb2_push_mandatory_locks

+26 -16
fs/cifs/cifsacl.c
··· 802 802 return; 803 803 } 804 804 805 + /* 806 + * Fill in the special SID based on the mode. See 807 + * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx 808 + */ 809 + unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) 810 + { 811 + int i; 812 + unsigned int ace_size = 28; 813 + 814 + pntace->type = ACCESS_DENIED_ACE_TYPE; 815 + pntace->flags = 0x0; 816 + pntace->access_req = 0; 817 + pntace->sid.num_subauth = 3; 818 + pntace->sid.revision = 1; 819 + for (i = 0; i < NUM_AUTHS; i++) 820 + pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i]; 821 + 822 + pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; 823 + pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; 824 + pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); 825 + 826 + /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ 827 + pntace->size = cpu_to_le16(ace_size); 828 + return ace_size; 829 + } 805 830 806 831 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, 807 832 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) ··· 840 815 if (modefromsid) { 841 816 struct cifs_ace *pntace = 842 817 (struct cifs_ace *)((char *)pnndacl + size); 843 - int i; 844 818 845 - pntace->type = ACCESS_ALLOWED; 846 - pntace->flags = 0x0; 847 - pntace->access_req = 0; 848 - pntace->sid.num_subauth = 3; 849 - pntace->sid.revision = 1; 850 - for (i = 0; i < NUM_AUTHS; i++) 851 - pntace->sid.authority[i] = 852 - sid_unix_NFS_mode.authority[i]; 853 - pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; 854 - pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; 855 - pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); 856 - 857 - /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ 858 - pntace->size = cpu_to_le16(28); 859 - size += 28; 819 + size += setup_special_mode_ACE(pntace, nmode); 860 820 num_aces++; 861 821 } 862 822
+16 -16
fs/cifs/cifsacl.h
··· 147 147 } __packed; 148 148 149 149 /* Meaning of 'Control' field flags */ 150 - #define ACL_CONTROL_SR 0x0001 /* Self relative */ 151 - #define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */ 152 - #define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */ 153 - #define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */ 154 - #define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */ 155 - #define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */ 156 - #define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */ 157 - #define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */ 158 - #define ACL_CONTROL_SS 0x0100 /* Create server ACL */ 159 - #define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */ 160 - #define ACL_CONTROL_SD 0x0400 /* SACL defaulted */ 161 - #define ACL_CONTROL_SP 0x0800 /* SACL is present on object */ 162 - #define ACL_CONTROL_DD 0x1000 /* DACL defaulted */ 163 - #define ACL_CONTROL_DP 0x2000 /* DACL is present on object */ 164 - #define ACL_CONTROL_GD 0x4000 /* Group was defaulted */ 165 - #define ACL_CONTROL_OD 0x8000 /* User was defaulted */ 150 + #define ACL_CONTROL_SR 0x8000 /* Self relative */ 151 + #define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */ 152 + #define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */ 153 + #define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */ 154 + #define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */ 155 + #define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */ 156 + #define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */ 157 + #define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */ 158 + #define ACL_CONTROL_SS 0x0080 /* Create server ACL */ 159 + #define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */ 160 + #define ACL_CONTROL_SD 0x0020 /* SACL defaulted */ 161 + #define ACL_CONTROL_SP 0x0010 /* SACL is present on object */ 162 + #define ACL_CONTROL_DD 0x0008 /* DACL defaulted */ 163 + #define ACL_CONTROL_DP 0x0004 /* DACL is present on object */ 164 + #define ACL_CONTROL_GD 0x0002 /* Group was defaulted */ 165 + #define ACL_CONTROL_OD 0x0001 /* User was defaulted */ 166 166 167 167 /* Meaning of AclRevision flags */ 168 168 #define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
+4
fs/cifs/cifsglob.h
··· 368 368 /* close a file */ 369 369 void (*close)(const unsigned int, struct cifs_tcon *, 370 370 struct cifs_fid *); 371 + /* close a file, returning file attributes and timestamps */ 372 + void (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon, 373 + struct cifsFileInfo *pfile_info); 371 374 /* send a flush request to the server */ 372 375 int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *); 373 376 /* async read from the server */ ··· 777 774 */ 778 775 int nr_targets; 779 776 bool noblockcnt; /* use non-blocking connect() */ 777 + bool is_channel; /* if a session channel */ 780 778 }; 781 779 782 780 struct cifs_credits {
+1
fs/cifs/cifsproto.h
··· 213 213 const struct cifs_fid *, u32 *); 214 214 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, 215 215 const char *, int); 216 + extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); 216 217 217 218 extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); 218 219 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
+5 -1
fs/cifs/connect.c
··· 2712 2712 2713 2713 spin_lock(&cifs_tcp_ses_lock); 2714 2714 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 2715 - if (!match_server(server, vol)) 2715 + /* 2716 + * Skip ses channels since they're only handled in lower layers 2717 + * (e.g. cifs_send_recv). 2718 + */ 2719 + if (server->is_channel || !match_server(server, vol)) 2716 2720 continue; 2717 2721 2718 2722 ++server->srv_count;
+7 -4
fs/cifs/file.c
··· 315 315 INIT_LIST_HEAD(&fdlocks->locks); 316 316 fdlocks->cfile = cfile; 317 317 cfile->llist = fdlocks; 318 - cifs_down_write(&cinode->lock_sem); 319 - list_add(&fdlocks->llist, &cinode->llist); 320 - up_write(&cinode->lock_sem); 321 318 322 319 cfile->count = 1; 323 320 cfile->pid = current->tgid; ··· 338 341 cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n"); 339 342 oplock = 0; 340 343 } 344 + 345 + cifs_down_write(&cinode->lock_sem); 346 + list_add(&fdlocks->llist, &cinode->llist); 347 + up_write(&cinode->lock_sem); 341 348 342 349 spin_lock(&tcon->open_file_lock); 343 350 if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock) ··· 496 495 unsigned int xid; 497 496 498 497 xid = get_xid(); 499 - if (server->ops->close) 498 + if (server->ops->close_getattr) 499 + server->ops->close_getattr(xid, tcon, cifs_file); 500 + else if (server->ops->close) 500 501 server->ops->close(xid, tcon, &cifs_file->fid); 501 502 _free_xid(xid); 502 503 }
+1 -1
fs/cifs/inode.c
··· 163 163 164 164 spin_lock(&inode->i_lock); 165 165 /* we do not want atime to be less than mtime, it broke some apps */ 166 - if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime)) 166 + if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0) 167 167 inode->i_atime = fattr->cf_mtime; 168 168 else 169 169 inode->i_atime = fattr->cf_atime;
+29 -3
fs/cifs/sess.c
··· 77 77 int i = 0; 78 78 int rc = 0; 79 79 int tries = 0; 80 + struct cifs_server_iface *ifaces = NULL; 81 + size_t iface_count; 80 82 81 83 if (left <= 0) { 82 84 cifs_dbg(FYI, ··· 91 89 cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n"); 92 90 return 0; 93 91 } 92 + 93 + /* 94 + * Make a copy of the iface list at the time and use that 95 + * instead so as to not hold the iface spinlock for opening 96 + * channels 97 + */ 98 + spin_lock(&ses->iface_lock); 99 + iface_count = ses->iface_count; 100 + if (iface_count <= 0) { 101 + spin_unlock(&ses->iface_lock); 102 + cifs_dbg(FYI, "no iface list available to open channels\n"); 103 + return 0; 104 + } 105 + ifaces = kmemdup(ses->iface_list, iface_count*sizeof(*ifaces), 106 + GFP_ATOMIC); 107 + if (!ifaces) { 108 + spin_unlock(&ses->iface_lock); 109 + return 0; 110 + } 111 + spin_unlock(&ses->iface_lock); 94 112 95 113 /* 96 114 * Keep connecting to same, fastest, iface for all channels as ··· 127 105 break; 128 106 } 129 107 130 - iface = &ses->iface_list[i]; 108 + iface = &ifaces[i]; 131 109 if (is_ses_using_iface(ses, iface) && !iface->rss_capable) { 132 - i = (i+1) % ses->iface_count; 110 + i = (i+1) % iface_count; 133 111 continue; 134 112 } 135 113 ··· 137 115 if (rc) { 138 116 cifs_dbg(FYI, "failed to open extra channel on iface#%d rc=%d\n", 139 117 i, rc); 140 - i = (i+1) % ses->iface_count; 118 + i = (i+1) % iface_count; 141 119 continue; 142 120 } 143 121 ··· 146 124 left--; 147 125 } 148 126 127 + kfree(ifaces); 149 128 return ses->chan_count - old_chan_count; 150 129 } 151 130 ··· 236 213 chan->server = NULL; 237 214 goto out; 238 215 } 216 + spin_lock(&cifs_tcp_ses_lock); 217 + chan->server->is_channel = true; 218 + spin_unlock(&cifs_tcp_ses_lock); 239 219 240 220 /* 241 221 * We need to allocate the server crypto now as we will need
+1 -1
fs/cifs/smb2inode.c
··· 313 313 rqst[num_rqst].rq_iov = close_iov; 314 314 rqst[num_rqst].rq_nvec = 1; 315 315 rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, 316 - COMPOUND_FID); 316 + COMPOUND_FID, false); 317 317 smb2_set_related(&rqst[num_rqst]); 318 318 if (rc) 319 319 goto finished;
+45 -4
fs/cifs/smb2ops.c
··· 1178 1178 memset(&close_iov, 0, sizeof(close_iov)); 1179 1179 rqst[2].rq_iov = close_iov; 1180 1180 rqst[2].rq_nvec = 1; 1181 - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); 1181 + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); 1182 1182 smb2_set_related(&rqst[2]); 1183 1183 1184 1184 rc = compound_send_recv(xid, ses, flags, 3, rqst, ··· 1330 1330 struct cifs_fid *fid) 1331 1331 { 1332 1332 SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); 1333 + } 1334 + 1335 + static void 1336 + smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, 1337 + struct cifsFileInfo *cfile) 1338 + { 1339 + struct smb2_file_network_open_info file_inf; 1340 + struct inode *inode; 1341 + int rc; 1342 + 1343 + rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid, 1344 + cfile->fid.volatile_fid, &file_inf); 1345 + if (rc) 1346 + return; 1347 + 1348 + inode = d_inode(cfile->dentry); 1349 + 1350 + spin_lock(&inode->i_lock); 1351 + CIFS_I(inode)->time = jiffies; 1352 + 1353 + /* Creation time should not need to be updated on close */ 1354 + if (file_inf.LastWriteTime) 1355 + inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime); 1356 + if (file_inf.ChangeTime) 1357 + inode->i_ctime = cifs_NTtimeToUnix(file_inf.ChangeTime); 1358 + if (file_inf.LastAccessTime) 1359 + inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime); 1360 + 1361 + /* 1362 + * i_blocks is not related to (i_size / i_blksize), 1363 + * but instead 512 byte (2**9) size is required for 1364 + * calculating num blocks. 1365 + */ 1366 + if (le64_to_cpu(file_inf.AllocationSize) > 4096) 1367 + inode->i_blocks = 1368 + (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9; 1369 + 1370 + /* End of file and Attributes should not have to be updated on close */ 1371 + spin_unlock(&inode->i_lock); 1333 1372 } 1334 1373 1335 1374 static int ··· 1551 1512 rqst[2].rq_iov = close_iov; 1552 1513 rqst[2].rq_nvec = 1; 1553 1514 1554 - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); 1515 + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); 1555 1516 if (rc) 1556 1517 goto iqinf_exit; 1557 1518 smb2_set_related(&rqst[2]); ··· 2280 2241 rqst[2].rq_iov = close_iov; 2281 2242 rqst[2].rq_nvec = 1; 2282 2243 2283 - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); 2244 + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); 2284 2245 if (rc) 2285 2246 goto qic_exit; 2286 2247 smb2_set_related(&rqst[2]); ··· 2693 2654 rqst[2].rq_iov = close_iov; 2694 2655 rqst[2].rq_nvec = 1; 2695 2656 2696 - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); 2657 + rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); 2697 2658 if (rc) 2698 2659 goto querty_exit; 2699 2660 ··· 4746 4707 .open = smb2_open_file, 4747 4708 .set_fid = smb2_set_fid, 4748 4709 .close = smb2_close_file, 4710 + .close_getattr = smb2_close_getattr, 4749 4711 .flush = smb2_flush_file, 4750 4712 .async_readv = smb2_async_readv, 4751 4713 .async_writev = smb2_async_writev, ··· 4856 4816 .open = smb2_open_file, 4857 4817 .set_fid = smb2_set_fid, 4858 4818 .close = smb2_close_file, 4819 + .close_getattr = smb2_close_getattr, 4859 4820 .flush = smb2_flush_file, 4860 4821 .async_readv = smb2_async_readv, 4861 4822 .async_writev = smb2_async_writev,
+105 -23
fs/cifs/smb2pdu.c
··· 554 554 assemble_neg_contexts(struct smb2_negotiate_req *req, 555 555 struct TCP_Server_Info *server, unsigned int *total_len) 556 556 { 557 - char *pneg_ctxt = (char *)req; 557 + char *pneg_ctxt; 558 558 unsigned int ctxt_len; 559 559 560 560 if (*total_len > 200) { ··· 2191 2191 return 0; 2192 2192 } 2193 2193 2194 + /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ 2195 + static struct crt_sd_ctxt * 2196 + create_sd_buf(umode_t mode, unsigned int *len) 2197 + { 2198 + struct crt_sd_ctxt *buf; 2199 + struct cifs_ace *pace; 2200 + unsigned int sdlen, acelen; 2201 + 2202 + *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8); 2203 + buf = kzalloc(*len, GFP_KERNEL); 2204 + if (buf == NULL) 2205 + return buf; 2206 + 2207 + sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + 2208 + sizeof(struct cifs_ace); 2209 + 2210 + buf->ccontext.DataOffset = cpu_to_le16(offsetof 2211 + (struct crt_sd_ctxt, sd)); 2212 + buf->ccontext.DataLength = cpu_to_le32(sdlen); 2213 + buf->ccontext.NameOffset = cpu_to_le16(offsetof 2214 + (struct crt_sd_ctxt, Name)); 2215 + buf->ccontext.NameLength = cpu_to_le16(4); 2216 + /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ 2217 + buf->Name[0] = 'S'; 2218 + buf->Name[1] = 'e'; 2219 + buf->Name[2] = 'c'; 2220 + buf->Name[3] = 'D'; 2221 + buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */ 2222 + /* 2223 + * ACL is "self relative" ie ACL is stored in contiguous block of memory 2224 + * and "DP" ie the DACL is present 2225 + */ 2226 + buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP); 2227 + 2228 + /* offset owner, group and Sbz1 and SACL are all zero */ 2229 + buf->sd.OffsetDacl = cpu_to_le32(sizeof(struct smb3_sd)); 2230 + buf->acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */ 2231 + 2232 + /* create one ACE to hold the mode embedded in reserved special SID */ 2233 + pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); 2234 + acelen = setup_special_mode_ACE(pace, (__u64)mode); 2235 + buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); 2236 + buf->acl.AceCount = cpu_to_le16(1); 2237 + return buf; 2238 + } 2239 + 2240 + static int 2241 + add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) 2242 + { 2243 + struct smb2_create_req *req = iov[0].iov_base; 2244 + unsigned int num = *num_iovec; 2245 + unsigned int len = 0; 2246 + 2247 + iov[num].iov_base = create_sd_buf(mode, &len); 2248 + if (iov[num].iov_base == NULL) 2249 + return -ENOMEM; 2250 + iov[num].iov_len = len; 2251 + if (!req->CreateContextsOffset) 2252 + req->CreateContextsOffset = cpu_to_le32( 2253 + sizeof(struct smb2_create_req) + 2254 + iov[num - 1].iov_len); 2255 + le32_add_cpu(&req->CreateContextsLength, len); 2256 + *num_iovec = num + 1; 2257 + return 0; 2258 + } 2259 + 2194 2260 static struct crt_query_id_ctxt * 2195 2261 create_query_id_buf(void) 2196 2262 { ··· 2629 2563 return rc; 2630 2564 } 2631 2565 2632 - if ((oparms->disposition == FILE_CREATE) && 2566 + if ((oparms->disposition != FILE_OPEN) && 2567 + (oparms->cifs_sb) && 2568 + (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && 2633 2569 (oparms->mode != ACL_NO_MODE)) { 2634 2570 if (n_iov > 2) { 2635 2571 struct create_context *ccontext = ··· 2640 2572 cpu_to_le32(iov[n_iov-1].iov_len); 2641 2573 } 2642 2574 2643 - /* rc = add_sd_context(iov, &n_iov, oparms->mode); */ 2575 + cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); 2576 + rc = add_sd_context(iov, &n_iov, oparms->mode); 2644 2577 if (rc) 2645 2578 return rc; 2646 2579 } ··· 3001 2932 3002 2933 int 3003 2934 SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, 3004 - u64 persistent_fid, u64 volatile_fid) 2935 + u64 persistent_fid, u64 volatile_fid, bool query_attrs) 3005 2936 { 3006 2937 struct smb2_close_req *req; 3007 2938 struct kvec *iov = rqst->rq_iov; ··· 3014 2945 3015 2946 req->PersistentFileId = persistent_fid; 3016 2947 req->VolatileFileId = volatile_fid; 2948 + if (query_attrs) 2949 + req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; 2950 + else 2951 + req->Flags = 0; 3017 2952 iov[0].iov_base = (char *)req; 3018 2953 iov[0].iov_len = total_len; 3019 2954 ··· 3032 2959 } 3033 2960 3034 2961 int 3035 - SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, 3036 - u64 persistent_fid, u64 volatile_fid, int flags) 2962 + __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 2963 + u64 persistent_fid, u64 volatile_fid, 2964 + struct smb2_file_network_open_info *pbuf) 3037 2965 { 3038 2966 struct smb_rqst rqst; 3039 2967 struct smb2_close_rsp *rsp = NULL; ··· 3043 2969 struct kvec rsp_iov; 3044 2970 int resp_buftype = CIFS_NO_BUFFER; 3045 2971 int rc = 0; 2972 + int flags = 0; 2973 + bool query_attrs = false; 3046 2974 3047 2975 cifs_dbg(FYI, "Close\n"); 3048 2976 ··· 3059 2983 rqst.rq_iov = iov; 3060 2984 rqst.rq_nvec = 1; 3061 2985 2986 + /* check if need to ask server to return timestamps in close response */ 2987 + if (pbuf) 2988 + query_attrs = true; 2989 + 3062 2990 trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); 3063 - rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); 2991 + rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid, 2992 + query_attrs); 3064 2993 if (rc) 3065 2994 goto close_exit; 3066 2995 ··· 3077 2996 trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, 3078 2997 rc); 3079 2998 goto close_exit; 3080 - } else 2999 + } else { 3081 3000 trace_smb3_close_done(xid, persistent_fid, tcon->tid, 3082 3001 ses->Suid); 3002 + /* 3003 + * Note that have to subtract 4 since struct network_open_info 3004 + * has a final 4 byte pad that close response does not have 3005 + */ 3006 + if (pbuf) 3007 + memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4); 3008 + } 3083 3009 3084 3010 atomic_dec(&tcon->num_remote_opens); 3085 - 3086 - /* BB FIXME - decode close response, update inode for caching */ 3087 - 3088 3011 close_exit: 3089 3012 SMB2_close_free(&rqst); 3090 3013 free_rsp_buf(resp_buftype, rsp); 3091 - return rc; 3092 - } 3093 - 3094 - int 3095 - SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 3096 - u64 persistent_fid, u64 volatile_fid) 3097 - { 3098 - int rc; 3099 - int tmp_rc; 3100 - 3101 - rc = SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); 3102 3014 3103 3015 /* retry close in a worker thread if this one is interrupted */ 3104 3016 if (rc == -EINTR) { 3017 + int tmp_rc; 3018 + 3105 3019 tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid, 3106 3020 volatile_fid); 3107 3021 if (tmp_rc) 3108 3022 cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n", 3109 3023 persistent_fid, tmp_rc); 3110 3024 } 3111 - 3112 3025 return rc; 3026 + } 3027 + 3028 + int 3029 + SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 3030 + u64 persistent_fid, u64 volatile_fid) 3031 + { 3032 + return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL); 3113 3033 } 3114 3034 3115 3035 int
+21
fs/cifs/smb2pdu.h
··· 25 25 #define _SMB2PDU_H 26 26 27 27 #include <net/sock.h> 28 + #include <cifsacl.h> 28 29 29 30 /* 30 31 * Note that, due to trying to use names similar to the protocol specifications, ··· 856 855 __u8 Name[8]; 857 856 } __packed; 858 857 858 + struct crt_sd_ctxt { 859 + struct create_context ccontext; 860 + __u8 Name[8]; 861 + struct smb3_sd sd; 862 + struct smb3_acl acl; 863 + /* Followed by at least 4 ACEs */ 864 + } __packed; 865 + 866 + 859 867 #define COPY_CHUNK_RES_KEY_SIZE 24 860 868 struct resume_key_req { 861 869 char ResumeKey[COPY_CHUNK_RES_KEY_SIZE]; ··· 1579 1569 struct smb2_file_eof_info { /* encoding of request for level 10 */ 1580 1570 __le64 EndOfFile; /* new end of file value */ 1581 1571 } __packed; /* level 20 Set */ 1572 + 1573 + struct smb2_file_network_open_info { 1574 + __le64 CreationTime; 1575 + __le64 LastAccessTime; 1576 + __le64 LastWriteTime; 1577 + __le64 ChangeTime; 1578 + __le64 AllocationSize; 1579 + __le64 EndOfFile; 1580 + __le32 Attributes; 1581 + __le32 Reserved; 1582 + } __packed; /* level 34 Query also similar returned in close rsp and open rsp */ 1582 1583 1583 1584 extern char smb2_padding[7]; 1584 1585
+4 -3
fs/cifs/smb2proto.h
··· 155 155 u64 persistent_fid, u64 volatile_fid, bool watch_tree, 156 156 u32 completion_filter); 157 157 158 + extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 159 + u64 persistent_fid, u64 volatile_fid, 160 + struct smb2_file_network_open_info *pbuf); 158 161 extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 159 162 u64 persistent_file_id, u64 volatile_file_id); 160 - extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, 161 - u64 persistent_fid, u64 volatile_fid, int flags); 162 163 extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, 163 - u64 persistent_file_id, u64 volatile_file_id); 164 + u64 persistent_fid, u64 volatile_fid, bool query_attrs); 164 165 extern void SMB2_close_free(struct smb_rqst *rqst); 165 166 extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, 166 167 u64 persistent_file_id, u64 volatile_file_id);