aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-09-22 01:05:57 -0400
committerSteve French <sfrench@us.ibm.com>2005-09-22 01:05:57 -0400
commit2096243885ee34b78cb57ce835e07c8536a67d2a (patch)
treecaae2d2535d33cca16f11da9a2d25e445bd30018 /fs/cifs/cifssmb.c
parente30dcf3a1905b4d2154f95db5fdfdf69691b4f0e (diff)
[CIFS] Add support for legacy servers part nine. statfs (df and du) is now
functional, and the length check is fixed so readdir does not throw a warning message when windows me messes up the response to FindFirst of an empty dir (with only . and ..). Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c95
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 */
3219int
3220SMBOldQFSInfo(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"));
3231oldQFSInfoRetry:
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
3218int 3304int
3219CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) 3305CIFSSMBQFSInfo(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