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.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 + 1 11 Version 1.56 2 12 ------------ 3 13 Add "forcemandatorylock" mount option to allow user to use mandatory ··· 17 7 top of the share. Fix problem in 2.6.28 resolving DFS paths to 18 8 Samba servers (worked to Windows). Fix rmdir so that pending search 19 9 (readdir) requests do not get invalid results which include the now 20 - removed directory. 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). 21 14 22 15 Version 1.55 23 16 ------------
+1 -1
fs/cifs/cifsfs.h
··· 100 100 extern const struct export_operations cifs_export_ops; 101 101 #endif /* EXPERIMENTAL */ 102 102 103 - #define CIFS_VERSION "1.56" 103 + #define CIFS_VERSION "1.57" 104 104 #endif /* _CIFSFS_H */
+5 -1
fs/cifs/cifsglob.h
··· 164 164 /* multiplexed reads or writes */ 165 165 unsigned int maxBuf; /* maxBuf specifies the maximum */ 166 166 /* message size the server can send or receive for non-raw SMBs */ 167 - unsigned int maxRw; /* maxRw specifies the maximum */ 167 + unsigned int max_rw; /* maxRw specifies the maximum */ 168 168 /* message size the server can send or receive for */ 169 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 */ 170 173 char sessid[4]; /* unique token id for this session */ 171 174 /* (returned on Negotiate */ 172 175 int capabilities; /* allow selective disabling of caps by smb sess */ ··· 213 210 unsigned overrideSecFlg; /* if non-zero override global sec flags */ 214 211 __u16 ipc_tid; /* special tid for connection to IPC share */ 215 212 __u16 flags; 213 + __u16 vcnum; 216 214 char *serverOS; /* name of operating system underlying server */ 217 215 char *serverNOS; /* name of network operating system of server */ 218 216 char *serverDomain; /* security realm of server */
+4
fs/cifs/cifsproto.h
··· 42 42 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); 43 43 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 44 44 extern char *build_path_from_dentry(struct dentry *); 45 + extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); 45 46 extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46 47 /* extern void renew_parental_timestamps(struct dentry *direntry);*/ 47 48 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, ··· 92 91 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 93 92 extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 94 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); 95 97 extern int cifs_get_inode_info(struct inode **pinode, 96 98 const unsigned char *search_path, 97 99 FILE_ALL_INFO *pfile_info,
+4 -3
fs/cifs/cifssmb.c
··· 528 528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount); 529 529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 530 530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 531 + server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 531 532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); 532 533 /* even though we do not use raw we might as well set this 533 534 accurately, in case we ever find a need for it */ 534 535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 535 - server->maxRw = 0xFF00; 536 + server->max_rw = 0xFF00; 536 537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; 537 538 } else { 538 - server->maxRw = 0;/* we do not need to use raw anyway */ 539 + server->max_rw = 0;/* do not need to use raw anyway */ 539 540 server->capabilities = CAP_MPX_MODE; 540 541 } 541 542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); ··· 639 638 /* probably no need to store and check maxvcs */ 640 639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), 641 640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 642 - server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 641 + server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 643 642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); 644 643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 645 644 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+48 -3
fs/cifs/connect.c
··· 23 23 #include <linux/string.h> 24 24 #include <linux/list.h> 25 25 #include <linux/wait.h> 26 - #include <linux/ipv6.h> 27 26 #include <linux/pagemap.h> 28 27 #include <linux/ctype.h> 29 28 #include <linux/utsname.h> ··· 34 35 #include <linux/freezer.h> 35 36 #include <asm/uaccess.h> 36 37 #include <asm/processor.h> 38 + #include <net/ipv6.h> 37 39 #include "cifspdu.h" 38 40 #include "cifsglob.h" 39 41 #include "cifsproto.h" ··· 1379 1379 server->addr.sockAddr.sin_addr.s_addr)) 1380 1380 continue; 1381 1381 else if (addr->ss_family == AF_INET6 && 1382 - memcmp(&server->addr.sockAddr6.sin6_addr, 1383 - &addr6->sin6_addr, sizeof(addr6->sin6_addr))) 1382 + !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, 1383 + &addr6->sin6_addr)) 1384 1384 continue; 1385 1385 1386 1386 ++server->srv_count; ··· 2180 2180 "mount option supported")); 2181 2181 } 2182 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 + 2183 2210 int 2184 2211 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2185 2212 char *mount_data, const char *devname) ··· 2217 2190 struct cifsSesInfo *pSesInfo = NULL; 2218 2191 struct cifsTconInfo *tcon = NULL; 2219 2192 struct TCP_Server_Info *srvTcp = NULL; 2193 + char *full_path; 2220 2194 2221 2195 xid = GetXid(); 2222 2196 ··· 2453 2425 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) 2454 2426 cifs_sb->rsize = min(cifs_sb->rsize, 2455 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 + } 2456 2445 2457 2446 /* volume_info->password is freed above when existing session found 2458 2447 (in which case it is not needed anymore) but when new sesion is created
+202 -99
fs/cifs/dir.c
··· 3 3 * 4 4 * vfs operations that deal with dentries 5 5 * 6 - * Copyright (C) International Business Machines Corp., 2002,2008 6 + * Copyright (C) International Business Machines Corp., 2002,2009 7 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 8 * 9 9 * This library is free software; you can redistribute it and/or modify ··· 129 129 return full_path; 130 130 } 131 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 + 132 204 static void setup_cifs_dentry(struct cifsTconInfo *tcon, 133 205 struct dentry *direntry, 134 206 struct inode *newinode) ··· 222 150 int xid; 223 151 int create_options = CREATE_NOT_DIR; 224 152 int oplock = 0; 225 - /* BB below access is too much for the mknod to request */ 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 + */ 226 161 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 227 162 __u16 fileHandle; 228 163 struct cifs_sb_info *cifs_sb; ··· 253 174 } 254 175 255 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 + } 256 207 257 208 if (nd && (nd->flags & LOOKUP_OPEN)) { 258 - int oflags = nd->intent.open.flags; 259 - 209 + /* if the file is going to stay open, then we 210 + need to set the desired access properly */ 260 211 desiredAccess = 0; 261 212 if (oflags & FMODE_READ) 262 - desiredAccess |= GENERIC_READ; 213 + desiredAccess |= GENERIC_READ; /* is this too little? */ 263 214 if (oflags & FMODE_WRITE) { 264 215 desiredAccess |= GENERIC_WRITE; 265 216 if (!(oflags & FMODE_READ)) ··· 308 199 309 200 /* BB add processing to set equivalent of mode - e.g. via CreateX with 310 201 ACLs */ 311 - if (oplockEnabled) 312 - oplock = REQ_OPLOCK; 313 202 314 203 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 315 204 if (buf == NULL) { ··· 340 233 } 341 234 if (rc) { 342 235 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 = { 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 = { 348 243 .mode = mode, 349 244 .ctime = NO_CHANGE_64, 350 245 .atime = NO_CHANGE_64, 351 246 .mtime = NO_CHANGE_64, 352 247 .device = 0, 353 - }; 248 + }; 354 249 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); 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(); 369 256 } 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 */ 257 + args.uid = NO_CHANGE_64; 258 + args.gid = NO_CHANGE_64; 375 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);*/ 376 267 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 - } 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(); 400 289 } 401 290 } 291 + } 402 292 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); 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)); 408 298 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); 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); 416 306 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); 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); 428 318 429 - /* set the following in open now 319 + /* set the following in open now 430 320 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; 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); 450 332 } 451 - write_unlock(&GlobalSMBSeslock); 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; 452 340 } 341 + write_unlock(&GlobalSMBSeslock); 453 342 } 454 343 cifs_create_out: 455 344 kfree(buf);
+64 -40
fs/cifs/inode.c
··· 199 199 pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); 200 200 } 201 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 + 202 245 int cifs_get_inode_info_unix(struct inode **pinode, 203 246 const unsigned char *full_path, struct super_block *sb, int xid) 204 247 { ··· 276 233 277 234 /* get new inode */ 278 235 if (*pinode == NULL) { 279 - *pinode = new_inode(sb); 236 + *pinode = cifs_new_inode(sb, &find_data.UniqueId); 280 237 if (*pinode == NULL) { 281 238 rc = -ENOMEM; 282 239 goto cgiiu_exit; 283 240 } 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 241 } 296 242 297 243 inode = *pinode; ··· 497 465 498 466 /* get new inode */ 499 467 if (*pinode == NULL) { 500 - *pinode = new_inode(sb); 501 - if (*pinode == NULL) { 502 - rc = -ENOMEM; 503 - goto cgii_exit; 504 - } 468 + __u64 inode_num; 469 + __u64 *pinum = &inode_num; 470 + 505 471 /* Is an i_ino of zero legal? Can we use that to check 506 472 if the server supports returning inode numbers? Are 507 473 there other sanity checks we can use to ensure that ··· 516 486 517 487 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 518 488 int rc1 = 0; 519 - __u64 inode_num; 520 489 521 490 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 522 - full_path, &inode_num, 491 + full_path, pinum, 523 492 cifs_sb->local_nls, 524 493 cifs_sb->mnt_cifs_flags & 525 494 CIFS_MOUNT_MAP_SPECIAL_CHR); 526 495 if (rc1) { 527 496 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 497 + pinum = NULL; 528 498 /* 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); 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 + } 535 509 } 536 510 inode = *pinode; 537 511 cifsInfo = CIFS_I(inode); ··· 655 621 .lookup = cifs_lookup, 656 622 }; 657 623 658 - static char *build_path_to_root(struct cifs_sb_info *cifs_sb) 624 + char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) 659 625 { 660 626 int pplen = cifs_sb->prepathlen; 661 627 int dfsplen; ··· 712 678 return inode; 713 679 714 680 cifs_sb = CIFS_SB(inode->i_sb); 715 - full_path = build_path_to_root(cifs_sb); 681 + full_path = cifs_build_path_to_root(cifs_sb); 716 682 if (full_path == NULL) 717 683 return ERR_PTR(-ENOMEM); 718 684 ··· 1051 1017 return rc; 1052 1018 } 1053 1019 1054 - static void posix_fill_in_inode(struct inode *tmp_inode, 1020 + void posix_fill_in_inode(struct inode *tmp_inode, 1055 1021 FILE_UNIX_BASIC_INFO *pData, int isNewInode) 1056 1022 { 1057 1023 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); ··· 1148 1114 else 1149 1115 direntry->d_op = &cifs_dentry_ops; 1150 1116 1151 - newinode = new_inode(inode->i_sb); 1117 + newinode = cifs_new_inode(inode->i_sb, 1118 + &pInfo->UniqueId); 1152 1119 if (newinode == NULL) { 1153 1120 kfree(pInfo); 1154 1121 goto mkdir_get_info; 1155 1122 } 1156 1123 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 1124 newinode->i_nlink = 2; 1167 - 1168 - insert_inode_hash(newinode); 1169 1125 d_instantiate(direntry, newinode); 1170 1126 1171 1127 /* we already checked in POSIXCreate whether
+26 -32
fs/cifs/readdir.c
··· 56 56 } 57 57 #endif /* DEBUG2 */ 58 58 59 - /* Returns one if new inode created (which therefore needs to be hashed) */ 59 + /* Returns 1 if new inode created, 2 if both dentry and inode were */ 60 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) 61 + static int 62 + construct_dentry(struct qstr *qstring, struct file *file, 63 + struct inode **ptmp_inode, struct dentry **pnew_dentry, 64 + __u64 *inum) 63 65 { 64 - struct dentry *tmp_dentry; 65 - struct cifs_sb_info *cifs_sb; 66 - struct cifsTconInfo *pTcon; 66 + struct dentry *tmp_dentry = NULL; 67 + struct super_block *sb = file->f_path.dentry->d_sb; 67 68 int rc = 0; 68 69 69 70 cFYI(1, ("For %s", qstring->name)); 70 - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 71 - pTcon = cifs_sb->tcon; 72 71 73 72 qstring->hash = full_name_hash(qstring->name, qstring->len); 74 73 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 75 74 if (tmp_dentry) { 75 + /* BB: overwrite old name? i.e. tmp_dentry->d_name and 76 + * tmp_dentry->d_name.len?? 77 + */ 76 78 cFYI(0, ("existing dentry with inode 0x%p", 77 79 tmp_dentry->d_inode)); 78 80 *ptmp_inode = tmp_dentry->d_inode; 79 - /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ 80 81 if (*ptmp_inode == NULL) { 81 - *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 82 + *ptmp_inode = cifs_new_inode(sb, inum); 82 83 if (*ptmp_inode == NULL) 83 84 return rc; 84 85 rc = 1; 85 86 } 86 - if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 87 - (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 88 87 } else { 89 88 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 90 89 if (tmp_dentry == NULL) { ··· 92 93 return rc; 93 94 } 94 95 95 - *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 96 - if (pTcon->nocase) 96 + if (CIFS_SB(sb)->tcon->nocase) 97 97 tmp_dentry->d_op = &cifs_ci_dentry_ops; 98 98 else 99 99 tmp_dentry->d_op = &cifs_dentry_ops; 100 + 101 + *ptmp_inode = cifs_new_inode(sb, inum); 100 102 if (*ptmp_inode == NULL) 101 103 return rc; 102 - if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 103 - (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 104 104 rc = 2; 105 105 } 106 106 ··· 820 822 /* inode num, inode type and filename returned */ 821 823 static int cifs_get_name_from_search_buf(struct qstr *pqst, 822 824 char *current_entry, __u16 level, unsigned int unicode, 823 - struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum) 825 + struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) 824 826 { 825 827 int rc = 0; 826 828 unsigned int len = 0; ··· 840 842 len = strnlen(filename, PATH_MAX); 841 843 } 842 844 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; 845 + *pinum = pFindData->UniqueId; 846 846 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 847 847 FILE_DIRECTORY_INFO *pFindData = 848 848 (FILE_DIRECTORY_INFO *)current_entry; ··· 903 907 struct qstr qstring; 904 908 struct cifsFileInfo *pCifsF; 905 909 unsigned int obj_type; 906 - ino_t inum; 910 + __u64 inum; 907 911 struct cifs_sb_info *cifs_sb; 908 912 struct inode *tmp_inode; 909 913 struct dentry *tmp_dentry; ··· 936 940 if (rc) 937 941 return rc; 938 942 939 - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); 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 + 940 952 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) 941 953 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 954 953 955 /* we pass in rc below, indicating whether it is a new inode, 954 956 so we can figure out whether to invalidate the inode cached
+87 -4
fs/cifs/sess.c
··· 34 34 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 35 35 unsigned char *p24); 36 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 + 37 117 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) 38 118 { 39 119 __u32 capabilities = 0; 40 120 41 121 /* init fields common to all four types of SessSetup */ 42 - /* note that header is initialized to zero in header_assemble */ 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 */ 43 126 pSMB->req.AndXCommand = 0xFF; 44 127 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 45 128 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 129 + pSMB->req.VcNumber = get_next_vcnum(ses); 46 130 47 131 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ 48 132 ··· 155 71 if (ses->capabilities & CAP_UNIX) 156 72 capabilities |= CAP_UNIX; 157 73 158 - /* BB check whether to init vcnum BB */ 159 74 return capabilities; 160 75 } 161 76 ··· 311 228 312 229 kfree(ses->serverOS); 313 230 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 314 - ses->serverOS = kzalloc(4 * len, GFP_KERNEL); 231 + ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 315 232 if (ses->serverOS != NULL) 316 233 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 317 234 data += 2 * (len + 1); ··· 324 241 return rc; 325 242 326 243 kfree(ses->serverNOS); 327 - ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ 244 + ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 328 245 if (ses->serverNOS != NULL) { 329 246 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 330 247 nls_cp);