diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b4f7b9859e3b..7d14f2414812 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2411,7 +2411,9 @@ findUniqueRetry: | |||
2411 | if (rc) { | 2411 | if (rc) { |
2412 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); | 2412 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); |
2413 | } else { /* decode response */ | 2413 | } else { /* decode response */ |
2414 | 2414 | #ifdef CONFIG_CIFS_STATS | |
2415 | atomic_inc(&tcon->num_ffirst); | ||
2416 | #endif | ||
2415 | /* BB fill in */ | 2417 | /* BB fill in */ |
2416 | } | 2418 | } |
2417 | 2419 | ||
@@ -2429,7 +2431,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | |||
2429 | const char *searchName, | 2431 | const char *searchName, |
2430 | const struct nls_table *nls_codepage, | 2432 | const struct nls_table *nls_codepage, |
2431 | __u16 * pnetfid, | 2433 | __u16 * pnetfid, |
2432 | struct cifs_search_info * psrch_inf, int remap) | 2434 | struct cifs_search_info * psrch_inf, int remap, const char dirsep) |
2433 | { | 2435 | { |
2434 | /* level 257 SMB_ */ | 2436 | /* level 257 SMB_ */ |
2435 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; | 2437 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; |
@@ -2456,7 +2458,7 @@ findFirstRetry: | |||
2456 | it got remapped to 0xF03A as if it were part of the | 2458 | it got remapped to 0xF03A as if it were part of the |
2457 | directory name instead of a wildcard */ | 2459 | directory name instead of a wildcard */ |
2458 | name_len *= 2; | 2460 | name_len *= 2; |
2459 | pSMB->FileName[name_len] = '\\'; | 2461 | pSMB->FileName[name_len] = dirsep; |
2460 | pSMB->FileName[name_len+1] = 0; | 2462 | pSMB->FileName[name_len+1] = 0; |
2461 | pSMB->FileName[name_len+2] = '*'; | 2463 | pSMB->FileName[name_len+2] = '*'; |
2462 | pSMB->FileName[name_len+3] = 0; | 2464 | pSMB->FileName[name_len+3] = 0; |
@@ -2470,7 +2472,7 @@ findFirstRetry: | |||
2470 | if(name_len > buffersize-header) | 2472 | if(name_len > buffersize-header) |
2471 | free buffer exit; BB */ | 2473 | free buffer exit; BB */ |
2472 | strncpy(pSMB->FileName, searchName, name_len); | 2474 | strncpy(pSMB->FileName, searchName, name_len); |
2473 | pSMB->FileName[name_len] = '\\'; | 2475 | pSMB->FileName[name_len] = dirsep; |
2474 | pSMB->FileName[name_len+1] = '*'; | 2476 | pSMB->FileName[name_len+1] = '*'; |
2475 | pSMB->FileName[name_len+2] = 0; | 2477 | pSMB->FileName[name_len+2] = 0; |
2476 | name_len += 3; | 2478 | name_len += 3; |
@@ -2524,6 +2526,9 @@ findFirstRetry: | |||
2524 | if (rc == -EAGAIN) | 2526 | if (rc == -EAGAIN) |
2525 | goto findFirstRetry; | 2527 | goto findFirstRetry; |
2526 | } else { /* decode response */ | 2528 | } else { /* decode response */ |
2529 | #ifdef CONFIG_CIFS_STATS | ||
2530 | atomic_inc(&tcon->num_ffirst); | ||
2531 | #endif | ||
2527 | /* BB remember to free buffer if error BB */ | 2532 | /* BB remember to free buffer if error BB */ |
2528 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2533 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2529 | if(rc == 0) { | 2534 | if(rc == 0) { |
@@ -2637,6 +2642,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
2637 | } else | 2642 | } else |
2638 | cFYI(1, ("FindNext returned = %d", rc)); | 2643 | cFYI(1, ("FindNext returned = %d", rc)); |
2639 | } else { /* decode response */ | 2644 | } else { /* decode response */ |
2645 | #ifdef CONFIG_CIFS_STATS | ||
2646 | atomic_inc(&tcon->num_fnext); | ||
2647 | #endif | ||
2640 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2648 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2641 | 2649 | ||
2642 | if(rc == 0) { | 2650 | if(rc == 0) { |
@@ -2706,6 +2714,9 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle | |||
2706 | if (rc) { | 2714 | if (rc) { |
2707 | cERROR(1, ("Send error in FindClose = %d", rc)); | 2715 | cERROR(1, ("Send error in FindClose = %d", rc)); |
2708 | } | 2716 | } |
2717 | #ifdef CONFIG_CIFS_STATS | ||
2718 | atomic_inc(&tcon->num_fclose); | ||
2719 | #endif | ||
2709 | cifs_small_buf_release(pSMB); | 2720 | cifs_small_buf_release(pSMB); |
2710 | 2721 | ||
2711 | /* Since session is dead, search handle closed on server already */ | 2722 | /* Since session is dead, search handle closed on server already */ |
@@ -3269,6 +3280,77 @@ QFSUnixRetry: | |||
3269 | return rc; | 3280 | return rc; |
3270 | } | 3281 | } |
3271 | 3282 | ||
3283 | int | ||
3284 | CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | ||
3285 | { | ||
3286 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ | ||
3287 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; | ||
3288 | TRANSACTION2_SETFSI_RSP *pSMBr = NULL; | ||
3289 | int rc = 0; | ||
3290 | int bytes_returned = 0; | ||
3291 | __u16 params, param_offset, offset, byte_count; | ||
3292 | |||
3293 | cFYI(1, ("In SETFSUnixInfo")); | ||
3294 | SETFSUnixRetry: | ||
3295 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3296 | (void **) &pSMBr); | ||
3297 | if (rc) | ||
3298 | return rc; | ||
3299 | |||
3300 | params = 4; /* 2 bytes zero followed by info level. */ | ||
3301 | pSMB->MaxSetupCount = 0; | ||
3302 | pSMB->Reserved = 0; | ||
3303 | pSMB->Flags = 0; | ||
3304 | pSMB->Timeout = 0; | ||
3305 | pSMB->Reserved2 = 0; | ||
3306 | param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4; | ||
3307 | offset = param_offset + params; | ||
3308 | |||
3309 | pSMB->MaxParameterCount = cpu_to_le16(4); | ||
3310 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | ||
3311 | pSMB->SetupCount = 1; | ||
3312 | pSMB->Reserved3 = 0; | ||
3313 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | ||
3314 | byte_count = 1 /* pad */ + params + 12; | ||
3315 | |||
3316 | pSMB->DataCount = cpu_to_le16(12); | ||
3317 | pSMB->ParameterCount = cpu_to_le16(params); | ||
3318 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3319 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3320 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
3321 | pSMB->DataOffset = cpu_to_le16(offset); | ||
3322 | |||
3323 | /* Params. */ | ||
3324 | pSMB->FileNum = 0; | ||
3325 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO); | ||
3326 | |||
3327 | /* Data. */ | ||
3328 | pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION); | ||
3329 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | ||
3330 | pSMB->ClientUnixCap = cpu_to_le64(cap); | ||
3331 | |||
3332 | pSMB->hdr.smb_buf_length += byte_count; | ||
3333 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3334 | |||
3335 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3336 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3337 | if (rc) { | ||
3338 | cERROR(1, ("Send error in SETFSUnixInfo = %d", rc)); | ||
3339 | } else { /* decode response */ | ||
3340 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3341 | if (rc) { | ||
3342 | rc = -EIO; /* bad smb */ | ||
3343 | } | ||
3344 | } | ||
3345 | cifs_buf_release(pSMB); | ||
3346 | |||
3347 | if (rc == -EAGAIN) | ||
3348 | goto SETFSUnixRetry; | ||
3349 | |||
3350 | return rc; | ||
3351 | } | ||
3352 | |||
3353 | |||
3272 | 3354 | ||
3273 | int | 3355 | int |
3274 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3356 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |