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: when renaming don't try to unlink negative dentry
cifs: remove unneeded bcc_ptr update in CIFSTCon
cifs: add cFYI messages with some of the saved strings from ssetup/tcon
cifs: fix buffer size for tcon->nativeFileSystem field
cifs: fix unicode string area word alignment in session setup
[CIFS] Fix build break caused by change to new current_umask helper function
[CIFS] Fix sparse warnings
[CIFS] Add support for posix open during lookup
cifs: no need to use rcu_assign_pointer on immutable keys
cifs: remove dnotify thread code
[CIFS] remove some build warnings
cifs: vary timeout on writes past EOF based on offset (try #5)
[CIFS] Fix build break from recent DFS patch when DFS support not enabled
Remote DFS root support.
[CIFS] Endian convert UniqueId when reporting inode numbers from server files
cifs: remove some pointless conditionals before kfree()
cifs: flush data on any setattr

+405 -270
+2 -1
fs/cifs/CHANGES
··· 15 15 fails to support it properly, as with Samba server versions prior to 3.3.2) 16 16 Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too 17 17 little memory for the "nativeFileSystem" field returned by the server 18 - during mount). 18 + during mount). Endian convert inode numbers if necessary (makes it easier 19 + to compare inode numbers on network files from big endian systems). 19 20 20 21 Version 1.56 21 22 ------------
+1 -1
fs/cifs/cifs_spnego.c
··· 41 41 42 42 /* attach the data */ 43 43 memcpy(payload, data, datalen); 44 - rcu_assign_pointer(key->payload.data, payload); 44 + key->payload.data = payload; 45 45 ret = 0; 46 46 47 47 error:
+1 -47
fs/cifs/cifsfs.c
··· 66 66 extern struct task_struct *oplockThread; /* remove sparse warning */ 67 67 struct task_struct *oplockThread = NULL; 68 68 /* extern struct task_struct * dnotifyThread; remove sparse warning */ 69 - #ifdef CONFIG_CIFS_EXPERIMENTAL 70 - static struct task_struct *dnotifyThread = NULL; 71 - #endif 72 69 static const struct super_operations cifs_super_ops; 73 70 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 74 71 module_param(CIFSMaxBufSize, int, 0); ··· 313 316 cifs_inode->clientCanCacheAll = false; 314 317 cifs_inode->delete_pending = false; 315 318 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 319 + cifs_inode->server_eof = 0; 316 320 317 321 /* Can not set i_flags here - they get immediately overwritten 318 322 to zero by the VFS */ ··· 1038 1040 return 0; 1039 1041 } 1040 1042 1041 - #ifdef CONFIG_CIFS_EXPERIMENTAL 1042 - static int cifs_dnotify_thread(void *dummyarg) 1043 - { 1044 - struct list_head *tmp; 1045 - struct TCP_Server_Info *server; 1046 - 1047 - do { 1048 - if (try_to_freeze()) 1049 - continue; 1050 - set_current_state(TASK_INTERRUPTIBLE); 1051 - schedule_timeout(15*HZ); 1052 - /* check if any stuck requests that need 1053 - to be woken up and wakeq so the 1054 - thread can wake up and error out */ 1055 - read_lock(&cifs_tcp_ses_lock); 1056 - list_for_each(tmp, &cifs_tcp_ses_list) { 1057 - server = list_entry(tmp, struct TCP_Server_Info, 1058 - tcp_ses_list); 1059 - if (atomic_read(&server->inFlight)) 1060 - wake_up_all(&server->response_q); 1061 - } 1062 - read_unlock(&cifs_tcp_ses_lock); 1063 - } while (!kthread_should_stop()); 1064 - 1065 - return 0; 1066 - } 1067 - #endif 1068 - 1069 1043 static int __init 1070 1044 init_cifs(void) 1071 1045 { ··· 1114 1144 goto out_unregister_dfs_key_type; 1115 1145 } 1116 1146 1117 - #ifdef CONFIG_CIFS_EXPERIMENTAL 1118 - dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); 1119 - if (IS_ERR(dnotifyThread)) { 1120 - rc = PTR_ERR(dnotifyThread); 1121 - cERROR(1, ("error %d create dnotify thread", rc)); 1122 - goto out_stop_oplock_thread; 1123 - } 1124 - #endif 1125 - 1126 1147 return 0; 1127 1148 1128 - #ifdef CONFIG_CIFS_EXPERIMENTAL 1129 - out_stop_oplock_thread: 1130 - #endif 1131 - kthread_stop(oplockThread); 1132 1149 out_unregister_dfs_key_type: 1133 1150 #ifdef CONFIG_CIFS_DFS_UPCALL 1134 1151 unregister_key_type(&key_type_dns_resolver); ··· 1153 1196 cifs_destroy_inodecache(); 1154 1197 cifs_destroy_mids(); 1155 1198 cifs_destroy_request_bufs(); 1156 - #ifdef CONFIG_CIFS_EXPERIMENTAL 1157 - kthread_stop(dnotifyThread); 1158 - #endif 1159 1199 kthread_stop(oplockThread); 1160 1200 } 1161 1201
+2 -1
fs/cifs/cifsglob.h
··· 350 350 bool invalidHandle:1; /* file closed via session abend */ 351 351 bool messageMode:1; /* for pipes: message vs byte mode */ 352 352 atomic_t wrtPending; /* handle in use - defer close */ 353 - struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 353 + struct mutex fh_mutex; /* prevents reopen race after dead ses*/ 354 354 struct cifs_search_info srch_inf; 355 355 }; 356 356 ··· 370 370 bool clientCanCacheAll:1; /* read and writebehind oplock */ 371 371 bool oplockPending:1; 372 372 bool delete_pending:1; /* DELETE_ON_CLOSE is set */ 373 + u64 server_eof; /* current file size on server */ 373 374 struct inode vfs_inode; 374 375 }; 375 376
+4 -4
fs/cifs/cifspdu.h
··· 2163 2163 __le32 Type; 2164 2164 __le64 DevMajor; 2165 2165 __le64 DevMinor; 2166 - __u64 UniqueId; 2166 + __le64 UniqueId; 2167 2167 __le64 Permissions; 2168 2168 __le64 Nlinks; 2169 2169 } __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ ··· 2308 2308 } __attribute__((packed)); 2309 2309 2310 2310 struct file_internal_info { 2311 - __u64 UniqueId; /* inode number */ 2311 + __le64 UniqueId; /* inode number */ 2312 2312 } __attribute__((packed)); /* level 0x3ee */ 2313 2313 2314 2314 struct file_mode_info { ··· 2338 2338 __le32 Type; 2339 2339 __le64 DevMajor; 2340 2340 __le64 DevMinor; 2341 - __u64 UniqueId; 2341 + __le64 UniqueId; 2342 2342 __le64 Permissions; 2343 2343 __le64 Nlinks; 2344 2344 char FileName[1]; ··· 2386 2386 __le32 FileNameLength; 2387 2387 __le32 EaSize; /* EA size */ 2388 2388 __le32 Reserved; 2389 - __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2389 + __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2390 2390 char FileName[1]; 2391 2391 } __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */ 2392 2392
+3 -3
fs/cifs/cifssmb.c
··· 1626 1626 int smb_hdr_len; 1627 1627 int resp_buf_type = 0; 1628 1628 1629 + *nbytes = 0; 1630 + 1629 1631 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count)); 1630 1632 1631 1633 if (tcon->ses->capabilities & CAP_LARGE_FILES) { ··· 1684 1682 cifs_stats_inc(&tcon->num_writes); 1685 1683 if (rc) { 1686 1684 cFYI(1, ("Send error Write2 = %d", rc)); 1687 - *nbytes = 0; 1688 1685 } else if (resp_buf_type == 0) { 1689 1686 /* presumably this can not happen, but best to be safe */ 1690 1687 rc = -EIO; 1691 - *nbytes = 0; 1692 1688 } else { 1693 1689 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; 1694 1690 *nbytes = le16_to_cpu(pSMBr->CountHigh); ··· 3918 3918 } 3919 3919 pfinfo = (struct file_internal_info *) 3920 3920 (data_offset + (char *) &pSMBr->hdr.Protocol); 3921 - *inode_number = pfinfo->UniqueId; 3921 + *inode_number = le64_to_cpu(pfinfo->UniqueId); 3922 3922 } 3923 3923 } 3924 3924 GetInodeNumOut:
+143 -62
fs/cifs/connect.c
··· 2214 2214 return rc; 2215 2215 } 2216 2216 2217 + static void 2218 + cleanup_volume_info(struct smb_vol **pvolume_info) 2219 + { 2220 + struct smb_vol *volume_info; 2221 + 2222 + if (!pvolume_info && !*pvolume_info) 2223 + return; 2224 + 2225 + volume_info = *pvolume_info; 2226 + kzfree(volume_info->password); 2227 + kfree(volume_info->UNC); 2228 + kfree(volume_info->prepath); 2229 + kfree(volume_info); 2230 + *pvolume_info = NULL; 2231 + return; 2232 + } 2233 + 2234 + #ifdef CONFIG_CIFS_DFS_UPCALL 2235 + /* build_path_to_root returns full path to root when 2236 + * we do not have an exiting connection (tcon) */ 2237 + static char * 2238 + build_unc_path_to_root(const struct smb_vol *volume_info, 2239 + const struct cifs_sb_info *cifs_sb) 2240 + { 2241 + char *full_path; 2242 + 2243 + int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1); 2244 + full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL); 2245 + if (full_path == NULL) 2246 + return ERR_PTR(-ENOMEM); 2247 + 2248 + strncpy(full_path, volume_info->UNC, unc_len); 2249 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { 2250 + int i; 2251 + for (i = 0; i < unc_len; i++) { 2252 + if (full_path[i] == '\\') 2253 + full_path[i] = '/'; 2254 + } 2255 + } 2256 + 2257 + if (cifs_sb->prepathlen) 2258 + strncpy(full_path + unc_len, cifs_sb->prepath, 2259 + cifs_sb->prepathlen); 2260 + 2261 + full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */ 2262 + return full_path; 2263 + } 2264 + #endif 2265 + 2217 2266 int 2218 2267 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2219 - char *mount_data, const char *devname) 2268 + char *mount_data_global, const char *devname) 2220 2269 { 2221 2270 int rc = 0; 2222 2271 int xid; ··· 2274 2225 struct cifsTconInfo *tcon = NULL; 2275 2226 struct TCP_Server_Info *srvTcp = NULL; 2276 2227 char *full_path; 2228 + char *mount_data = mount_data_global; 2229 + #ifdef CONFIG_CIFS_DFS_UPCALL 2230 + struct dfs_info3_param *referrals = NULL; 2231 + unsigned int num_referrals = 0; 2232 + try_mount_again: 2233 + #endif 2234 + full_path = NULL; 2277 2235 2278 2236 xid = GetXid(); 2279 2237 ··· 2427 2371 } 2428 2372 } 2429 2373 2430 - /* check for null share name ie connect to dfs root */ 2431 2374 if ((strchr(volume_info->UNC + 3, '\\') == NULL) 2432 2375 && (strchr(volume_info->UNC + 3, '/') == NULL)) { 2433 - /* rc = connect_to_dfs_path(...) */ 2434 - cFYI(1, ("DFS root not supported")); 2376 + cERROR(1, ("Missing share name")); 2435 2377 rc = -ENODEV; 2436 2378 goto mount_fail_check; 2437 2379 } else { ··· 2446 2392 } 2447 2393 } 2448 2394 if (rc) 2449 - goto mount_fail_check; 2395 + goto remote_path_check; 2450 2396 tcon->seal = volume_info->seal; 2451 2397 write_lock(&cifs_tcp_ses_lock); 2452 2398 list_add(&tcon->tcon_list, &pSesInfo->tcon_list); ··· 2471 2417 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2472 2418 sb->s_time_gran = 100; 2473 2419 2474 - mount_fail_check: 2475 - /* on error free sesinfo and tcon struct if needed */ 2476 - if (rc) { 2477 - /* If find_unc succeeded then rc == 0 so we can not end */ 2478 - /* up accidently freeing someone elses tcon struct */ 2479 - if (tcon) 2480 - cifs_put_tcon(tcon); 2481 - else if (pSesInfo) 2482 - cifs_put_smb_ses(pSesInfo); 2483 - else 2484 - cifs_put_tcp_session(srvTcp); 2485 - goto out; 2486 - } 2420 + if (rc) 2421 + goto remote_path_check; 2422 + 2487 2423 cifs_sb->tcon = tcon; 2488 2424 2489 2425 /* do not care if following two calls succeed - informational */ ··· 2505 2461 cifs_sb->rsize = min(cifs_sb->rsize, 2506 2462 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2507 2463 2508 - if (!rc && cifs_sb->prepathlen) { 2464 + remote_path_check: 2465 + /* check if a whole path (including prepath) is not remote */ 2466 + if (!rc && cifs_sb->prepathlen && tcon) { 2509 2467 /* build_path_to_root works only when we have a valid tcon */ 2510 2468 full_path = cifs_build_path_to_root(cifs_sb); 2511 2469 if (full_path == NULL) { ··· 2515 2469 goto mount_fail_check; 2516 2470 } 2517 2471 rc = is_path_accessible(xid, tcon, cifs_sb, full_path); 2518 - if (rc) { 2519 - cERROR(1, ("Path %s in not accessible: %d", 2520 - full_path, rc)); 2472 + if (rc != -EREMOTE) { 2521 2473 kfree(full_path); 2522 2474 goto mount_fail_check; 2523 2475 } 2524 2476 kfree(full_path); 2477 + } 2478 + 2479 + /* get referral if needed */ 2480 + if (rc == -EREMOTE) { 2481 + #ifdef CONFIG_CIFS_DFS_UPCALL 2482 + /* convert forward to back slashes in prepath here if needed */ 2483 + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) 2484 + convert_delimiter(cifs_sb->prepath, 2485 + CIFS_DIR_SEP(cifs_sb)); 2486 + full_path = build_unc_path_to_root(volume_info, cifs_sb); 2487 + if (IS_ERR(full_path)) { 2488 + rc = PTR_ERR(full_path); 2489 + goto mount_fail_check; 2490 + } 2491 + 2492 + cFYI(1, ("Getting referral for: %s", full_path)); 2493 + rc = get_dfs_path(xid, pSesInfo , full_path + 1, 2494 + cifs_sb->local_nls, &num_referrals, &referrals, 2495 + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 2496 + if (!rc && num_referrals > 0) { 2497 + char *fake_devname = NULL; 2498 + 2499 + if (mount_data != mount_data_global) 2500 + kfree(mount_data); 2501 + mount_data = cifs_compose_mount_options( 2502 + cifs_sb->mountdata, full_path + 1, 2503 + referrals, &fake_devname); 2504 + kfree(fake_devname); 2505 + free_dfs_info_array(referrals, num_referrals); 2506 + 2507 + if (tcon) 2508 + cifs_put_tcon(tcon); 2509 + else if (pSesInfo) 2510 + cifs_put_smb_ses(pSesInfo); 2511 + 2512 + cleanup_volume_info(&volume_info); 2513 + FreeXid(xid); 2514 + kfree(full_path); 2515 + goto try_mount_again; 2516 + } 2517 + #else /* No DFS support, return error on mount */ 2518 + rc = -EOPNOTSUPP; 2519 + #endif 2520 + } 2521 + 2522 + mount_fail_check: 2523 + /* on error free sesinfo and tcon struct if needed */ 2524 + if (rc) { 2525 + if (mount_data != mount_data_global) 2526 + kfree(mount_data); 2527 + /* If find_unc succeeded then rc == 0 so we can not end */ 2528 + /* up accidently freeing someone elses tcon struct */ 2529 + if (tcon) 2530 + cifs_put_tcon(tcon); 2531 + else if (pSesInfo) 2532 + cifs_put_smb_ses(pSesInfo); 2533 + else 2534 + cifs_put_tcp_session(srvTcp); 2535 + goto out; 2525 2536 } 2526 2537 2527 2538 /* volume_info->password is freed above when existing session found ··· 2587 2484 password will be freed at unmount time) */ 2588 2485 out: 2589 2486 /* zero out password before freeing */ 2590 - if (volume_info) { 2591 - if (volume_info->password != NULL) { 2592 - memset(volume_info->password, 0, 2593 - strlen(volume_info->password)); 2594 - kfree(volume_info->password); 2595 - } 2596 - kfree(volume_info->UNC); 2597 - kfree(volume_info->prepath); 2598 - kfree(volume_info); 2599 - } 2487 + cleanup_volume_info(&volume_info); 2600 2488 FreeXid(xid); 2601 2489 return rc; 2602 2490 } ··· 2767 2673 /* We look for obvious messed up bcc or strings in response so we do not go off 2768 2674 the end since (at least) WIN2K and Windows XP have a major bug in not null 2769 2675 terminating last Unicode string in response */ 2770 - if (ses->serverOS) 2771 - kfree(ses->serverOS); 2676 + kfree(ses->serverOS); 2772 2677 ses->serverOS = kzalloc(2 * (len + 1), 2773 2678 GFP_KERNEL); 2774 2679 if (ses->serverOS == NULL) ··· 2803 2710 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2804 2711 /* last string is not always null terminated 2805 2712 (for e.g. for Windows XP & 2000) */ 2806 - if (ses->serverDomain) 2807 - kfree(ses->serverDomain); 2713 + kfree(ses->serverDomain); 2808 2714 ses->serverDomain = 2809 2715 kzalloc(2*(len+1), 2810 2716 GFP_KERNEL); ··· 2817 2725 ses->serverDomain[1+(2*len)] = 0; 2818 2726 } else { /* else no more room so create 2819 2727 dummy domain string */ 2820 - if (ses->serverDomain) 2821 - kfree(ses->serverDomain); 2728 + kfree(ses->serverDomain); 2822 2729 ses->serverDomain = 2823 2730 kzalloc(2, GFP_KERNEL); 2824 2731 } ··· 2863 2772 bcc_ptr++; 2864 2773 2865 2774 len = strnlen(bcc_ptr, 1024); 2866 - if (ses->serverDomain) 2867 - kfree(ses->serverDomain); 2775 + kfree(ses->serverDomain); 2868 2776 ses->serverDomain = kzalloc(len + 1, 2869 2777 GFP_KERNEL); 2870 2778 if (ses->serverDomain == NULL) ··· 3103 3013 /* We look for obvious messed up bcc or strings in response so we do not go off 3104 3014 the end since (at least) WIN2K and Windows XP have a major bug in not null 3105 3015 terminating last Unicode string in response */ 3106 - if (ses->serverOS) 3107 - kfree(ses->serverOS); 3016 + kfree(ses->serverOS); 3108 3017 ses->serverOS = 3109 3018 kzalloc(2 * (len + 1), GFP_KERNEL); 3110 3019 cifs_strfromUCS_le(ses->serverOS, ··· 3175 3086 if (((long) bcc_ptr + len) - (long) 3176 3087 pByteArea(smb_buffer_response) 3177 3088 <= BCC(smb_buffer_response)) { 3178 - if (ses->serverOS) 3179 - kfree(ses->serverOS); 3089 + kfree(ses->serverOS); 3180 3090 ses->serverOS = 3181 3091 kzalloc(len + 1, 3182 3092 GFP_KERNEL); ··· 3502 3414 /* We look for obvious messed up bcc or strings in response so we do not go off 3503 3415 the end since (at least) WIN2K and Windows XP have a major bug in not null 3504 3416 terminating last Unicode string in response */ 3505 - if (ses->serverOS) 3506 - kfree(ses->serverOS); 3417 + kfree(ses->serverOS); 3507 3418 ses->serverOS = 3508 3419 kzalloc(2 * (len + 1), GFP_KERNEL); 3509 3420 cifs_strfromUCS_le(ses->serverOS, ··· 3535 3448 if (remaining_words > 0) { 3536 3449 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 3537 3450 /* last string not always null terminated (e.g. for Windows XP & 2000) */ 3538 - if (ses->serverDomain) 3539 - kfree(ses->serverDomain); 3451 + kfree(ses->serverDomain); 3540 3452 ses->serverDomain = 3541 3453 kzalloc(2 * 3542 3454 (len + ··· 3562 3476 = 0; 3563 3477 } /* else no more room so create dummy domain string */ 3564 3478 else { 3565 - if (ses->serverDomain) 3566 - kfree(ses->serverDomain); 3479 + kfree(ses->serverDomain); 3567 3480 ses->serverDomain = kzalloc(2,GFP_KERNEL); 3568 3481 } 3569 3482 } else { /* no room so create dummy domain and NOS string */ 3570 - if (ses->serverDomain) 3571 - kfree(ses->serverDomain); 3483 + kfree(ses->serverDomain); 3572 3484 ses->serverDomain = kzalloc(2, GFP_KERNEL); 3573 3485 kfree(ses->serverNOS); 3574 3486 ses->serverNOS = kzalloc(2, GFP_KERNEL); ··· 3576 3492 if (((long) bcc_ptr + len) - 3577 3493 (long) pByteArea(smb_buffer_response) 3578 3494 <= BCC(smb_buffer_response)) { 3579 - if (ses->serverOS) 3580 - kfree(ses->serverOS); 3495 + kfree(ses->serverOS); 3581 3496 ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 3582 3497 strncpy(ses->serverOS,bcc_ptr, len); 3583 3498 ··· 3595 3512 bcc_ptr++; 3596 3513 3597 3514 len = strnlen(bcc_ptr, 1024); 3598 - if (ses->serverDomain) 3599 - kfree(ses->serverDomain); 3515 + kfree(ses->serverDomain); 3600 3516 ses->serverDomain = 3601 3517 kzalloc(len+1, 3602 3518 GFP_KERNEL); ··· 3756 3674 BCC(smb_buffer_response)) { 3757 3675 kfree(tcon->nativeFileSystem); 3758 3676 tcon->nativeFileSystem = 3759 - kzalloc(2*(length + 1), GFP_KERNEL); 3760 - if (tcon->nativeFileSystem) 3677 + kzalloc((4 * length) + 2, GFP_KERNEL); 3678 + if (tcon->nativeFileSystem) { 3761 3679 cifs_strfromUCS_le( 3762 3680 tcon->nativeFileSystem, 3763 3681 (__le16 *) bcc_ptr, 3764 3682 length, nls_codepage); 3765 - bcc_ptr += 2 * length; 3766 - bcc_ptr[0] = 0; /* null terminate the string */ 3767 - bcc_ptr[1] = 0; 3768 - bcc_ptr += 2; 3683 + cFYI(1, ("nativeFileSystem=%s", 3684 + tcon->nativeFileSystem)); 3685 + } 3769 3686 } 3770 3687 /* else do not bother copying these information fields*/ 3771 3688 } else {
+97 -48
fs/cifs/dir.c
··· 129 129 return full_path; 130 130 } 131 131 132 + static void 133 + cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle, 134 + struct cifsTconInfo *tcon, bool write_only) 135 + { 136 + int oplock = 0; 137 + struct cifsFileInfo *pCifsFile; 138 + struct cifsInodeInfo *pCifsInode; 139 + 140 + pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 141 + 142 + if (pCifsFile == NULL) 143 + return; 144 + 145 + if (oplockEnabled) 146 + oplock = REQ_OPLOCK; 147 + 148 + pCifsFile->netfid = fileHandle; 149 + pCifsFile->pid = current->tgid; 150 + pCifsFile->pInode = newinode; 151 + pCifsFile->invalidHandle = false; 152 + pCifsFile->closePend = false; 153 + mutex_init(&pCifsFile->fh_mutex); 154 + mutex_init(&pCifsFile->lock_mutex); 155 + INIT_LIST_HEAD(&pCifsFile->llist); 156 + atomic_set(&pCifsFile->wrtPending, 0); 157 + 158 + /* set the following in open now 159 + pCifsFile->pfile = file; */ 160 + write_lock(&GlobalSMBSeslock); 161 + list_add(&pCifsFile->tlist, &tcon->openFileList); 162 + pCifsInode = CIFS_I(newinode); 163 + if (pCifsInode) { 164 + /* if readable file instance put first in list*/ 165 + if (write_only) 166 + list_add_tail(&pCifsFile->flist, 167 + &pCifsInode->openFileList); 168 + else 169 + list_add(&pCifsFile->flist, &pCifsInode->openFileList); 170 + 171 + if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 172 + pCifsInode->clientCanCacheAll = true; 173 + pCifsInode->clientCanCacheRead = true; 174 + cFYI(1, ("Exclusive Oplock inode %p", newinode)); 175 + } else if ((oplock & 0xF) == OPLOCK_READ) 176 + pCifsInode->clientCanCacheRead = true; 177 + } 178 + write_unlock(&GlobalSMBSeslock); 179 + } 180 + 132 181 int cifs_posix_open(char *full_path, struct inode **pinode, 133 182 struct super_block *sb, int mode, int oflags, 134 183 int *poplock, __u16 *pnetfid, int xid) 135 184 { 136 185 int rc; 137 186 __u32 oplock; 187 + bool write_only = false; 138 188 FILE_UNIX_BASIC_INFO *presp_data; 139 189 __u32 posix_flags = 0; 140 190 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); ··· 222 172 if (oflags & O_DIRECT) 223 173 posix_flags |= SMB_O_DIRECT; 224 174 175 + if (!(oflags & FMODE_READ)) 176 + write_only = true; 225 177 226 178 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 227 179 pnetfid, presp_data, &oplock, full_path, ··· 239 187 if (!pinode) 240 188 goto posix_open_ret; /* caller does not need info */ 241 189 242 - if (*pinode == NULL) 243 - *pinode = cifs_new_inode(sb, &presp_data->UniqueId); 190 + if (*pinode == NULL) { 191 + __u64 unique_id = le64_to_cpu(presp_data->UniqueId); 192 + *pinode = cifs_new_inode(sb, &unique_id); 193 + } 244 194 /* else an inode was passed in. Update its info, don't create one */ 245 195 246 196 /* We do not need to close the file if new_inode fails since ··· 251 197 goto posix_open_ret; 252 198 253 199 posix_fill_in_inode(*pinode, presp_data, 1); 200 + 201 + cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); 254 202 255 203 posix_open_ret: 256 204 kfree(presp_data); ··· 295 239 char *full_path = NULL; 296 240 FILE_ALL_INFO *buf = NULL; 297 241 struct inode *newinode = NULL; 298 - struct cifsInodeInfo *pCifsInode; 299 242 int disposition = FILE_OVERWRITE_IF; 300 243 bool write_only = false; 301 244 ··· 465 410 /* mknod case - do not leave file open */ 466 411 CIFSSMBClose(xid, tcon, fileHandle); 467 412 } else if (newinode) { 468 - struct cifsFileInfo *pCifsFile = 469 - kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 470 - 471 - if (pCifsFile == NULL) 472 - goto cifs_create_out; 473 - pCifsFile->netfid = fileHandle; 474 - pCifsFile->pid = current->tgid; 475 - pCifsFile->pInode = newinode; 476 - pCifsFile->invalidHandle = false; 477 - pCifsFile->closePend = false; 478 - init_MUTEX(&pCifsFile->fh_sem); 479 - mutex_init(&pCifsFile->lock_mutex); 480 - INIT_LIST_HEAD(&pCifsFile->llist); 481 - atomic_set(&pCifsFile->wrtPending, 0); 482 - 483 - /* set the following in open now 484 - pCifsFile->pfile = file; */ 485 - write_lock(&GlobalSMBSeslock); 486 - list_add(&pCifsFile->tlist, &tcon->openFileList); 487 - pCifsInode = CIFS_I(newinode); 488 - if (pCifsInode) { 489 - /* if readable file instance put first in list*/ 490 - if (write_only) { 491 - list_add_tail(&pCifsFile->flist, 492 - &pCifsInode->openFileList); 493 - } else { 494 - list_add(&pCifsFile->flist, 495 - &pCifsInode->openFileList); 496 - } 497 - if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 498 - pCifsInode->clientCanCacheAll = true; 499 - pCifsInode->clientCanCacheRead = true; 500 - cFYI(1, ("Exclusive Oplock inode %p", 501 - newinode)); 502 - } else if ((oplock & 0xF) == OPLOCK_READ) 503 - pCifsInode->clientCanCacheRead = true; 504 - } 505 - write_unlock(&GlobalSMBSeslock); 413 + cifs_fill_fileinfo(newinode, fileHandle, 414 + cifs_sb->tcon, write_only); 506 415 } 507 416 cifs_create_out: 508 417 kfree(buf); ··· 599 580 return rc; 600 581 } 601 582 602 - 603 583 struct dentry * 604 584 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, 605 585 struct nameidata *nd) 606 586 { 607 587 int xid; 608 588 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 589 + int oplock = 0; 590 + int mode; 591 + __u16 fileHandle = 0; 592 + bool posix_open = false; 609 593 struct cifs_sb_info *cifs_sb; 610 594 struct cifsTconInfo *pTcon; 611 595 struct inode *newInode = NULL; 612 596 char *full_path = NULL; 597 + struct file *filp; 613 598 614 599 xid = GetXid(); 615 600 ··· 655 632 } 656 633 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); 657 634 658 - if (pTcon->unix_ext) 659 - rc = cifs_get_inode_info_unix(&newInode, full_path, 660 - parent_dir_inode->i_sb, xid); 661 - else 635 + if (pTcon->unix_ext) { 636 + if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 637 + (nd->flags & LOOKUP_OPEN)) { 638 + if (!((nd->intent.open.flags & O_CREAT) && 639 + (nd->intent.open.flags & O_EXCL))) { 640 + mode = nd->intent.open.create_mode & 641 + ~current_umask(); 642 + rc = cifs_posix_open(full_path, &newInode, 643 + parent_dir_inode->i_sb, mode, 644 + nd->intent.open.flags, &oplock, 645 + &fileHandle, xid); 646 + /* 647 + * This code works around a bug in 648 + * samba posix open in samba versions 3.3.1 649 + * and earlier where create works 650 + * but open fails with invalid parameter. 651 + * If either of these error codes are 652 + * returned, follow the normal lookup. 653 + * Otherwise, the error during posix open 654 + * is handled. 655 + */ 656 + if ((rc != -EINVAL) && (rc != -EOPNOTSUPP)) 657 + posix_open = true; 658 + } 659 + } 660 + if (!posix_open) 661 + rc = cifs_get_inode_info_unix(&newInode, full_path, 662 + parent_dir_inode->i_sb, xid); 663 + } else 662 664 rc = cifs_get_inode_info(&newInode, full_path, NULL, 663 - parent_dir_inode->i_sb, xid, NULL); 665 + parent_dir_inode->i_sb, xid, NULL); 664 666 665 667 if ((rc == 0) && (newInode != NULL)) { 666 668 if (pTcon->nocase) ··· 693 645 else 694 646 direntry->d_op = &cifs_dentry_ops; 695 647 d_add(direntry, newInode); 696 - 648 + if (posix_open) 649 + filp = lookup_instantiate_filp(nd, direntry, NULL); 697 650 /* since paths are not looked up by component - the parent 698 651 directories are presumed to be good here */ 699 652 renew_parental_timestamps(direntry);
+1 -1
fs/cifs/dns_resolve.c
··· 78 78 } 79 79 80 80 key->type_data.x[0] = datalen; 81 - rcu_assign_pointer(key->payload.data, ip); 81 + key->payload.data = ip; 82 82 83 83 return rc; 84 84 }
+78 -45
fs/cifs/file.c
··· 46 46 memset(private_data, 0, sizeof(struct cifsFileInfo)); 47 47 private_data->netfid = netfid; 48 48 private_data->pid = current->tgid; 49 - init_MUTEX(&private_data->fh_sem); 49 + mutex_init(&private_data->fh_mutex); 50 50 mutex_init(&private_data->lock_mutex); 51 51 INIT_LIST_HEAD(&private_data->llist); 52 52 private_data->pfile = file; /* needed for writepage */ ··· 284 284 cifs_sb = CIFS_SB(inode->i_sb); 285 285 tcon = cifs_sb->tcon; 286 286 287 - if (file->f_flags & O_CREAT) { 288 - /* search inode for this file and fill in file->private_data */ 289 - pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 290 - read_lock(&GlobalSMBSeslock); 291 - list_for_each(tmp, &pCifsInode->openFileList) { 292 - pCifsFile = list_entry(tmp, struct cifsFileInfo, 293 - flist); 294 - if ((pCifsFile->pfile == NULL) && 295 - (pCifsFile->pid == current->tgid)) { 296 - /* mode set in cifs_create */ 287 + /* search inode for this file and fill in file->private_data */ 288 + pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 289 + read_lock(&GlobalSMBSeslock); 290 + list_for_each(tmp, &pCifsInode->openFileList) { 291 + pCifsFile = list_entry(tmp, struct cifsFileInfo, 292 + flist); 293 + if ((pCifsFile->pfile == NULL) && 294 + (pCifsFile->pid == current->tgid)) { 295 + /* mode set in cifs_create */ 297 296 298 - /* needed for writepage */ 299 - pCifsFile->pfile = file; 297 + /* needed for writepage */ 298 + pCifsFile->pfile = file; 300 299 301 - file->private_data = pCifsFile; 302 - break; 303 - } 304 - } 305 - read_unlock(&GlobalSMBSeslock); 306 - if (file->private_data != NULL) { 307 - rc = 0; 308 - FreeXid(xid); 309 - return rc; 310 - } else { 311 - if (file->f_flags & O_EXCL) 312 - cERROR(1, ("could not find file instance for " 313 - "new file %p", file)); 300 + file->private_data = pCifsFile; 301 + break; 314 302 } 315 303 } 304 + read_unlock(&GlobalSMBSeslock); 305 + 306 + if (file->private_data != NULL) { 307 + rc = 0; 308 + FreeXid(xid); 309 + return rc; 310 + } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) 311 + cERROR(1, ("could not find file instance for " 312 + "new file %p", file)); 316 313 317 314 full_path = build_path_from_dentry(file->f_path.dentry); 318 315 if (full_path == NULL) { ··· 497 500 return -EBADF; 498 501 499 502 xid = GetXid(); 500 - down(&pCifsFile->fh_sem); 503 + mutex_unlock(&pCifsFile->fh_mutex); 501 504 if (!pCifsFile->invalidHandle) { 502 - up(&pCifsFile->fh_sem); 505 + mutex_lock(&pCifsFile->fh_mutex); 503 506 FreeXid(xid); 504 507 return 0; 505 508 } ··· 530 533 if (full_path == NULL) { 531 534 rc = -ENOMEM; 532 535 reopen_error_exit: 533 - up(&pCifsFile->fh_sem); 536 + mutex_lock(&pCifsFile->fh_mutex); 534 537 FreeXid(xid); 535 538 return rc; 536 539 } ··· 572 575 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 573 576 CIFS_MOUNT_MAP_SPECIAL_CHR); 574 577 if (rc) { 575 - up(&pCifsFile->fh_sem); 578 + mutex_lock(&pCifsFile->fh_mutex); 576 579 cFYI(1, ("cifs_open returned 0x%x", rc)); 577 580 cFYI(1, ("oplock: %d", oplock)); 578 581 } else { 579 582 reopen_success: 580 583 pCifsFile->netfid = netfid; 581 584 pCifsFile->invalidHandle = false; 582 - up(&pCifsFile->fh_sem); 585 + mutex_lock(&pCifsFile->fh_mutex); 583 586 pCifsInode = CIFS_I(inode); 584 587 if (pCifsInode) { 585 588 if (can_flush) { ··· 968 971 return rc; 969 972 } 970 973 974 + /* 975 + * Set the timeout on write requests past EOF. For some servers (Windows) 976 + * these calls can be very long. 977 + * 978 + * If we're writing >10M past the EOF we give a 180s timeout. Anything less 979 + * than that gets a 45s timeout. Writes not past EOF get 15s timeouts. 980 + * The 10M cutoff is totally arbitrary. A better scheme for this would be 981 + * welcome if someone wants to suggest one. 982 + * 983 + * We may be able to do a better job with this if there were some way to 984 + * declare that a file should be sparse. 985 + */ 986 + static int 987 + cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset) 988 + { 989 + if (offset <= cifsi->server_eof) 990 + return CIFS_STD_OP; 991 + else if (offset > (cifsi->server_eof + (10 * 1024 * 1024))) 992 + return CIFS_VLONG_OP; 993 + else 994 + return CIFS_LONG_OP; 995 + } 996 + 997 + /* update the file size (if needed) after a write */ 998 + static void 999 + cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, 1000 + unsigned int bytes_written) 1001 + { 1002 + loff_t end_of_write = offset + bytes_written; 1003 + 1004 + if (end_of_write > cifsi->server_eof) 1005 + cifsi->server_eof = end_of_write; 1006 + } 1007 + 971 1008 ssize_t cifs_user_write(struct file *file, const char __user *write_data, 972 1009 size_t write_size, loff_t *poffset) 973 1010 { ··· 1012 981 struct cifsTconInfo *pTcon; 1013 982 int xid, long_op; 1014 983 struct cifsFileInfo *open_file; 984 + struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode); 1015 985 1016 986 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1017 987 ··· 1032 1000 1033 1001 xid = GetXid(); 1034 1002 1035 - if (*poffset > file->f_path.dentry->d_inode->i_size) 1036 - long_op = CIFS_VLONG_OP; /* writes past EOF take long time */ 1037 - else 1038 - long_op = CIFS_LONG_OP; 1039 - 1003 + long_op = cifs_write_timeout(cifsi, *poffset); 1040 1004 for (total_written = 0; write_size > total_written; 1041 1005 total_written += bytes_written) { 1042 1006 rc = -EAGAIN; ··· 1076 1048 FreeXid(xid); 1077 1049 return rc; 1078 1050 } 1079 - } else 1051 + } else { 1052 + cifs_update_eof(cifsi, *poffset, bytes_written); 1080 1053 *poffset += bytes_written; 1054 + } 1081 1055 long_op = CIFS_STD_OP; /* subsequent writes fast - 1082 1056 15 seconds is plenty */ 1083 1057 } ··· 1115 1085 struct cifsTconInfo *pTcon; 1116 1086 int xid, long_op; 1117 1087 struct cifsFileInfo *open_file; 1088 + struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode); 1118 1089 1119 1090 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1120 1091 ··· 1130 1099 1131 1100 xid = GetXid(); 1132 1101 1133 - if (*poffset > file->f_path.dentry->d_inode->i_size) 1134 - long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */ 1135 - else 1136 - long_op = CIFS_LONG_OP; 1137 - 1102 + long_op = cifs_write_timeout(cifsi, *poffset); 1138 1103 for (total_written = 0; write_size > total_written; 1139 1104 total_written += bytes_written) { 1140 1105 rc = -EAGAIN; ··· 1193 1166 FreeXid(xid); 1194 1167 return rc; 1195 1168 } 1196 - } else 1169 + } else { 1170 + cifs_update_eof(cifsi, *poffset, bytes_written); 1197 1171 *poffset += bytes_written; 1172 + } 1198 1173 long_op = CIFS_STD_OP; /* subsequent writes fast - 1199 1174 15 seconds is plenty */ 1200 1175 } ··· 1409 1380 int nr_pages; 1410 1381 __u64 offset = 0; 1411 1382 struct cifsFileInfo *open_file; 1383 + struct cifsInodeInfo *cifsi = CIFS_I(mapping->host); 1412 1384 struct page *page; 1413 1385 struct pagevec pvec; 1414 1386 int rc = 0; 1415 1387 int scanned = 0; 1416 - int xid; 1388 + int xid, long_op; 1417 1389 1418 1390 cifs_sb = CIFS_SB(mapping->host->i_sb); 1419 1391 ··· 1558 1528 cERROR(1, ("No writable handles for inode")); 1559 1529 rc = -EBADF; 1560 1530 } else { 1531 + long_op = cifs_write_timeout(cifsi, offset); 1561 1532 rc = CIFSSMBWrite2(xid, cifs_sb->tcon, 1562 1533 open_file->netfid, 1563 1534 bytes_to_write, offset, 1564 1535 &bytes_written, iov, n_iov, 1565 - CIFS_LONG_OP); 1536 + long_op); 1566 1537 atomic_dec(&open_file->wrtPending); 1538 + cifs_update_eof(cifsi, offset, bytes_written); 1539 + 1567 1540 if (rc || bytes_written < bytes_to_write) { 1568 1541 cERROR(1, ("Write2 ret %d, wrote %d", 1569 1542 rc, bytes_written));
+42 -35
fs/cifs/inode.c
··· 143 143 144 144 inode->i_nlink = le64_to_cpu(info->Nlinks); 145 145 146 + cifsInfo->server_eof = end_of_file; 146 147 spin_lock(&inode->i_lock); 147 148 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 148 149 /* ··· 277 276 278 277 /* get new inode */ 279 278 if (*pinode == NULL) { 280 - *pinode = cifs_new_inode(sb, &find_data.UniqueId); 279 + __u64 unique_id = le64_to_cpu(find_data.UniqueId); 280 + *pinode = cifs_new_inode(sb, &unique_id); 281 281 if (*pinode == NULL) { 282 282 rc = -ENOMEM; 283 283 goto cgiiu_exit; ··· 607 605 inode->i_mode |= S_IFREG; 608 606 } 609 607 608 + cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); 610 609 spin_lock(&inode->i_lock); 611 - if (is_size_safe_to_change(cifsInfo, 612 - le64_to_cpu(pfindData->EndOfFile))) { 610 + if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { 613 611 /* can not safely shrink the file size here if the 614 612 client is writing to it due to potential races */ 615 - i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); 613 + i_size_write(inode, cifsInfo->server_eof); 616 614 617 615 /* 512 bytes (2**9) is the fake blocksize that must be 618 616 used for this calculation */ ··· 1140 1138 cFYI(1, ("posix mkdir returned 0x%x", rc)); 1141 1139 d_drop(direntry); 1142 1140 } else { 1141 + __u64 unique_id; 1143 1142 if (pInfo->Type == cpu_to_le32(-1)) { 1144 1143 /* no return info, go query for it */ 1145 1144 kfree(pInfo); ··· 1154 1151 else 1155 1152 direntry->d_op = &cifs_dentry_ops; 1156 1153 1157 - newinode = cifs_new_inode(inode->i_sb, 1158 - &pInfo->UniqueId); 1154 + unique_id = le64_to_cpu(pInfo->UniqueId); 1155 + newinode = cifs_new_inode(inode->i_sb, &unique_id); 1159 1156 if (newinode == NULL) { 1160 1157 kfree(pInfo); 1161 1158 goto mkdir_get_info; ··· 1453 1450 checking the UniqueId via FILE_INTERNAL_INFO */ 1454 1451 1455 1452 unlink_target: 1456 - if ((rc == -EACCES) || (rc == -EEXIST)) { 1453 + /* Try unlinking the target dentry if it's not negative */ 1454 + if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { 1457 1455 tmprc = cifs_unlink(target_dir, target_dentry); 1458 1456 if (tmprc) 1459 1457 goto cifs_rename_exit; ··· 1757 1753 } 1758 1754 1759 1755 if (rc == 0) { 1756 + cifsInode->server_eof = attrs->ia_size; 1760 1757 rc = cifs_vmtruncate(inode, attrs->ia_size); 1761 1758 cifs_truncate_page(inode->i_mapping, inode->i_size); 1762 1759 } ··· 1797 1792 goto out; 1798 1793 } 1799 1794 1800 - if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1801 - /* 1802 - Flush data before changing file size or changing the last 1803 - write time of the file on the server. If the 1804 - flush returns error, store it to report later and continue. 1805 - BB: This should be smarter. Why bother flushing pages that 1806 - will be truncated anyway? Also, should we error out here if 1807 - the flush returns error? 1808 - */ 1809 - rc = filemap_write_and_wait(inode->i_mapping); 1810 - if (rc != 0) { 1811 - cifsInode->write_behind_rc = rc; 1812 - rc = 0; 1813 - } 1795 + /* 1796 + * Attempt to flush data before changing attributes. We need to do 1797 + * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the 1798 + * ownership or mode then we may also need to do this. Here, we take 1799 + * the safe way out and just do the flush on all setattr requests. If 1800 + * the flush returns error, store it to report later and continue. 1801 + * 1802 + * BB: This should be smarter. Why bother flushing pages that 1803 + * will be truncated anyway? Also, should we error out here if 1804 + * the flush returns error? 1805 + */ 1806 + rc = filemap_write_and_wait(inode->i_mapping); 1807 + if (rc != 0) { 1808 + cifsInode->write_behind_rc = rc; 1809 + rc = 0; 1814 1810 } 1815 1811 1816 1812 if (attrs->ia_valid & ATTR_SIZE) { ··· 1909 1903 return -ENOMEM; 1910 1904 } 1911 1905 1912 - if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1913 - /* 1914 - Flush data before changing file size or changing the last 1915 - write time of the file on the server. If the 1916 - flush returns error, store it to report later and continue. 1917 - BB: This should be smarter. Why bother flushing pages that 1918 - will be truncated anyway? Also, should we error out here if 1919 - the flush returns error? 1920 - */ 1921 - rc = filemap_write_and_wait(inode->i_mapping); 1922 - if (rc != 0) { 1923 - cifsInode->write_behind_rc = rc; 1924 - rc = 0; 1925 - } 1906 + /* 1907 + * Attempt to flush data before changing attributes. We need to do 1908 + * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the 1909 + * ownership or mode then we may also need to do this. Here, we take 1910 + * the safe way out and just do the flush on all setattr requests. If 1911 + * the flush returns error, store it to report later and continue. 1912 + * 1913 + * BB: This should be smarter. Why bother flushing pages that 1914 + * will be truncated anyway? Also, should we error out here if 1915 + * the flush returns error? 1916 + */ 1917 + rc = filemap_write_and_wait(inode->i_mapping); 1918 + if (rc != 0) { 1919 + cifsInode->write_behind_rc = rc; 1920 + rc = 0; 1926 1921 } 1927 1922 1928 1923 if (attrs->ia_valid & ATTR_SIZE) {
+4 -2
fs/cifs/readdir.c
··· 239 239 if (atomic_read(&cifsInfo->inUse) == 0) 240 240 atomic_set(&cifsInfo->inUse, 1); 241 241 242 + cifsInfo->server_eof = end_of_file; 242 243 spin_lock(&tmp_inode->i_lock); 243 244 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 244 245 /* can not safely change the file size here if the ··· 376 375 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 377 376 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 378 377 378 + cifsInfo->server_eof = end_of_file; 379 379 spin_lock(&tmp_inode->i_lock); 380 380 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 381 381 /* can not safely change the file size here if the ··· 842 840 len = strnlen(filename, PATH_MAX); 843 841 } 844 842 845 - *pinum = pFindData->UniqueId; 843 + *pinum = le64_to_cpu(pFindData->UniqueId); 846 844 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 847 845 FILE_DIRECTORY_INFO *pFindData = 848 846 (FILE_DIRECTORY_INFO *)current_entry; ··· 858 856 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 859 857 filename = &pFindData->FileName[0]; 860 858 len = le32_to_cpu(pFindData->FileNameLength); 861 - *pinum = pFindData->UniqueId; 859 + *pinum = le64_to_cpu(pFindData->UniqueId); 862 860 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { 863 861 FILE_BOTH_DIRECTORY_INFO *pFindData = 864 862 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
+27 -20
fs/cifs/sess.c
··· 285 285 int words_left, len; 286 286 char *data = *pbcc_area; 287 287 288 - 289 - 290 288 cFYI(1, ("bleft %d", bleft)); 291 289 292 - 293 - /* SMB header is unaligned, so cifs servers word align start of 294 - Unicode strings */ 295 - data++; 296 - bleft--; /* Windows servers do not always double null terminate 297 - their final Unicode string - in which case we 298 - now will not attempt to decode the byte of junk 299 - which follows it */ 290 + /* 291 + * Windows servers do not always double null terminate their final 292 + * Unicode string. Check to see if there are an uneven number of bytes 293 + * left. If so, then add an extra NULL pad byte to the end of the 294 + * response. 295 + * 296 + * See section 2.7.2 in "Implementing CIFS" for details 297 + */ 298 + if (bleft % 2) { 299 + data[bleft] = 0; 300 + ++bleft; 301 + } 300 302 301 303 words_left = bleft / 2; 302 304 303 305 /* save off server operating system */ 304 306 len = UniStrnlen((wchar_t *) data, words_left); 305 307 306 - /* We look for obvious messed up bcc or strings in response so we do not go off 307 - the end since (at least) WIN2K and Windows XP have a major bug in not null 308 - terminating last Unicode string in response */ 309 308 if (len >= words_left) 310 309 return rc; 311 310 312 311 kfree(ses->serverOS); 313 312 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 314 313 ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); 315 - if (ses->serverOS != NULL) 314 + if (ses->serverOS != NULL) { 316 315 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 316 + cFYI(1, ("serverOS=%s", ses->serverOS)); 317 + } 317 318 data += 2 * (len + 1); 318 319 words_left -= len + 1; 319 320 ··· 329 328 if (ses->serverNOS != NULL) { 330 329 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 331 330 nls_cp); 331 + cFYI(1, ("serverNOS=%s", ses->serverNOS)); 332 332 if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { 333 333 cFYI(1, ("NT4 server")); 334 334 ses->flags |= CIFS_SES_NT4; ··· 345 343 return rc; 346 344 347 345 kfree(ses->serverDomain); 348 - ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ 346 + ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL); 349 347 if (ses->serverDomain != NULL) { 350 348 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, 351 349 nls_cp); 352 - ses->serverDomain[2*len] = 0; 353 - ses->serverDomain[(2*len) + 1] = 0; 350 + cFYI(1, ("serverDomain=%s", ses->serverDomain)); 354 351 } 355 352 data += 2 * (len + 1); 356 353 words_left -= len + 1; ··· 703 702 } 704 703 705 704 /* BB check if Unicode and decode strings */ 706 - if (smb_buf->Flags2 & SMBFLG2_UNICODE) 705 + if (smb_buf->Flags2 & SMBFLG2_UNICODE) { 706 + /* unicode string area must be word-aligned */ 707 + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { 708 + ++bcc_ptr; 709 + --bytes_remaining; 710 + } 707 711 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, 708 - ses, nls_cp); 709 - else 712 + ses, nls_cp); 713 + } else { 710 714 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, 711 715 ses, nls_cp); 716 + } 712 717 713 718 ssetup_exit: 714 719 if (spnego_key) {