Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
[CIFS] Fix multiuser mounts so server does not invalidate earlier security contexts
[CIFS] improve posix semantics of file create
[CIFS] Fix oops in cifs_strfromUCS_le mounting to servers which do not specify their OS
cifs: posix fill in inode needed by posix open
cifs: properly handle case where CIFSGetSrvInodeNumber fails
cifs: refactor new_inode() calls and inode initialization
[CIFS] Prevent OOPs when mounting with remote prefixpath.
[CIFS] ipv6_addr_equal for address comparison

+455 -184
+14 -1
fs/cifs/CHANGES
··· 1 Version 1.56 2 ------------ 3 Add "forcemandatorylock" mount option to allow user to use mandatory ··· 17 top of the share. Fix problem in 2.6.28 resolving DFS paths to 18 Samba servers (worked to Windows). Fix rmdir so that pending search 19 (readdir) requests do not get invalid results which include the now 20 - removed directory. 21 22 Version 1.55 23 ------------
··· 1 + Version 1.57 2 + ------------ 3 + Improve support for multiple security contexts to the same server. We 4 + used to use the same "vcnumber" for all connections which could cause 5 + the server to treat subsequent connections, especially those that 6 + are authenticated as guest, as reconnections, invalidating the earlier 7 + user's smb session. This fix allows cifs to mount multiple times to the 8 + same server with different userids without risking invalidating earlier 9 + established security contexts. 10 + 11 Version 1.56 12 ------------ 13 Add "forcemandatorylock" mount option to allow user to use mandatory ··· 7 top of the share. Fix problem in 2.6.28 resolving DFS paths to 8 Samba servers (worked to Windows). Fix rmdir so that pending search 9 (readdir) requests do not get invalid results which include the now 10 + removed directory. Fix oops in cifs_dfs_ref.c when prefixpath is not reachable 11 + when using DFS. Add better file create support to servers which support 12 + the CIFS POSIX protocol extensions (this adds support for new flags 13 + on create, and improves semantics for write of locked ranges). 14 15 Version 1.55 16 ------------
+1 -1
fs/cifs/cifsfs.h
··· 100 extern const struct export_operations cifs_export_ops; 101 #endif /* EXPERIMENTAL */ 102 103 - #define CIFS_VERSION "1.56" 104 #endif /* _CIFSFS_H */
··· 100 extern const struct export_operations cifs_export_ops; 101 #endif /* EXPERIMENTAL */ 102 103 + #define CIFS_VERSION "1.57" 104 #endif /* _CIFSFS_H */
+5 -1
fs/cifs/cifsglob.h
··· 164 /* multiplexed reads or writes */ 165 unsigned int maxBuf; /* maxBuf specifies the maximum */ 166 /* message size the server can send or receive for non-raw SMBs */ 167 - unsigned int maxRw; /* maxRw specifies the maximum */ 168 /* message size the server can send or receive for */ 169 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ 170 char sessid[4]; /* unique token id for this session */ 171 /* (returned on Negotiate */ 172 int capabilities; /* allow selective disabling of caps by smb sess */ ··· 213 unsigned overrideSecFlg; /* if non-zero override global sec flags */ 214 __u16 ipc_tid; /* special tid for connection to IPC share */ 215 __u16 flags; 216 char *serverOS; /* name of operating system underlying server */ 217 char *serverNOS; /* name of network operating system of server */ 218 char *serverDomain; /* security realm of server */
··· 164 /* multiplexed reads or writes */ 165 unsigned int maxBuf; /* maxBuf specifies the maximum */ 166 /* message size the server can send or receive for non-raw SMBs */ 167 + unsigned int max_rw; /* maxRw specifies the maximum */ 168 /* message size the server can send or receive for */ 169 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ 170 + unsigned int max_vcs; /* maximum number of smb sessions, at least 171 + those that can be specified uniquely with 172 + vcnumbers */ 173 char sessid[4]; /* unique token id for this session */ 174 /* (returned on Negotiate */ 175 int capabilities; /* allow selective disabling of caps by smb sess */ ··· 210 unsigned overrideSecFlg; /* if non-zero override global sec flags */ 211 __u16 ipc_tid; /* special tid for connection to IPC share */ 212 __u16 flags; 213 + __u16 vcnum; 214 char *serverOS; /* name of operating system underlying server */ 215 char *serverNOS; /* name of network operating system of server */ 216 char *serverDomain; /* security realm of server */
+4
fs/cifs/cifsproto.h
··· 42 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); 43 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 44 extern char *build_path_from_dentry(struct dentry *); 45 extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46 /* extern void renew_parental_timestamps(struct dentry *direntry);*/ 47 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, ··· 92 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 93 extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 94 95 extern int cifs_get_inode_info(struct inode **pinode, 96 const unsigned char *search_path, 97 FILE_ALL_INFO *pfile_info,
··· 42 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); 43 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 44 extern char *build_path_from_dentry(struct dentry *); 45 + extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); 46 extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 47 /* extern void renew_parental_timestamps(struct dentry *direntry);*/ 48 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, ··· 91 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 92 extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 93 94 + extern void posix_fill_in_inode(struct inode *tmp_inode, 95 + FILE_UNIX_BASIC_INFO *pData, int isNewInode); 96 + extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); 97 extern int cifs_get_inode_info(struct inode **pinode, 98 const unsigned char *search_path, 99 FILE_ALL_INFO *pfile_info,
+4 -3
fs/cifs/cifssmb.c
··· 528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount); 529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 531 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); 532 /* even though we do not use raw we might as well set this 533 accurately, in case we ever find a need for it */ 534 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 535 - server->maxRw = 0xFF00; 536 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; 537 } else { 538 - server->maxRw = 0;/* we do not need to use raw anyway */ 539 server->capabilities = CAP_MPX_MODE; 540 } 541 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); ··· 639 /* probably no need to store and check maxvcs */ 640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), 641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 642 - server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); 644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
··· 528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount); 529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 531 + server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); 533 /* even though we do not use raw we might as well set this 534 accurately, in case we ever find a need for it */ 535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 536 + server->max_rw = 0xFF00; 537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; 538 } else { 539 + server->max_rw = 0;/* do not need to use raw anyway */ 540 server->capabilities = CAP_MPX_MODE; 541 } 542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); ··· 638 /* probably no need to store and check maxvcs */ 639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), 640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 641 + server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); 643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 644 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+48 -3
fs/cifs/connect.c
··· 23 #include <linux/string.h> 24 #include <linux/list.h> 25 #include <linux/wait.h> 26 - #include <linux/ipv6.h> 27 #include <linux/pagemap.h> 28 #include <linux/ctype.h> 29 #include <linux/utsname.h> ··· 34 #include <linux/freezer.h> 35 #include <asm/uaccess.h> 36 #include <asm/processor.h> 37 #include "cifspdu.h" 38 #include "cifsglob.h" 39 #include "cifsproto.h" ··· 1379 server->addr.sockAddr.sin_addr.s_addr)) 1380 continue; 1381 else if (addr->ss_family == AF_INET6 && 1382 - memcmp(&server->addr.sockAddr6.sin6_addr, 1383 - &addr6->sin6_addr, sizeof(addr6->sin6_addr))) 1384 continue; 1385 1386 ++server->srv_count; ··· 2180 "mount option supported")); 2181 } 2182 2183 int 2184 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2185 char *mount_data, const char *devname) ··· 2217 struct cifsSesInfo *pSesInfo = NULL; 2218 struct cifsTconInfo *tcon = NULL; 2219 struct TCP_Server_Info *srvTcp = NULL; 2220 2221 xid = GetXid(); 2222 ··· 2453 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) 2454 cifs_sb->rsize = min(cifs_sb->rsize, 2455 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2456 2457 /* volume_info->password is freed above when existing session found 2458 (in which case it is not needed anymore) but when new sesion is created
··· 23 #include <linux/string.h> 24 #include <linux/list.h> 25 #include <linux/wait.h> 26 #include <linux/pagemap.h> 27 #include <linux/ctype.h> 28 #include <linux/utsname.h> ··· 35 #include <linux/freezer.h> 36 #include <asm/uaccess.h> 37 #include <asm/processor.h> 38 + #include <net/ipv6.h> 39 #include "cifspdu.h" 40 #include "cifsglob.h" 41 #include "cifsproto.h" ··· 1379 server->addr.sockAddr.sin_addr.s_addr)) 1380 continue; 1381 else if (addr->ss_family == AF_INET6 && 1382 + !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, 1383 + &addr6->sin6_addr)) 1384 continue; 1385 1386 ++server->srv_count; ··· 2180 "mount option supported")); 2181 } 2182 2183 + static int 2184 + is_path_accessible(int xid, struct cifsTconInfo *tcon, 2185 + struct cifs_sb_info *cifs_sb, const char *full_path) 2186 + { 2187 + int rc; 2188 + __u64 inode_num; 2189 + FILE_ALL_INFO *pfile_info; 2190 + 2191 + rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num, 2192 + cifs_sb->local_nls, 2193 + cifs_sb->mnt_cifs_flags & 2194 + CIFS_MOUNT_MAP_SPECIAL_CHR); 2195 + if (rc != -EOPNOTSUPP) 2196 + return rc; 2197 + 2198 + pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 2199 + if (pfile_info == NULL) 2200 + return -ENOMEM; 2201 + 2202 + rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info, 2203 + 0 /* not legacy */, cifs_sb->local_nls, 2204 + cifs_sb->mnt_cifs_flags & 2205 + CIFS_MOUNT_MAP_SPECIAL_CHR); 2206 + kfree(pfile_info); 2207 + return rc; 2208 + } 2209 + 2210 int 2211 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2212 char *mount_data, const char *devname) ··· 2190 struct cifsSesInfo *pSesInfo = NULL; 2191 struct cifsTconInfo *tcon = NULL; 2192 struct TCP_Server_Info *srvTcp = NULL; 2193 + char *full_path; 2194 2195 xid = GetXid(); 2196 ··· 2425 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) 2426 cifs_sb->rsize = min(cifs_sb->rsize, 2427 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2428 + 2429 + if (!rc && cifs_sb->prepathlen) { 2430 + /* build_path_to_root works only when we have a valid tcon */ 2431 + full_path = cifs_build_path_to_root(cifs_sb); 2432 + if (full_path == NULL) { 2433 + rc = -ENOMEM; 2434 + goto mount_fail_check; 2435 + } 2436 + rc = is_path_accessible(xid, tcon, cifs_sb, full_path); 2437 + if (rc) { 2438 + cERROR(1, ("Path %s in not accessible: %d", 2439 + full_path, rc)); 2440 + kfree(full_path); 2441 + goto mount_fail_check; 2442 + } 2443 + kfree(full_path); 2444 + } 2445 2446 /* volume_info->password is freed above when existing session found 2447 (in which case it is not needed anymore) but when new sesion is created
+202 -99
fs/cifs/dir.c
··· 3 * 4 * vfs operations that deal with dentries 5 * 6 - * Copyright (C) International Business Machines Corp., 2002,2008 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 * 9 * This library is free software; you can redistribute it and/or modify ··· 129 return full_path; 130 } 131 132 static void setup_cifs_dentry(struct cifsTconInfo *tcon, 133 struct dentry *direntry, 134 struct inode *newinode) ··· 222 int xid; 223 int create_options = CREATE_NOT_DIR; 224 int oplock = 0; 225 - /* BB below access is too much for the mknod to request */ 226 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 227 __u16 fileHandle; 228 struct cifs_sb_info *cifs_sb; ··· 253 } 254 255 mode &= ~current->fs->umask; 256 257 if (nd && (nd->flags & LOOKUP_OPEN)) { 258 - int oflags = nd->intent.open.flags; 259 - 260 desiredAccess = 0; 261 if (oflags & FMODE_READ) 262 - desiredAccess |= GENERIC_READ; 263 if (oflags & FMODE_WRITE) { 264 desiredAccess |= GENERIC_WRITE; 265 if (!(oflags & FMODE_READ)) ··· 308 309 /* BB add processing to set equivalent of mode - e.g. via CreateX with 310 ACLs */ 311 - if (oplockEnabled) 312 - oplock = REQ_OPLOCK; 313 314 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 315 if (buf == NULL) { ··· 340 } 341 if (rc) { 342 cFYI(1, ("cifs_create returned 0x%x", rc)); 343 - } else { 344 - /* If Open reported that we actually created a file 345 - then we now have to set the mode if possible */ 346 - if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 347 - struct cifs_unix_set_info_args args = { 348 .mode = mode, 349 .ctime = NO_CHANGE_64, 350 .atime = NO_CHANGE_64, 351 .mtime = NO_CHANGE_64, 352 .device = 0, 353 - }; 354 355 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 356 - args.uid = (__u64) current_fsuid(); 357 - if (inode->i_mode & S_ISGID) 358 - args.gid = (__u64) inode->i_gid; 359 - else 360 - args.gid = (__u64) current_fsgid(); 361 - } else { 362 - args.uid = NO_CHANGE_64; 363 - args.gid = NO_CHANGE_64; 364 - } 365 - CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, 366 - cifs_sb->local_nls, 367 - cifs_sb->mnt_cifs_flags & 368 - CIFS_MOUNT_MAP_SPECIAL_CHR); 369 } else { 370 - /* BB implement mode setting via Windows security 371 - descriptors e.g. */ 372 - /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ 373 - 374 - /* Could set r/o dos attribute if mode & 0222 == 0 */ 375 } 376 377 - /* server might mask mode so we have to query for it */ 378 - if (tcon->unix_ext) 379 - rc = cifs_get_inode_info_unix(&newinode, full_path, 380 - inode->i_sb, xid); 381 - else { 382 - rc = cifs_get_inode_info(&newinode, full_path, 383 - buf, inode->i_sb, xid, 384 - &fileHandle); 385 - if (newinode) { 386 - if (cifs_sb->mnt_cifs_flags & 387 - CIFS_MOUNT_DYNPERM) 388 - newinode->i_mode = mode; 389 - if ((oplock & CIFS_CREATE_ACTION) && 390 - (cifs_sb->mnt_cifs_flags & 391 - CIFS_MOUNT_SET_UID)) { 392 - newinode->i_uid = current_fsuid(); 393 - if (inode->i_mode & S_ISGID) 394 - newinode->i_gid = 395 - inode->i_gid; 396 - else 397 - newinode->i_gid = 398 - current_fsgid(); 399 - } 400 } 401 } 402 403 - if (rc != 0) { 404 - cFYI(1, ("Create worked, get_inode_info failed rc = %d", 405 - rc)); 406 - } else 407 - setup_cifs_dentry(tcon, direntry, newinode); 408 409 - if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || 410 - (!(nd->flags & LOOKUP_OPEN))) { 411 - /* mknod case - do not leave file open */ 412 - CIFSSMBClose(xid, tcon, fileHandle); 413 - } else if (newinode) { 414 - struct cifsFileInfo *pCifsFile = 415 - kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 416 417 - if (pCifsFile == NULL) 418 - goto cifs_create_out; 419 - pCifsFile->netfid = fileHandle; 420 - pCifsFile->pid = current->tgid; 421 - pCifsFile->pInode = newinode; 422 - pCifsFile->invalidHandle = false; 423 - pCifsFile->closePend = false; 424 - init_MUTEX(&pCifsFile->fh_sem); 425 - mutex_init(&pCifsFile->lock_mutex); 426 - INIT_LIST_HEAD(&pCifsFile->llist); 427 - atomic_set(&pCifsFile->wrtPending, 0); 428 429 - /* set the following in open now 430 pCifsFile->pfile = file; */ 431 - write_lock(&GlobalSMBSeslock); 432 - list_add(&pCifsFile->tlist, &tcon->openFileList); 433 - pCifsInode = CIFS_I(newinode); 434 - if (pCifsInode) { 435 - /* if readable file instance put first in list*/ 436 - if (write_only) { 437 - list_add_tail(&pCifsFile->flist, 438 - &pCifsInode->openFileList); 439 - } else { 440 - list_add(&pCifsFile->flist, 441 - &pCifsInode->openFileList); 442 - } 443 - if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 444 - pCifsInode->clientCanCacheAll = true; 445 - pCifsInode->clientCanCacheRead = true; 446 - cFYI(1, ("Exclusive Oplock inode %p", 447 - newinode)); 448 - } else if ((oplock & 0xF) == OPLOCK_READ) 449 - pCifsInode->clientCanCacheRead = true; 450 } 451 - write_unlock(&GlobalSMBSeslock); 452 } 453 } 454 cifs_create_out: 455 kfree(buf);
··· 3 * 4 * vfs operations that deal with dentries 5 * 6 + * Copyright (C) International Business Machines Corp., 2002,2009 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 * 9 * This library is free software; you can redistribute it and/or modify ··· 129 return full_path; 130 } 131 132 + static int cifs_posix_open(char *full_path, struct inode **pinode, 133 + struct super_block *sb, int mode, int oflags, 134 + int *poplock, __u16 *pnetfid, int xid) 135 + { 136 + int rc; 137 + __u32 oplock; 138 + FILE_UNIX_BASIC_INFO *presp_data; 139 + __u32 posix_flags = 0; 140 + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 141 + 142 + cFYI(1, ("posix open %s", full_path)); 143 + 144 + presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); 145 + if (presp_data == NULL) 146 + return -ENOMEM; 147 + 148 + /* So far cifs posix extensions can only map the following flags. 149 + There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but 150 + so far we do not seem to need them, and we can treat them as local only */ 151 + if ((oflags & (FMODE_READ | FMODE_WRITE)) == 152 + (FMODE_READ | FMODE_WRITE)) 153 + posix_flags = SMB_O_RDWR; 154 + else if (oflags & FMODE_READ) 155 + posix_flags = SMB_O_RDONLY; 156 + else if (oflags & FMODE_WRITE) 157 + posix_flags = SMB_O_WRONLY; 158 + if (oflags & O_CREAT) 159 + posix_flags |= SMB_O_CREAT; 160 + if (oflags & O_EXCL) 161 + posix_flags |= SMB_O_EXCL; 162 + if (oflags & O_TRUNC) 163 + posix_flags |= SMB_O_TRUNC; 164 + if (oflags & O_APPEND) 165 + posix_flags |= SMB_O_APPEND; 166 + if (oflags & O_SYNC) 167 + posix_flags |= SMB_O_SYNC; 168 + if (oflags & O_DIRECTORY) 169 + posix_flags |= SMB_O_DIRECTORY; 170 + if (oflags & O_NOFOLLOW) 171 + posix_flags |= SMB_O_NOFOLLOW; 172 + if (oflags & O_DIRECT) 173 + posix_flags |= SMB_O_DIRECT; 174 + 175 + 176 + rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 177 + pnetfid, presp_data, &oplock, full_path, 178 + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 179 + CIFS_MOUNT_MAP_SPECIAL_CHR); 180 + if (rc) 181 + goto posix_open_ret; 182 + 183 + if (presp_data->Type == cpu_to_le32(-1)) 184 + goto posix_open_ret; /* open ok, caller does qpathinfo */ 185 + 186 + /* get new inode and set it up */ 187 + if (!pinode) 188 + goto posix_open_ret; /* caller does not need info */ 189 + 190 + *pinode = cifs_new_inode(sb, &presp_data->UniqueId); 191 + 192 + /* We do not need to close the file if new_inode fails since 193 + the caller will retry qpathinfo as long as inode is null */ 194 + if (*pinode == NULL) 195 + goto posix_open_ret; 196 + 197 + posix_fill_in_inode(*pinode, presp_data, 1); 198 + 199 + posix_open_ret: 200 + kfree(presp_data); 201 + return rc; 202 + } 203 + 204 static void setup_cifs_dentry(struct cifsTconInfo *tcon, 205 struct dentry *direntry, 206 struct inode *newinode) ··· 150 int xid; 151 int create_options = CREATE_NOT_DIR; 152 int oplock = 0; 153 + int oflags; 154 + /* 155 + * BB below access is probably too much for mknod to request 156 + * but we have to do query and setpathinfo so requesting 157 + * less could fail (unless we want to request getatr and setatr 158 + * permissions (only). At least for POSIX we do not have to 159 + * request so much. 160 + */ 161 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 162 __u16 fileHandle; 163 struct cifs_sb_info *cifs_sb; ··· 174 } 175 176 mode &= ~current->fs->umask; 177 + if (oplockEnabled) 178 + oplock = REQ_OPLOCK; 179 + 180 + if (nd && (nd->flags & LOOKUP_OPEN)) 181 + oflags = nd->intent.open.flags; 182 + else 183 + oflags = FMODE_READ; 184 + 185 + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 186 + (CIFS_UNIX_POSIX_PATH_OPS_CAP & 187 + le64_to_cpu(tcon->fsUnixInfo.Capability))) { 188 + rc = cifs_posix_open(full_path, &newinode, inode->i_sb, 189 + mode, oflags, &oplock, &fileHandle, xid); 190 + /* EIO could indicate that (posix open) operation is not 191 + supported, despite what server claimed in capability 192 + negotation. EREMOTE indicates DFS junction, which is not 193 + handled in posix open */ 194 + 195 + if ((rc == 0) && (newinode == NULL)) 196 + goto cifs_create_get_file_info; /* query inode info */ 197 + else if (rc == 0) /* success, no need to query */ 198 + goto cifs_create_set_dentry; 199 + else if ((rc != -EIO) && (rc != -EREMOTE) && 200 + (rc != -EOPNOTSUPP)) /* path not found or net err */ 201 + goto cifs_create_out; 202 + /* else fallthrough to retry, using older open call, this is 203 + case where server does not support this SMB level, and 204 + falsely claims capability (also get here for DFS case 205 + which should be rare for path not covered on files) */ 206 + } 207 208 if (nd && (nd->flags & LOOKUP_OPEN)) { 209 + /* if the file is going to stay open, then we 210 + need to set the desired access properly */ 211 desiredAccess = 0; 212 if (oflags & FMODE_READ) 213 + desiredAccess |= GENERIC_READ; /* is this too little? */ 214 if (oflags & FMODE_WRITE) { 215 desiredAccess |= GENERIC_WRITE; 216 if (!(oflags & FMODE_READ)) ··· 199 200 /* BB add processing to set equivalent of mode - e.g. via CreateX with 201 ACLs */ 202 203 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 204 if (buf == NULL) { ··· 233 } 234 if (rc) { 235 cFYI(1, ("cifs_create returned 0x%x", rc)); 236 + goto cifs_create_out; 237 + } 238 + 239 + /* If Open reported that we actually created a file 240 + then we now have to set the mode if possible */ 241 + if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 242 + struct cifs_unix_set_info_args args = { 243 .mode = mode, 244 .ctime = NO_CHANGE_64, 245 .atime = NO_CHANGE_64, 246 .mtime = NO_CHANGE_64, 247 .device = 0, 248 + }; 249 250 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 251 + args.uid = (__u64) current_fsuid(); 252 + if (inode->i_mode & S_ISGID) 253 + args.gid = (__u64) inode->i_gid; 254 + else 255 + args.gid = (__u64) current_fsgid(); 256 } else { 257 + args.uid = NO_CHANGE_64; 258 + args.gid = NO_CHANGE_64; 259 } 260 + CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, 261 + cifs_sb->local_nls, 262 + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 263 + } else { 264 + /* BB implement mode setting via Windows security 265 + descriptors e.g. */ 266 + /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ 267 268 + /* Could set r/o dos attribute if mode & 0222 == 0 */ 269 + } 270 + 271 + cifs_create_get_file_info: 272 + /* server might mask mode so we have to query for it */ 273 + if (tcon->unix_ext) 274 + rc = cifs_get_inode_info_unix(&newinode, full_path, 275 + inode->i_sb, xid); 276 + else { 277 + rc = cifs_get_inode_info(&newinode, full_path, buf, 278 + inode->i_sb, xid, &fileHandle); 279 + if (newinode) { 280 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) 281 + newinode->i_mode = mode; 282 + if ((oplock & CIFS_CREATE_ACTION) && 283 + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { 284 + newinode->i_uid = current_fsuid(); 285 + if (inode->i_mode & S_ISGID) 286 + newinode->i_gid = inode->i_gid; 287 + else 288 + newinode->i_gid = current_fsgid(); 289 } 290 } 291 + } 292 293 + cifs_create_set_dentry: 294 + if (rc == 0) 295 + setup_cifs_dentry(tcon, direntry, newinode); 296 + else 297 + cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc)); 298 299 + /* nfsd case - nfs srv does not set nd */ 300 + if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { 301 + /* mknod case - do not leave file open */ 302 + CIFSSMBClose(xid, tcon, fileHandle); 303 + } else if (newinode) { 304 + struct cifsFileInfo *pCifsFile = 305 + kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 306 307 + if (pCifsFile == NULL) 308 + goto cifs_create_out; 309 + pCifsFile->netfid = fileHandle; 310 + pCifsFile->pid = current->tgid; 311 + pCifsFile->pInode = newinode; 312 + pCifsFile->invalidHandle = false; 313 + pCifsFile->closePend = false; 314 + init_MUTEX(&pCifsFile->fh_sem); 315 + mutex_init(&pCifsFile->lock_mutex); 316 + INIT_LIST_HEAD(&pCifsFile->llist); 317 + atomic_set(&pCifsFile->wrtPending, 0); 318 319 + /* set the following in open now 320 pCifsFile->pfile = file; */ 321 + write_lock(&GlobalSMBSeslock); 322 + list_add(&pCifsFile->tlist, &tcon->openFileList); 323 + pCifsInode = CIFS_I(newinode); 324 + if (pCifsInode) { 325 + /* if readable file instance put first in list*/ 326 + if (write_only) { 327 + list_add_tail(&pCifsFile->flist, 328 + &pCifsInode->openFileList); 329 + } else { 330 + list_add(&pCifsFile->flist, 331 + &pCifsInode->openFileList); 332 } 333 + if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 334 + pCifsInode->clientCanCacheAll = true; 335 + pCifsInode->clientCanCacheRead = true; 336 + cFYI(1, ("Exclusive Oplock inode %p", 337 + newinode)); 338 + } else if ((oplock & 0xF) == OPLOCK_READ) 339 + pCifsInode->clientCanCacheRead = true; 340 } 341 + write_unlock(&GlobalSMBSeslock); 342 } 343 cifs_create_out: 344 kfree(buf);
+64 -40
fs/cifs/inode.c
··· 199 pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); 200 } 201 202 int cifs_get_inode_info_unix(struct inode **pinode, 203 const unsigned char *full_path, struct super_block *sb, int xid) 204 { ··· 276 277 /* get new inode */ 278 if (*pinode == NULL) { 279 - *pinode = new_inode(sb); 280 if (*pinode == NULL) { 281 rc = -ENOMEM; 282 goto cgiiu_exit; 283 } 284 - /* Is an i_ino of zero legal? */ 285 - /* note ino incremented to unique num in new_inode */ 286 - /* Are there sanity checks we can use to ensure that 287 - the server is really filling in that field? */ 288 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 289 - (*pinode)->i_ino = (unsigned long)find_data.UniqueId; 290 - 291 - if (sb->s_flags & MS_NOATIME) 292 - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 293 - 294 - insert_inode_hash(*pinode); 295 } 296 297 inode = *pinode; ··· 497 498 /* get new inode */ 499 if (*pinode == NULL) { 500 - *pinode = new_inode(sb); 501 - if (*pinode == NULL) { 502 - rc = -ENOMEM; 503 - goto cgii_exit; 504 - } 505 /* Is an i_ino of zero legal? Can we use that to check 506 if the server supports returning inode numbers? Are 507 there other sanity checks we can use to ensure that ··· 516 517 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 518 int rc1 = 0; 519 - __u64 inode_num; 520 521 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 522 - full_path, &inode_num, 523 cifs_sb->local_nls, 524 cifs_sb->mnt_cifs_flags & 525 CIFS_MOUNT_MAP_SPECIAL_CHR); 526 if (rc1) { 527 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 528 /* BB EOPNOSUPP disable SERVER_INUM? */ 529 - } else /* do we need cast or hash to ino? */ 530 - (*pinode)->i_ino = inode_num; 531 - } /* else ino incremented to unique num in new_inode*/ 532 - if (sb->s_flags & MS_NOATIME) 533 - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 534 - insert_inode_hash(*pinode); 535 } 536 inode = *pinode; 537 cifsInfo = CIFS_I(inode); ··· 655 .lookup = cifs_lookup, 656 }; 657 658 - static char *build_path_to_root(struct cifs_sb_info *cifs_sb) 659 { 660 int pplen = cifs_sb->prepathlen; 661 int dfsplen; ··· 712 return inode; 713 714 cifs_sb = CIFS_SB(inode->i_sb); 715 - full_path = build_path_to_root(cifs_sb); 716 if (full_path == NULL) 717 return ERR_PTR(-ENOMEM); 718 ··· 1051 return rc; 1052 } 1053 1054 - static void posix_fill_in_inode(struct inode *tmp_inode, 1055 FILE_UNIX_BASIC_INFO *pData, int isNewInode) 1056 { 1057 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); ··· 1148 else 1149 direntry->d_op = &cifs_dentry_ops; 1150 1151 - newinode = new_inode(inode->i_sb); 1152 if (newinode == NULL) { 1153 kfree(pInfo); 1154 goto mkdir_get_info; 1155 } 1156 1157 - /* Is an i_ino of zero legal? */ 1158 - /* Are there sanity checks we can use to ensure that 1159 - the server is really filling in that field? */ 1160 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 1161 - newinode->i_ino = 1162 - (unsigned long)pInfo->UniqueId; 1163 - } /* note ino incremented to unique num in new_inode */ 1164 - if (inode->i_sb->s_flags & MS_NOATIME) 1165 - newinode->i_flags |= S_NOATIME | S_NOCMTIME; 1166 newinode->i_nlink = 2; 1167 - 1168 - insert_inode_hash(newinode); 1169 d_instantiate(direntry, newinode); 1170 1171 /* we already checked in POSIXCreate whether
··· 199 pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); 200 } 201 202 + /** 203 + * cifs_new inode - create new inode, initialize, and hash it 204 + * @sb - pointer to superblock 205 + * @inum - if valid pointer and serverino is enabled, replace i_ino with val 206 + * 207 + * Create a new inode, initialize it for CIFS and hash it. Returns the new 208 + * inode or NULL if one couldn't be allocated. 209 + * 210 + * If the share isn't mounted with "serverino" or inum is a NULL pointer then 211 + * we'll just use the inode number assigned by new_inode(). Note that this can 212 + * mean i_ino collisions since the i_ino assigned by new_inode is not 213 + * guaranteed to be unique. 214 + */ 215 + struct inode * 216 + cifs_new_inode(struct super_block *sb, __u64 *inum) 217 + { 218 + struct inode *inode; 219 + 220 + inode = new_inode(sb); 221 + if (inode == NULL) 222 + return NULL; 223 + 224 + /* 225 + * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we 226 + * stop passing inum as ptr. Are there sanity checks we can use to 227 + * ensure that the server is really filling in that field? Also, 228 + * if serverino is disabled, perhaps we should be using iunique()? 229 + */ 230 + if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) 231 + inode->i_ino = (unsigned long) *inum; 232 + 233 + /* 234 + * must set this here instead of cifs_alloc_inode since VFS will 235 + * clobber i_flags 236 + */ 237 + if (sb->s_flags & MS_NOATIME) 238 + inode->i_flags |= S_NOATIME | S_NOCMTIME; 239 + 240 + insert_inode_hash(inode); 241 + 242 + return inode; 243 + } 244 + 245 int cifs_get_inode_info_unix(struct inode **pinode, 246 const unsigned char *full_path, struct super_block *sb, int xid) 247 { ··· 233 234 /* get new inode */ 235 if (*pinode == NULL) { 236 + *pinode = cifs_new_inode(sb, &find_data.UniqueId); 237 if (*pinode == NULL) { 238 rc = -ENOMEM; 239 goto cgiiu_exit; 240 } 241 } 242 243 inode = *pinode; ··· 465 466 /* get new inode */ 467 if (*pinode == NULL) { 468 + __u64 inode_num; 469 + __u64 *pinum = &inode_num; 470 + 471 /* Is an i_ino of zero legal? Can we use that to check 472 if the server supports returning inode numbers? Are 473 there other sanity checks we can use to ensure that ··· 486 487 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 488 int rc1 = 0; 489 490 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 491 + full_path, pinum, 492 cifs_sb->local_nls, 493 cifs_sb->mnt_cifs_flags & 494 CIFS_MOUNT_MAP_SPECIAL_CHR); 495 if (rc1) { 496 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 497 + pinum = NULL; 498 /* BB EOPNOSUPP disable SERVER_INUM? */ 499 + } 500 + } else { 501 + pinum = NULL; 502 + } 503 + 504 + *pinode = cifs_new_inode(sb, pinum); 505 + if (*pinode == NULL) { 506 + rc = -ENOMEM; 507 + goto cgii_exit; 508 + } 509 } 510 inode = *pinode; 511 cifsInfo = CIFS_I(inode); ··· 621 .lookup = cifs_lookup, 622 }; 623 624 + char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) 625 { 626 int pplen = cifs_sb->prepathlen; 627 int dfsplen; ··· 678 return inode; 679 680 cifs_sb = CIFS_SB(inode->i_sb); 681 + full_path = cifs_build_path_to_root(cifs_sb); 682 if (full_path == NULL) 683 return ERR_PTR(-ENOMEM); 684 ··· 1017 return rc; 1018 } 1019 1020 + void posix_fill_in_inode(struct inode *tmp_inode, 1021 FILE_UNIX_BASIC_INFO *pData, int isNewInode) 1022 { 1023 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); ··· 1114 else 1115 direntry->d_op = &cifs_dentry_ops; 1116 1117 + newinode = cifs_new_inode(inode->i_sb, 1118 + &pInfo->UniqueId); 1119 if (newinode == NULL) { 1120 kfree(pInfo); 1121 goto mkdir_get_info; 1122 } 1123 1124 newinode->i_nlink = 2; 1125 d_instantiate(direntry, newinode); 1126 1127 /* we already checked in POSIXCreate whether
+26 -32
fs/cifs/readdir.c
··· 56 } 57 #endif /* DEBUG2 */ 58 59 - /* Returns one if new inode created (which therefore needs to be hashed) */ 60 /* Might check in the future if inode number changed so we can rehash inode */ 61 - static int construct_dentry(struct qstr *qstring, struct file *file, 62 - struct inode **ptmp_inode, struct dentry **pnew_dentry) 63 { 64 - struct dentry *tmp_dentry; 65 - struct cifs_sb_info *cifs_sb; 66 - struct cifsTconInfo *pTcon; 67 int rc = 0; 68 69 cFYI(1, ("For %s", qstring->name)); 70 - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 71 - pTcon = cifs_sb->tcon; 72 73 qstring->hash = full_name_hash(qstring->name, qstring->len); 74 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 75 if (tmp_dentry) { 76 cFYI(0, ("existing dentry with inode 0x%p", 77 tmp_dentry->d_inode)); 78 *ptmp_inode = tmp_dentry->d_inode; 79 - /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ 80 if (*ptmp_inode == NULL) { 81 - *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 82 if (*ptmp_inode == NULL) 83 return rc; 84 rc = 1; 85 } 86 - if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 87 - (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 88 } else { 89 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 90 if (tmp_dentry == NULL) { ··· 92 return rc; 93 } 94 95 - *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 96 - if (pTcon->nocase) 97 tmp_dentry->d_op = &cifs_ci_dentry_ops; 98 else 99 tmp_dentry->d_op = &cifs_dentry_ops; 100 if (*ptmp_inode == NULL) 101 return rc; 102 - if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 103 - (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 104 rc = 2; 105 } 106 ··· 820 /* inode num, inode type and filename returned */ 821 static int cifs_get_name_from_search_buf(struct qstr *pqst, 822 char *current_entry, __u16 level, unsigned int unicode, 823 - struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum) 824 { 825 int rc = 0; 826 unsigned int len = 0; ··· 840 len = strnlen(filename, PATH_MAX); 841 } 842 843 - /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */ 844 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 845 - *pinum = pFindData->UniqueId; 846 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 847 FILE_DIRECTORY_INFO *pFindData = 848 (FILE_DIRECTORY_INFO *)current_entry; ··· 903 struct qstr qstring; 904 struct cifsFileInfo *pCifsF; 905 unsigned int obj_type; 906 - ino_t inum; 907 struct cifs_sb_info *cifs_sb; 908 struct inode *tmp_inode; 909 struct dentry *tmp_dentry; ··· 936 if (rc) 937 return rc; 938 939 - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); 940 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) 941 return -ENOMEM; 942 - 943 - if (rc) { 944 - /* inode created, we need to hash it with right inode number */ 945 - if (inum != 0) { 946 - /* BB fixme - hash the 2 32 quantities bits together if 947 - * necessary BB */ 948 - tmp_inode->i_ino = inum; 949 - } 950 - insert_inode_hash(tmp_inode); 951 - } 952 953 /* we pass in rc below, indicating whether it is a new inode, 954 so we can figure out whether to invalidate the inode cached
··· 56 } 57 #endif /* DEBUG2 */ 58 59 + /* Returns 1 if new inode created, 2 if both dentry and inode were */ 60 /* Might check in the future if inode number changed so we can rehash inode */ 61 + static int 62 + construct_dentry(struct qstr *qstring, struct file *file, 63 + struct inode **ptmp_inode, struct dentry **pnew_dentry, 64 + __u64 *inum) 65 { 66 + struct dentry *tmp_dentry = NULL; 67 + struct super_block *sb = file->f_path.dentry->d_sb; 68 int rc = 0; 69 70 cFYI(1, ("For %s", qstring->name)); 71 72 qstring->hash = full_name_hash(qstring->name, qstring->len); 73 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 74 if (tmp_dentry) { 75 + /* BB: overwrite old name? i.e. tmp_dentry->d_name and 76 + * tmp_dentry->d_name.len?? 77 + */ 78 cFYI(0, ("existing dentry with inode 0x%p", 79 tmp_dentry->d_inode)); 80 *ptmp_inode = tmp_dentry->d_inode; 81 if (*ptmp_inode == NULL) { 82 + *ptmp_inode = cifs_new_inode(sb, inum); 83 if (*ptmp_inode == NULL) 84 return rc; 85 rc = 1; 86 } 87 } else { 88 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 89 if (tmp_dentry == NULL) { ··· 93 return rc; 94 } 95 96 + if (CIFS_SB(sb)->tcon->nocase) 97 tmp_dentry->d_op = &cifs_ci_dentry_ops; 98 else 99 tmp_dentry->d_op = &cifs_dentry_ops; 100 + 101 + *ptmp_inode = cifs_new_inode(sb, inum); 102 if (*ptmp_inode == NULL) 103 return rc; 104 rc = 2; 105 } 106 ··· 822 /* inode num, inode type and filename returned */ 823 static int cifs_get_name_from_search_buf(struct qstr *pqst, 824 char *current_entry, __u16 level, unsigned int unicode, 825 + struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) 826 { 827 int rc = 0; 828 unsigned int len = 0; ··· 842 len = strnlen(filename, PATH_MAX); 843 } 844 845 + *pinum = pFindData->UniqueId; 846 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 847 FILE_DIRECTORY_INFO *pFindData = 848 (FILE_DIRECTORY_INFO *)current_entry; ··· 907 struct qstr qstring; 908 struct cifsFileInfo *pCifsF; 909 unsigned int obj_type; 910 + __u64 inum; 911 struct cifs_sb_info *cifs_sb; 912 struct inode *tmp_inode; 913 struct dentry *tmp_dentry; ··· 940 if (rc) 941 return rc; 942 943 + /* only these two infolevels return valid inode numbers */ 944 + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || 945 + pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) 946 + rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, 947 + &inum); 948 + else 949 + rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, 950 + NULL); 951 + 952 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) 953 return -ENOMEM; 954 955 /* we pass in rc below, indicating whether it is a new inode, 956 so we can figure out whether to invalidate the inode cached
+87 -4
fs/cifs/sess.c
··· 34 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 35 unsigned char *p24); 36 37 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) 38 { 39 __u32 capabilities = 0; 40 41 /* init fields common to all four types of SessSetup */ 42 - /* note that header is initialized to zero in header_assemble */ 43 pSMB->req.AndXCommand = 0xFF; 44 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 45 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 46 47 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ 48 ··· 155 if (ses->capabilities & CAP_UNIX) 156 capabilities |= CAP_UNIX; 157 158 - /* BB check whether to init vcnum BB */ 159 return capabilities; 160 } 161 ··· 311 312 kfree(ses->serverOS); 313 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 314 - ses->serverOS = kzalloc(4 * len, GFP_KERNEL); 315 if (ses->serverOS != NULL) 316 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 317 data += 2 * (len + 1); ··· 324 return rc; 325 326 kfree(ses->serverNOS); 327 - ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ 328 if (ses->serverNOS != NULL) { 329 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 330 nls_cp);
··· 34 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 35 unsigned char *p24); 36 37 + /* Checks if this is the first smb session to be reconnected after 38 + the socket has been reestablished (so we know whether to use vc 0). 39 + Called while holding the cifs_tcp_ses_lock, so do not block */ 40 + static bool is_first_ses_reconnect(struct cifsSesInfo *ses) 41 + { 42 + struct list_head *tmp; 43 + struct cifsSesInfo *tmp_ses; 44 + 45 + list_for_each(tmp, &ses->server->smb_ses_list) { 46 + tmp_ses = list_entry(tmp, struct cifsSesInfo, 47 + smb_ses_list); 48 + if (tmp_ses->need_reconnect == false) 49 + return false; 50 + } 51 + /* could not find a session that was already connected, 52 + this must be the first one we are reconnecting */ 53 + return true; 54 + } 55 + 56 + /* 57 + * vc number 0 is treated specially by some servers, and should be the 58 + * first one we request. After that we can use vcnumbers up to maxvcs, 59 + * one for each smb session (some Windows versions set maxvcs incorrectly 60 + * so maxvc=1 can be ignored). If we have too many vcs, we can reuse 61 + * any vc but zero (some servers reset the connection on vcnum zero) 62 + * 63 + */ 64 + static __le16 get_next_vcnum(struct cifsSesInfo *ses) 65 + { 66 + __u16 vcnum = 0; 67 + struct list_head *tmp; 68 + struct cifsSesInfo *tmp_ses; 69 + __u16 max_vcs = ses->server->max_vcs; 70 + __u16 i; 71 + int free_vc_found = 0; 72 + 73 + /* Quoting the MS-SMB specification: "Windows-based SMB servers set this 74 + field to one but do not enforce this limit, which allows an SMB client 75 + to establish more virtual circuits than allowed by this value ... but 76 + other server implementations can enforce this limit." */ 77 + if (max_vcs < 2) 78 + max_vcs = 0xFFFF; 79 + 80 + write_lock(&cifs_tcp_ses_lock); 81 + if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) 82 + goto get_vc_num_exit; /* vcnum will be zero */ 83 + for (i = ses->server->srv_count - 1; i < max_vcs; i++) { 84 + if (i == 0) /* this is the only connection, use vc 0 */ 85 + break; 86 + 87 + free_vc_found = 1; 88 + 89 + list_for_each(tmp, &ses->server->smb_ses_list) { 90 + tmp_ses = list_entry(tmp, struct cifsSesInfo, 91 + smb_ses_list); 92 + if (tmp_ses->vcnum == i) { 93 + free_vc_found = 0; 94 + break; /* found duplicate, try next vcnum */ 95 + } 96 + } 97 + if (free_vc_found) 98 + break; /* we found a vcnumber that will work - use it */ 99 + } 100 + 101 + if (i == 0) 102 + vcnum = 0; /* for most common case, ie if one smb session, use 103 + vc zero. Also for case when no free vcnum, zero 104 + is safest to send (some clients only send zero) */ 105 + else if (free_vc_found == 0) 106 + vcnum = 1; /* we can not reuse vc=0 safely, since some servers 107 + reset all uids on that, but 1 is ok. */ 108 + else 109 + vcnum = i; 110 + ses->vcnum = vcnum; 111 + get_vc_num_exit: 112 + write_unlock(&cifs_tcp_ses_lock); 113 + 114 + return le16_to_cpu(vcnum); 115 + } 116 + 117 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) 118 { 119 __u32 capabilities = 0; 120 121 /* init fields common to all four types of SessSetup */ 122 + /* Note that offsets for first seven fields in req struct are same */ 123 + /* in CIFS Specs so does not matter which of 3 forms of struct */ 124 + /* that we use in next few lines */ 125 + /* Note that header is initialized to zero in header_assemble */ 126 pSMB->req.AndXCommand = 0xFF; 127 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 128 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 129 + pSMB->req.VcNumber = get_next_vcnum(ses); 130 131 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ 132 ··· 71 if (ses->capabilities & CAP_UNIX) 72 capabilities |= CAP_UNIX; 73 74 return capabilities; 75 } 76 ··· 228 229 kfree(ses->serverOS); 230 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 231 + ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 232 if (ses->serverOS != NULL) 233 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 234 data += 2 * (len + 1); ··· 241 return rc; 242 243 kfree(ses->serverNOS); 244 + ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 245 if (ses->serverNOS != NULL) { 246 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 247 nls_cp);