diff options
author | Steve French <sfrench@us.ibm.com> | 2005-09-22 01:05:57 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-09-22 01:05:57 -0400 |
commit | 2096243885ee34b78cb57ce835e07c8536a67d2a (patch) | |
tree | caae2d2535d33cca16f11da9a2d25e445bd30018 /fs | |
parent | e30dcf3a1905b4d2154f95db5fdfdf69691b4f0e (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')
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 95 | ||||
-rw-r--r-- | fs/cifs/misc.c | 3 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 2 |
7 files changed, 107 insertions, 10 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 47ae68b51847..661b45906d09 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -3,7 +3,8 @@ Version 1.37 | |||
3 | Fix readdir caching when unlink removes file in current search buffer, | 3 | Fix readdir caching when unlink removes file in current search buffer, |
4 | and this is followed by a rewind search to just before the deleted entry. | 4 | and this is followed by a rewind search to just before the deleted entry. |
5 | Do not attempt to set ctime unless atime and/or mtime change requested | 5 | Do not attempt to set ctime unless atime and/or mtime change requested |
6 | (most servers throw it away anyway). | 6 | (most servers throw it away anyway). Fix length check of received smbs |
7 | to be more accurate. | ||
7 | 8 | ||
8 | Version 1.36 | 9 | Version 1.36 |
9 | ------------ | 10 | ------------ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f738c8b19e3b..1f97d39100ee 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -205,6 +205,10 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) | |||
205 | #endif /* CIFS_EXPERIMENTAL */ | 205 | #endif /* CIFS_EXPERIMENTAL */ |
206 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); | 206 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); |
207 | 207 | ||
208 | /* Old Windows servers do not support level 103, retry with level | ||
209 | one if old server failed the previous call */ | ||
210 | if(rc) | ||
211 | rc = SMBOldQFSInfo(xid, pTcon, buf); | ||
208 | /* | 212 | /* |
209 | int f_type; | 213 | int f_type; |
210 | __fsid_t f_fsid; | 214 | __fsid_t f_fsid; |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index cf466595b0d4..3fa37790bea2 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -1684,6 +1684,14 @@ typedef struct { | |||
1684 | } FILE_SYSTEM_INFO; /* size info, level 0x103 */ | 1684 | } FILE_SYSTEM_INFO; /* size info, level 0x103 */ |
1685 | 1685 | ||
1686 | typedef struct { | 1686 | typedef struct { |
1687 | __le32 fsid; | ||
1688 | __le32 SectorsPerAllocationUnit; | ||
1689 | __le32 TotalAllocationUnits; | ||
1690 | __le32 FreeAllocationUnits; | ||
1691 | __le16 BytesPerSector; | ||
1692 | } FILE_SYSTEM_ALLOC_INFO; | ||
1693 | |||
1694 | typedef struct { | ||
1687 | __le16 MajorVersionNumber; | 1695 | __le16 MajorVersionNumber; |
1688 | __le16 MinorVersionNumber; | 1696 | __le16 MinorVersionNumber; |
1689 | __le64 Capability; | 1697 | __le64 Capability; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 6943f7c6de08..0bace385e97a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -133,6 +133,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | |||
133 | int remap); | 133 | int remap); |
134 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 134 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
135 | struct kstatfs *FSData); | 135 | struct kstatfs *FSData); |
136 | extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, | ||
137 | struct kstatfs *FSData); | ||
136 | extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | 138 | extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, |
137 | __u64 cap); | 139 | __u64 cap); |
138 | 140 | ||
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 |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index fafbdbfa63a1..26b35b55f31b 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -450,13 +450,12 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
450 | 450 | ||
451 | if ((4 + len != smbCalcSize(smb)) | 451 | if ((4 + len != smbCalcSize(smb)) |
452 | || (4 + len != (unsigned int)length)) { | 452 | || (4 + len != (unsigned int)length)) { |
453 | return 0; | ||
454 | } else { | ||
455 | cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); | 453 | cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); |
456 | cERROR(1, | 454 | cERROR(1, |
457 | ("bad smb size detected. The Mid=%d", smb->Mid)); | 455 | ("bad smb size detected. The Mid=%d", smb->Mid)); |
458 | return 1; | 456 | return 1; |
459 | } | 457 | } |
458 | return 0; | ||
460 | } | 459 | } |
461 | int | 460 | int |
462 | is_valid_oplock_break(struct smb_hdr *buf) | 461 | is_valid_oplock_break(struct smb_hdr *buf) |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 873b812c0f40..32efa32774d2 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -868,7 +868,7 @@ unsigned int | |||
868 | smbCalcSize(struct smb_hdr *ptr) | 868 | smbCalcSize(struct smb_hdr *ptr) |
869 | { | 869 | { |
870 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + | 870 | return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + |
871 | BCC(ptr)); | 871 | 2 /* size of the bcc field itself */ + BCC(ptr)); |
872 | } | 872 | } |
873 | 873 | ||
874 | /* The following are taken from fs/ntfs/util.c */ | 874 | /* The following are taken from fs/ntfs/util.c */ |