diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 95 |
1 files changed, 89 insertions, 6 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f72a61df3c68..daf717e6b6eb 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -3215,6 +3215,92 @@ GetDFSRefExit: | |||
3215 | return rc; | 3215 | return rc; |
3216 | } | 3216 | } |
3217 | 3217 | ||
3218 | /* Query File System Info such as free space to old servers such as Win 9x */ | ||
3219 | int | ||
3220 | SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | ||
3221 | { | ||
3222 | /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */ | ||
3223 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | ||
3224 | TRANSACTION2_QFSI_RSP *pSMBr = NULL; | ||
3225 | FILE_SYSTEM_ALLOC_INFO *response_data; | ||
3226 | int rc = 0; | ||
3227 | int bytes_returned = 0; | ||
3228 | __u16 params, byte_count; | ||
3229 | |||
3230 | cFYI(1, ("OldQFSInfo")); | ||
3231 | oldQFSInfoRetry: | ||
3232 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3233 | (void **) &pSMBr); | ||
3234 | if (rc) | ||
3235 | return rc; | ||
3236 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3237 | (void **) &pSMBr); | ||
3238 | if (rc) | ||
3239 | return rc; | ||
3240 | |||
3241 | params = 2; /* level */ | ||
3242 | pSMB->TotalDataCount = 0; | ||
3243 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
3244 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
3245 | pSMB->MaxSetupCount = 0; | ||
3246 | pSMB->Reserved = 0; | ||
3247 | pSMB->Flags = 0; | ||
3248 | pSMB->Timeout = 0; | ||
3249 | pSMB->Reserved2 = 0; | ||
3250 | byte_count = params + 1 /* pad */ ; | ||
3251 | pSMB->TotalParameterCount = cpu_to_le16(params); | ||
3252 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
3253 | pSMB->ParameterOffset = cpu_to_le16(offsetof( | ||
3254 | struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); | ||
3255 | pSMB->DataCount = 0; | ||
3256 | pSMB->DataOffset = 0; | ||
3257 | pSMB->SetupCount = 1; | ||
3258 | pSMB->Reserved3 = 0; | ||
3259 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | ||
3260 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | ||
3261 | pSMB->hdr.smb_buf_length += byte_count; | ||
3262 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3263 | |||
3264 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3265 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3266 | if (rc) { | ||
3267 | cFYI(1, ("Send error in QFSInfo = %d", rc)); | ||
3268 | } else { /* decode response */ | ||
3269 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3270 | |||
3271 | if (rc || (pSMBr->ByteCount < 18)) | ||
3272 | rc = -EIO; /* bad smb */ | ||
3273 | else { | ||
3274 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
3275 | cFYI(1,("qfsinf resp BCC: %d Offset %d", | ||
3276 | pSMBr->ByteCount, data_offset)); | ||
3277 | |||
3278 | response_data = | ||
3279 | (FILE_SYSTEM_ALLOC_INFO *) | ||
3280 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | ||
3281 | FSData->f_bsize = | ||
3282 | le16_to_cpu(response_data->BytesPerSector) * | ||
3283 | le32_to_cpu(response_data-> | ||
3284 | SectorsPerAllocationUnit); | ||
3285 | FSData->f_blocks = | ||
3286 | le32_to_cpu(response_data->TotalAllocationUnits); | ||
3287 | FSData->f_bfree = FSData->f_bavail = | ||
3288 | le32_to_cpu(response_data->FreeAllocationUnits); | ||
3289 | cFYI(1, | ||
3290 | ("Blocks: %lld Free: %lld Block size %ld", | ||
3291 | (unsigned long long)FSData->f_blocks, | ||
3292 | (unsigned long long)FSData->f_bfree, | ||
3293 | FSData->f_bsize)); | ||
3294 | } | ||
3295 | } | ||
3296 | cifs_buf_release(pSMB); | ||
3297 | |||
3298 | if (rc == -EAGAIN) | ||
3299 | goto oldQFSInfoRetry; | ||
3300 | |||
3301 | return rc; | ||
3302 | } | ||
3303 | |||
3218 | int | 3304 | int |
3219 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | 3305 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) |
3220 | { | 3306 | { |
@@ -3236,7 +3322,7 @@ QFSInfoRetry: | |||
3236 | params = 2; /* level */ | 3322 | params = 2; /* level */ |
3237 | pSMB->TotalDataCount = 0; | 3323 | pSMB->TotalDataCount = 0; |
3238 | pSMB->MaxParameterCount = cpu_to_le16(2); | 3324 | pSMB->MaxParameterCount = cpu_to_le16(2); |
3239 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 3325 | pSMB->MaxDataCount = cpu_to_le16(1000); |
3240 | pSMB->MaxSetupCount = 0; | 3326 | pSMB->MaxSetupCount = 0; |
3241 | pSMB->Reserved = 0; | 3327 | pSMB->Reserved = 0; |
3242 | pSMB->Flags = 0; | 3328 | pSMB->Flags = 0; |
@@ -3259,17 +3345,14 @@ QFSInfoRetry: | |||
3259 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3345 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3260 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3346 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
3261 | if (rc) { | 3347 | if (rc) { |
3262 | cERROR(1, ("Send error in QFSInfo = %d", rc)); | 3348 | cFYI(1, ("Send error in QFSInfo = %d", rc)); |
3263 | } else { /* decode response */ | 3349 | } else { /* decode response */ |
3264 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3350 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3265 | 3351 | ||
3266 | if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ | 3352 | if (rc || (pSMBr->ByteCount < 24)) |
3267 | rc = -EIO; /* bad smb */ | 3353 | rc = -EIO; /* bad smb */ |
3268 | else { | 3354 | else { |
3269 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3355 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
3270 | cFYI(1, | ||
3271 | ("Decoding qfsinfo response. BCC: %d Offset %d", | ||
3272 | pSMBr->ByteCount, data_offset)); | ||
3273 | 3356 | ||
3274 | response_data = | 3357 | response_data = |
3275 | (FILE_SYSTEM_INFO | 3358 | (FILE_SYSTEM_INFO |