GIT 442aa310f3bc49cf4e059da790fbae62411d50db git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git commit Author: Steve French Date: Mon Sep 24 20:25:46 2007 +0000 [CIFS] Support for CIFS ACLs (part 1) Add code to be able to dump CIFS ACL information when Query Posix ACL with cifsacl mount parm enabled. Signed-off-by: Shirish Pargoankar Signed-off-by: Steve French commit 2224f4e5d5317552d48ce9059761148b1516ba5d Author: Steve French Date: Thu Sep 20 15:37:29 2007 +0000 [CIFS] fix typo in previous commit Signed-off-by: Steve French commit 1e71f25d14d70f2bf607b40ab6d7e18daca57f36 Author: Steve French Date: Thu Sep 20 15:30:07 2007 +0000 [CIFS] Print better error when server returns malformed QueryUnixInfo response Signed-off-by: Steve French commit 5a44b3190e3441986648ff664ef045685995324b Author: Steve French Date: Thu Sep 20 15:16:24 2007 +0000 [CIFS] Add warning message when broken server fails SetFSInfo call A reasonably common NAS server returns an error on the SetFSInfo of the Unix capabilities. Log a message for this alerting the user that the server may have problems with the Unix extensions, and telling them what they can do to workaround it. Unfortunately the server does not return other clues that we could easily use to turn the Unix Extension support off automatically in this case (since they claim to support it). Signed-off-by: Steve French commit c45d707f67b82236fcf9ca2af31c264669368b9b Author: Steve French Date: Mon Sep 17 02:04:21 2007 +0000 [CIFS] Fallback to standard mkdir if server incorrectly claims support for posix ops Signed-off-by: Steve French commit 5a07cdf86c1485b570789fb660c8ada7c2635b23 Author: Steve French Date: Sun Sep 16 23:12:47 2007 +0000 [CIFS] fix small memory leak in an error path in new posix mkdir There is a small memory leak in fs/cifs/inode.c::cifs_mkdir(). Storage for 'pInfo' is allocated with kzalloc(), but if the call to CIFSPOSIXCreate(...) happens to return 0 and pInfo->Type == -1, then we'll jump to the 'mkdir_get_info' label without freeing the storage allocated for 'pInfo'. This patch adds a kfree() call to free the storage just before jumping to the label, thus getting rid of the leak. Signed-off-by: Jesper Juhl Signed-off-by: Steve French commit a23d30698190f05491a6096f027311f94d4d26d5 Author: Steve French Date: Sat Sep 15 03:43:47 2007 +0000 [CIFS] missing field in debug output from previous fix Signed-off-by: Steve French commit 88f370a688e765de9755a343702ca04e6817e5f5 Author: Steve French Date: Sat Sep 15 03:01:17 2007 +0000 [CIFS] Fix potential NULL pointer usage if kzalloc fails Potential problem was noticed by Cyrill Gorcunov CC: Cyrill Gorcunov Signed-off-by: Steve French commit 638b250766272fcaaa0f7ed2776f58f4ac701914 Author: Steve French Date: Sat Sep 15 02:35:51 2007 +0000 [CIFS] typo in earlier cifs_reconnect fix Signed-off-by: Steve French commit a8cd925f74c3b1b6d1192f9e75f9d12cc2ab148a Author: Jeff Date: Thu Sep 13 18:38:50 2007 +0000 [CIFS] Respect umask when using POSIX mkdir When making a directory with POSIX mkdir calls, cifs_mkdir does not respect the umask. This patch causes the new POSIX mkdir to create with the right mode Signed-off-by: Jeff Layton Signed-off-by: Steve French commit 4efa53f0907bb4378015c129a2c11b8d3a90bce2 Author: Steve French Date: Tue Sep 11 05:50:53 2007 +0000 [CIFS] lock inode open file list in close in case racing with open Harmless since it only protected turning off caching for the inode, but cleaner to lock around this in case we have a close racing with open. Signed-off-by: Shaggy CC: Cyrill Gorcunov Signed-off-by: Steve French commit 15745320f374aa6cbfe4836b76469159c0f49640 Author: Steve French Date: Fri Sep 7 22:23:48 2007 +0000 [CIFS] Fix oops in find_writable_file There was a case in which find_writable_file was not waiting long enough under heavy stress when writepages was racing with close of the file handle being used by the write. Signed-off-by: Steve French commit 77159b4df894f9e5e31f709fb0e5e52f6c1b1048 Author: Steve French Date: Fri Aug 31 01:10:17 2007 +0000 [CIFS] Fix warnings shown by newer version of sparse Signed-off-by: Steve French commit 26f57364d7cdef9d7ebe27c931fff5e4f21ffb1c Author: Steve French Date: Thu Aug 30 22:09:15 2007 +0000 [CIFS] formatting cleanup found by checkpatch Signed-off-by: Steve French commit f01d5e14e764b14b6bf5512678523d009254b209 Author: Steve French Date: Thu Aug 30 21:13:31 2007 +0000 [CIFS] fix for incorrect session reconnects cifs reconnect could end up happening incorrectly due to the small initial tcp recvmsg response. When the socket was within three bytes of being full and the recvmsg returned only 1 to 3 bytes of the initial 4 byte read of the RFC1001 length field. Fortunately this seems to be less common on more current kernels, but this fixes it so cifs tries to retrieve all 4 bytes of the initial tcp read. Signed-off-by: Shirish Pargoankar Signed-off-by: Steve French commit 8594c15ad226227aaf178b7cf57f2e7291684dd4 Author: Andre Haupt Date: Thu Aug 30 20:18:41 2007 +0000 [CIFS][KJ] use abs() from kernel.h where appropriate Signed-off-by: Andrew Haupt Signed-off-by: Steve French commit c19eb71020687e178b9fa564f4a8ac1880f87b10 Author: Steve French Date: Fri Aug 24 03:22:48 2007 +0000 [CIFS] fix typo in previous Signed-off-by: Steve French commit 39db810cb6c1e7d1f2e43ae38b437b7ee72fe815 Author: Jeff Layton Date: Fri Aug 24 03:16:51 2007 +0000 [CIFS] Byte range unlock request to non-Unix server can unlock too much On a mount without posix extensions enabled, when an unlock request is made, the client can release more than is intended. To reproduce, on a CIFS mount without posix extensions enabled: 1) open file 2) do fcntl lock: start=0 len=1 3) do fcntl lock: start=2 len=1 4) do fcntl unlock: start=0 len=1 ...on the unlock call the client sends an unlock request to the server for both locks. The problem is a bad test in cifs_lock. Signed-off-by: Jeff Layton Signed-off-by: Steve French commit 95ba7362105646523ee712fd252ec2e34ccbec15 Author: Cyrill Gorcunov Date: Fri Aug 24 00:23:36 2007 +0000 [CIFS] Fix unbalanced call to GetXid/FreeXid Signed-off-by: Cyrill Gorcunov Signed-off-by: Steve French commit 8064ab4da104900505f33535d230ce0da5d18341 Author: Steve French Date: Wed Aug 22 22:12:07 2007 +0000 [CIFS] cifs truncate missing a fix for private map COW race vmtruncate had added the same fix to handle the case of private pages being Copy on writed while truncate_inode_pages is going on Signed-off-by: Steve French fs/cifs/CHANGES | 5 +- fs/cifs/asn1.c | 10 +-- fs/cifs/cifs_debug.c | 17 +++--- fs/cifs/cifsacl.h | 34 +++++++++++ fs/cifs/cifsfs.c | 22 ++++--- fs/cifs/cifsfs.h | 4 + fs/cifs/cifsglob.h | 12 ++++ fs/cifs/cifspdu.h | 6 +- fs/cifs/cifsproto.h | 2 - fs/cifs/cifssmb.c | 150 ++++++++++++++++++++++++++++++++++++++++---------- fs/cifs/connect.c | 147 ++++++++++++++++++++++++------------------------- fs/cifs/dir.c | 2 - fs/cifs/file.c | 42 +++++++++++--- fs/cifs/inode.c | 29 ++++++++-- fs/cifs/link.c | 2 - fs/cifs/readdir.c | 2 - fs/cifs/sess.c | 27 +++------ fs/cifs/transport.c | 24 +++----- 18 files changed, 351 insertions(+), 186 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index bed6215..41e3b6a 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -6,7 +6,10 @@ (helps with certain sharing violation ca Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" mount option to allow disabling the CIFS Unix Extensions for just that mount. Fix hang on spinlock in find_writable_file (race when -reopening file after session crash). +reopening file after session crash). Byte range unlock request to +windows server could unlock more bytes (on server copy of file) +than intended if start of unlock request is well before start of +a previous byte range lock that we issued. Version 1.49 ------------ diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index f50a88d..2a01f3e 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx, unsigned long *optr; size = eoc - ctx->pointer + 1; - *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); - if (*oid == NULL) { + *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); + if (*oid == NULL) return 0; - } optr = *oid; @@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *secur return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, - ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end)); } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 1bf8cf5..56c5d91 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -209,13 +209,16 @@ #endif i++; tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); - length = - sprintf(buf, - "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " - "Attributes: 0x%x\nPathComponentMax: %d Status: %d", - i, tcon->treeName, - atomic_read(&tcon->useCount), - tcon->nativeFileSystem, + length = sprintf(buf, "\n%d) %s Uses: %d ", i, + tcon->treeName, atomic_read(&tcon->useCount)); + buf += length; + if (tcon->nativeFileSystem) { + length = sprintf(buf, "Type: %s ", + tcon->nativeFileSystem); + buf += length; + } + length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x" + "\nPathComponentMax: %d Status: %d", le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), le32_to_cpu(tcon->fsAttrInfo.Attributes), le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 5eff35d..97d03dc 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -22,12 +22,42 @@ #ifndef _CIFSACL_H #define _CIFSACL_H +struct cifs_ntsd { + __u16 revision; /* revision level */ + __u16 type; + __u32 osidoffset; + __u32 gsidoffset; + __u32 sacloffset; + __u32 dacloffset; +} __attribute__((packed)); + struct cifs_sid { __u8 revision; /* revision level */ - __u8 num_subauths; + __u8 num_auth; + __u8 authority[6]; + __u32 sub_auth[4]; + __u32 rid; +} __attribute__((packed)); + +struct cifs_acl { + __u16 revision; /* revision level */ + __u16 size; + __u32 num_aces; +} __attribute__((packed)); + +struct cifs_ntace { + __u8 type; + __u8 flags; + __u16 size; + __u32 access_req; +} __attribute__((packed)); + +struct cifs_ace { + __u8 revision; /* revision level */ + __u8 num_auth; __u8 authority[6]; __u32 sub_auth[4]; - /* next sub_auth if any ... */ + __u32 rid; } __attribute__((packed)); /* everyone */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index cabb6a5..c7c3521 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -240,9 +240,9 @@ static int cifs_permission(struct inode cifs_sb = CIFS_SB(inode->i_sb); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) return 0; - } else /* file mode might have been restricted at mount time + else /* file mode might have been restricted at mount time on the client (above and beyond ACL on servers) for servers which do not support setting and viewing mode bits, so allowing client to check permissions is useful */ @@ -346,7 +346,7 @@ int cifs_xquota_set(struct super_block * if (pTcon) { cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); } else { - return -EIO; + rc = -EIO; } FreeXid(xid); @@ -716,7 +716,7 @@ static int cifs_init_inodecache(void) { cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", - sizeof (struct cifsInodeInfo), + sizeof(struct cifsInodeInfo), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), cifs_init_once); @@ -816,8 +816,8 @@ static int cifs_init_mids(void) { cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", - sizeof (struct mid_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct mid_q_entry), 0, + SLAB_HWCACHE_ALIGN, NULL); if (cifs_mid_cachep == NULL) return -ENOMEM; @@ -829,8 +829,8 @@ cifs_init_mids(void) } cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", - sizeof (struct oplock_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct oplock_q_entry), 0, + SLAB_HWCACHE_ALIGN, NULL); if (cifs_oplock_cachep == NULL) { mempool_destroy(cifs_mid_poolp); kmem_cache_destroy(cifs_mid_cachep); @@ -882,7 +882,8 @@ static int cifs_oplock_thread(void *dumm the call */ /* mutex_lock(&inode->i_mutex);*/ if (S_ISREG(inode->i_mode)) { - rc = filemap_fdatawrite(inode->i_mapping); + rc = + filemap_fdatawrite(inode->i_mapping); if (CIFS_I(inode)->clientCanCacheRead == 0) { filemap_fdatawait(inode->i_mapping); @@ -907,8 +908,7 @@ static int cifs_oplock_thread(void *dumm 0 /* len */ , 0 /* offset */, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, 0 /* wait flag */); - cFYI(1, - ("Oplock release rc = %d ", rc)); + cFYI(1, ("Oplock release rc = %d", rc)); } } else spin_unlock(&GlobalMid_Lock); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a20de77..13c53a4 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -99,7 +99,7 @@ extern int cifs_setxattr(struct dentry size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -extern int cifs_ioctl (struct inode *inode, struct file *filep, +extern int cifs_ioctl(struct inode *inode, struct file *filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.50" +#define CIFS_VERSION "1.51" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b98742f..bb468de 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -19,6 +19,7 @@ #include #include #include "cifs_fs_sb.h" +#include "cifsacl.h" /* * The sizes of various internal tables and strings */ @@ -115,6 +116,17 @@ struct mac_key { } data; }; +struct cifs_cred { + int uid; + int gid; + int mode; + int cecount; + struct cifs_sid osid; + struct cifs_sid gsid; + struct cifs_ntace *ntaces; + struct cifs_ace *aces; +}; + /* ***************************************************************** * Except the CIFS PDUs themselves all the diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 6a2056e..e975ce4 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -360,10 +360,10 @@ struct smb_hdr { __u8 WordCount; } __attribute__((packed)); /* given a pointer to an smb_hdr retrieve the value of byte count */ -#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) -#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) +#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) +#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ -#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) +#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2) /* * Computer Name Length (since Netbios name was length 16 with last byte 0x20) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 04a69da..4ffae9d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -304,7 +304,7 @@ extern int cifs_calculate_mac_key(struct const char *pass); extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, const struct nls_table *); -extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); +extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, const struct nls_table *); #ifdef CONFIG_CIFS_WEAK_PW_HASH diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8eb102f..46c2bb4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -94,9 +94,8 @@ static void mark_open_files_invalid(stru write_lock(&GlobalSMBSeslock); list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { open_file = list_entry(tmp, struct cifsFileInfo, tlist); - if (open_file) { + if (open_file) open_file->invalidHandle = TRUE; - } } write_unlock(&GlobalSMBSeslock); /* BB Add call to invalidate_inodes(sb) for all superblocks mounted @@ -513,7 +512,7 @@ #ifdef CONFIG_CIFS_WEAK_PW_HASH (int)ts.tv_sec, (int)utc.tv_sec, (int)(utc.tv_sec - ts.tv_sec))); val = (int)(utc.tv_sec - ts.tv_sec); - seconds = val < 0 ? -val : val; + seconds = abs(val); result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; remain = seconds % MIN_TZ_ADJ; if (remain >= (MIN_TZ_ADJ / 2)) @@ -1112,7 +1111,7 @@ #endif } memcpy((char *) pRetData, (char *)psx_rsp + sizeof(OPEN_PSX_RSP), - sizeof (FILE_UNIX_BASIC_INFO)); + sizeof(FILE_UNIX_BASIC_INFO)); } psx_create_err: @@ -1193,9 +1192,9 @@ OldOpenRetry: } if (*pOplock & REQ_OPLOCK) pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); - else if (*pOplock & REQ_BATCHOPLOCK) { + else if (*pOplock & REQ_BATCHOPLOCK) pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); - } + pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ /* 0 = read @@ -1310,9 +1309,8 @@ openRetry: } if (*pOplock & REQ_OPLOCK) pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); - else if (*pOplock & REQ_BATCHOPLOCK) { + else if (*pOplock & REQ_BATCHOPLOCK) pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); - } pSMB->DesiredAccess = cpu_to_le32(access_flags); pSMB->AllocationSize = 0; /* set file as system file if special file such @@ -1446,11 +1444,11 @@ CIFSSMBRead(const int xid, struct cifsTc *nbytes = 0; } else { pReadData = (char *) (&pSMBr->hdr.Protocol) + - le16_to_cpu(pSMBr->DataOffset); -/* if (rc = copy_to_user(buf, pReadData, data_length)) { + le16_to_cpu(pSMBr->DataOffset); +/* if (rc = copy_to_user(buf, pReadData, data_length)) { cERROR(1,("Faulting on read rc = %d",rc)); rc = -EFAULT; - }*/ /* can not use copy_to_user when using page cache*/ + }*/ /* can not use copy_to_user when using page cache*/ if (*buf) memcpy(*buf, pReadData, data_length); } @@ -2538,7 +2536,7 @@ validate_ntransact(char *buf, char **ppp cFYI(1, ("data starts after end of smb")); return -EINVAL; } else if (data_count + *ppdata > end_of_smb) { - cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", + cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p", *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); return -EINVAL; @@ -2615,7 +2613,7 @@ CIFSSMBQueryReparseLinkInfo(const int xi reparse_buf->TargetNameOffset + reparse_buf->TargetNameLen) > end_of_smb) { - cFYI(1,("reparse buf goes beyond SMB")); + cFYI(1, ("reparse buf beyond SMB")); rc = -EIO; goto qreparse_out; } @@ -3050,17 +3048,110 @@ static const struct cifs_sid sid_everyon static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; +static void parse_sid(struct cifs_sid * psid, char * end_of_acl) +{ + /* BB need to add parm so we can store the SID BB */ + + /* validate that we do not go past end of acl */ + if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { + cERROR(1, ("ACL to small to parse SID")); + return; + } +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("revision %d num_auth %d First subauth 0x%x", + psid->revision, psid->num_auth, psid->sub_auth[0])); + + /* BB add length check to make sure that we do not have huge num auths + and therefore go off the end */ + cFYI(1, ("RID 0x%x", le32_to_cpu(psid->sub_auth[psid->num_auth]))); +#endif + return; +} + /* Convert CIFS ACL to POSIX form */ -static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len) +static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) { - return 0; + int i; + int num_aces = 0; + int acl_size; + struct cifs_sid *owner_sid_ptr, *group_sid_ptr; + struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ + struct cifs_ntace **ppntace; + struct cifs_ace **ppace; + char *acl_base; + char *end_of_acl = ((char *)pntsd) + acl_len; + + owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + + cpu_to_le32(pntsd->osidoffset)); + group_sid_ptr = (struct cifs_sid *)((char *)pntsd + + cpu_to_le32(pntsd->gsidoffset)); + dacl_ptr = (struct cifs_acl *)((char *)pntsd + + cpu_to_le32(pntsd->dacloffset)); +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1,("revision %d type 0x%x ooffset 0x%x goffset 0x%x " + "sacloffset 0x%x dacloffset 0x%x", pntsd->revision, pntsd->type, + pntsd->osidoffset, pntsd->gsidoffset, pntsd->sacloffset, + pntsd->dacloffset)); +#endif + parse_sid(owner_sid_ptr, end_of_acl); + parse_sid(group_sid_ptr, end_of_acl); + +/* cifscred->uid = owner_sid_ptr->rid; + cifscred->gid = group_sid_ptr->rid; + memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, + sizeof (struct cifs_sid)); + memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, + sizeof (struct cifs_sid)); */ + + num_aces = cpu_to_le32(dacl_ptr->num_aces); + cFYI(1, ("num aces %d", num_aces)); + if (num_aces > 0) { + ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), + GFP_KERNEL); + ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), + GFP_KERNEL); + +/* cifscred->cecount = dacl_ptr->num_aces; + cifscred->ntaces = kmalloc(num_aces * + sizeof(struct cifs_ntace *), GFP_KERNEL); + cifscred->aces = kmalloc(num_aces * + sizeof(struct cifs_ace *), GFP_KERNEL);*/ + + acl_base = (char *)dacl_ptr; + acl_size = sizeof(struct cifs_acl); + + for (i = 0; i < num_aces; ++i) { + ppntace[i] = (struct cifs_ntace *) + (acl_base + acl_size); + ppace[i] = (struct cifs_ace *) + ((char *)ppntace[i] + + sizeof(struct cifs_ntace)); + +/* memcpy((void *)(&(cifscred->ntaces[i])), + (void *)ntace_ptrptr[i], + sizeof(struct cifs_ntace)); + memcpy((void *)(&(cifscred->aces[i])), + (void *)ace_ptrptr[i], + sizeof(struct cifs_ace)); */ + + acl_base = (char *)ppntace[i]; + acl_size = cpu_to_le32(ppntace[i]->size); +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("ACE revision:%d", ppace[i]->revision)); + } +#endif + kfree(ppace); + kfree(ppntace); + } + + return (0); } /* Get Security Descriptor (by handle) from remote server for a file or dir */ int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, /* BB fix up return info */ char *acl_inf, const int buflen, - const int acl_type /* ACCESS/DEFAULT not sure implication */) + const int acl_type) { int rc = 0; int buf_type = 0; @@ -3090,7 +3181,7 @@ CIFSSMBGetCIFSACL(const int xid, struct if (rc) { cFYI(1, ("Send error in QuerySecDesc = %d", rc)); } else { /* decode response */ - struct cifs_sid *psec_desc; + struct cifs_ntsd *psec_desc; __le32 * parm; int parm_len; int data_len; @@ -3363,6 +3454,9 @@ UnixQPathInfoRetry: rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { + cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n" + "Unix Extensions can be disabled on mount " + "by specifying the nosfu mount option.")); rc = -EIO; /* bad smb */ } else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); @@ -3883,12 +3977,10 @@ getDFSRetry: pSMB->hdr.Mid = GetNextMid(ses->server); pSMB->hdr.Tid = ses->ipc_tid; pSMB->hdr.Uid = ses->Suid; - if (ses->capabilities & CAP_STATUS32) { + if (ses->capabilities & CAP_STATUS32) pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; - } - if (ses->capabilities & CAP_DFS) { + if (ses->capabilities & CAP_DFS) pSMB->hdr.Flags2 |= SMBFLG2_DFS; - } if (ses->capabilities & CAP_UNICODE) { pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; @@ -4265,7 +4357,7 @@ QFSAttributeRetry: *) (((char *) &pSMBr->hdr.Protocol) + data_offset); memcpy(&tcon->fsAttrInfo, response_data, - sizeof (FILE_SYSTEM_ATTRIBUTE_INFO)); + sizeof(FILE_SYSTEM_ATTRIBUTE_INFO)); } } cifs_buf_release(pSMB); @@ -4334,7 +4426,7 @@ QFSDeviceRetry: (((char *) &pSMBr->hdr.Protocol) + data_offset); memcpy(&tcon->fsDevInfo, response_data, - sizeof (FILE_SYSTEM_DEVICE_INFO)); + sizeof(FILE_SYSTEM_DEVICE_INFO)); } } cifs_buf_release(pSMB); @@ -4402,7 +4494,7 @@ QFSUnixRetry: *) (((char *) &pSMBr->hdr.Protocol) + data_offset); memcpy(&tcon->fsUnixInfo, response_data, - sizeof (FILE_SYSTEM_UNIX_INFO)); + sizeof(FILE_SYSTEM_UNIX_INFO)); } } cifs_buf_release(pSMB); @@ -4612,7 +4704,7 @@ SetEOFRetry: strncpy(pSMB->FileName, fileName, name_len); } params = 6 + name_len; - data_count = sizeof (struct file_end_of_file_info); + data_count = sizeof(struct file_end_of_file_info); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(4100); pSMB->MaxSetupCount = 0; @@ -4800,7 +4892,7 @@ CIFSSMBSetFileTimes(const int xid, struc data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - count = sizeof (FILE_BASIC_INFO); + count = sizeof(FILE_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ pSMB->SetupCount = 1; @@ -4871,7 +4963,7 @@ SetTimesRetry: } params = 6 + name_len; - count = sizeof (FILE_BASIC_INFO); + count = sizeof(FILE_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxSetupCount = 0; @@ -4900,7 +4992,7 @@ SetTimesRetry: pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; - memcpy(data_offset, data, sizeof (FILE_BASIC_INFO)); + memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); @@ -5003,7 +5095,7 @@ setPermsRetry: } params = 6 + name_len; - count = sizeof (FILE_UNIX_BASIC_INFO); + count = sizeof(FILE_UNIX_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxSetupCount = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4af3588..e43cb88 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *s struct mid_q_entry *mid_entry; spin_lock(&GlobalMid_Lock); - if ( kthread_should_stop() ) { + if (kthread_should_stop()) { /* the demux thread will exit normally next time through the loop */ spin_unlock(&GlobalMid_Lock); @@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *s } list_for_each(tmp, &GlobalTreeConnectionList) { tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); - if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { + if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) tcon->tidStatus = CifsNeedReconnect; - } } read_unlock(&GlobalSMBSeslock); /* do not want to be sending data on a socket we are freeing */ @@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *s spin_unlock(&GlobalMid_Lock); up(&server->tcpSem); - while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { + while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { try_to_freeze(); if (server->protocolType == IPV6) { rc = ipv6_connect(&server->addr.sockAddr6, @@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *s } else { atomic_inc(&tcpSesReconnectCount); spin_lock(&GlobalMid_Lock); - if ( !kthread_should_stop() ) + if (!kthread_should_stop()) server->tcpStatus = CifsGood; server->sequence_number = 0; spin_unlock(&GlobalMid_Lock); @@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Serve length = tcpSesAllocCount.counter; write_unlock(&GlobalSMBSeslock); complete(&cifsd_complete); - if (length > 1) { - mempool_resize(cifs_req_poolp, - length + cifs_min_rcv, - GFP_KERNEL); - } + if (length > 1) + mempool_resize(cifs_req_poolp, length + cifs_min_rcv, + GFP_KERNEL); set_freezable(); while (!kthread_should_stop()) { @@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Serve } } else if (isLargeBuf) { /* we are reusing a dirty large buf, clear its start */ - memset(bigbuf, 0, sizeof (struct smb_hdr)); + memset(bigbuf, 0, sizeof(struct smb_hdr)); } if (smallbuf == NULL) { @@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Serve } /* beginning of smb buffer is cleared in our buf_get */ } else /* if existing small buf clear beginning */ - memset(smallbuf, 0, sizeof (struct smb_hdr)); + memset(smallbuf, 0, sizeof(struct smb_hdr)); isLargeBuf = FALSE; isMultiRsp = FALSE; @@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Serve iov.iov_len = 4; smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; + pdu_length = 4; /* enough to get RFC1001 header */ +incomplete_rcv: length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, 4, 0 /* BB see socket.h flags */); + &iov, 1, pdu_length, 0 /* BB other flags? */); - if ( kthread_should_stop() ) { + if (kthread_should_stop()) { break; } else if (server->tcpStatus == CifsNeedReconnect) { cFYI(1, ("Reconnect after server stopped responding")); @@ -437,13 +436,11 @@ cifs_demultiplex_thread(struct TCP_Serve wake_up(&server->response_q); continue; } else if (length < 4) { - cFYI(1, - ("Frame under four bytes received (%d bytes long)", + cFYI(1, ("less than four bytes received (%d bytes)", length)); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; + pdu_length -= length; + msleep(1); + goto incomplete_rcv; } /* The right amount was read from socket - 4 bytes */ @@ -504,7 +501,7 @@ cifs_demultiplex_thread(struct TCP_Serve /* else we have an SMB response */ if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || - (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { + (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { cERROR(1, ("Invalid size SMB length %d pdu_length %d", length, pdu_length+4)); cifs_reconnect(server); @@ -528,7 +525,7 @@ cifs_demultiplex_thread(struct TCP_Serve total_read += length) { length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, pdu_length - total_read, 0); - if ( kthread_should_stop() || + if (kthread_should_stop() || (length == -EINTR)) { /* then will exit */ reconnect = 2; @@ -631,9 +628,9 @@ #endif /* Was previous buf put in mpx struct for multi-rsp? */ if (!isMultiRsp) { /* smb buffer will be freed by user thread */ - if (isLargeBuf) { + if (isLargeBuf) bigbuf = NULL; - } else + else smallbuf = NULL; } wake_up_process(task_to_wake); @@ -702,9 +699,8 @@ #endif /* CIFS_DEBUG2 */ list_for_each(tmp, &GlobalSMBSessionList) { ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); - if (ses->server == server) { + if (ses->server == server) ses->status = CifsExiting; - } } spin_lock(&GlobalMid_Lock); @@ -714,9 +710,8 @@ #endif /* CIFS_DEBUG2 */ cFYI(1, ("Clearing Mid 0x%x - waking up ", mid_entry->mid)); task_to_wake = mid_entry->tsk; - if (task_to_wake) { + if (task_to_wake) wake_up_process(task_to_wake); - } } } spin_unlock(&GlobalMid_Lock); @@ -749,18 +744,15 @@ #endif /* CIFS_DEBUG2 */ list_for_each(tmp, &GlobalSMBSessionList) { ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); - if (ses->server == server) { + if (ses->server == server) ses->server = NULL; - } } write_unlock(&GlobalSMBSeslock); kfree(server); - if (length > 0) { - mempool_resize(cifs_req_poolp, - length + cifs_min_rcv, - GFP_KERNEL); - } + if (length > 0) + mempool_resize(cifs_req_poolp, length + cifs_min_rcv, + GFP_KERNEL); return 0; } @@ -1750,7 +1742,16 @@ #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("very large write cap")); #endif /* CIFS_DEBUG2 */ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { - cFYI(1, ("setting capabilities failed")); + if (vol_info == NULL) { + cFYI(1, ("resetting capabilities failed")); + } else + cERROR(1, ("Negotiating Unix capabilities " + "with the server failed. Consider " + "mounting with the Unix Extensions\n" + "disabled, if problems are found, " + "by specifying the nounix mount " + "option.")); + } } } @@ -2979,36 +2980,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { - __u16 len = - cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, + __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, nls_codepage); - len *= 2; + ln *= 2; SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(len); + cpu_to_le16(ln); SecurityBlob->DomainName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->DomainName.Length = - cpu_to_le16(len); + bcc_ptr += ln; + SecurityBlobLength += ln; + SecurityBlob->DomainName.Length = cpu_to_le16(ln); } if (user == NULL) { SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.MaximumLength = 0; } else { - __u16 len = - cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, + __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, nls_codepage); - len *= 2; + ln *= 2; SecurityBlob->UserName.MaximumLength = - cpu_to_le16(len); + cpu_to_le16(ln); SecurityBlob->UserName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->UserName.Length = - cpu_to_le16(len); + bcc_ptr += ln; + SecurityBlobLength += ln; + SecurityBlob->UserName.Length = cpu_to_le16(ln); } /* SecurityBlob->WorkstationName.Length = @@ -3052,33 +3049,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { - __u16 len; + __u16 ln; negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; strncpy(bcc_ptr, domain, 63); - len = strnlen(domain, 64); + ln = strnlen(domain, 64); SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(len); + cpu_to_le16(ln); SecurityBlob->DomainName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->DomainName.Length = cpu_to_le16(len); + bcc_ptr += ln; + SecurityBlobLength += ln; + SecurityBlob->DomainName.Length = cpu_to_le16(ln); } if (user == NULL) { SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.MaximumLength = 0; } else { - __u16 len; + __u16 ln; strncpy(bcc_ptr, user, 63); - len = strnlen(user, 64); - SecurityBlob->UserName.MaximumLength = - cpu_to_le16(len); + ln = strnlen(user, 64); + SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); SecurityBlob->UserName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->UserName.Length = cpu_to_le16(len); + cpu_to_le32(SecurityBlobLength); + bcc_ptr += ln; + SecurityBlobLength += ln; + SecurityBlob->UserName.Length = cpu_to_le16(ln); } /* BB fill in our workstation name if known BB */ @@ -3145,8 +3141,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi } else { remaining_words = BCC(smb_buffer_response) / 2; } - len = - UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); + len = UniStrnlen((wchar_t *) bcc_ptr, + remaining_words - 1); /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ @@ -3230,7 +3226,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi <= BCC(smb_buffer_response)) { if (ses->serverOS) kfree(ses->serverOS); - ses->serverOS = kzalloc(len + 1,GFP_KERNEL); + ses->serverOS = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverOS,bcc_ptr, len); bcc_ptr += len; @@ -3399,9 +3395,11 @@ #endif /* CIFS_WEAK_PW_HASH */ kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 2, GFP_KERNEL); - cifs_strfromUCS_le(tcon->nativeFileSystem, - (__le16 *) bcc_ptr, - length, nls_codepage); + if (tcon->nativeFileSystem) + cifs_strfromUCS_le( + tcon->nativeFileSystem, + (__le16 *) bcc_ptr, + length, nls_codepage); bcc_ptr += 2 * length; bcc_ptr[0] = 0; /* null terminate the string */ bcc_ptr[1] = 0; @@ -3416,8 +3414,9 @@ #endif /* CIFS_WEAK_PW_HASH */ kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 1, GFP_KERNEL); - strncpy(tcon->nativeFileSystem, bcc_ptr, - length); + if (tcon->nativeFileSystem) + strncpy(tcon->nativeFileSystem, bcc_ptr, + length); } /* else do not bother copying these information fields*/ } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 4830acc..db5287a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, stru /* BB Do not bother to decode buf since no local inode yet to put timestamps in, but we can reuse it safely */ - int bytes_written; + unsigned int bytes_written; struct win_dev *pdev; pdev = (struct win_dev *)buf; if (S_ISCHR(mode)) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 894b1f7..7925491 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -467,7 +467,7 @@ reopen_error_exit: int cifs_close(struct inode *inode, struct file *file) { int rc = 0; - int xid; + int xid, timeout; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; struct cifsFileInfo *pSMBFile = @@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, stru /* no sense reconnecting to close a file that is already closed */ if (pTcon->tidStatus != CifsNeedReconnect) { - int timeout = 2; + timeout = 2; while ((atomic_read(&pSMBFile->wrtPending) != 0) - && (timeout < 1000) ) { + && (timeout <= 2048)) { /* Give write a better chance to get to server ahead of the close. We do not want to add a wait_q here as it would @@ -522,12 +522,30 @@ #endif /* DEBUG2 */ list_del(&pSMBFile->flist); list_del(&pSMBFile->tlist); write_unlock(&GlobalSMBSeslock); + timeout = 10; + /* We waited above to give the SMBWrite a chance to issue + on the wire (so we do not get SMBWrite returning EBADF + if writepages is racing with close. Note that writepages + does not specify a file handle, so it is possible for a file + to be opened twice, and the application close the "wrong" + file handle - in these cases we delay long enough to allow + the SMBWrite to get on the wire before the SMB Close. + We allow total wait here over 45 seconds, more than + oplock break time, and more than enough to allow any write + to complete on the server, or to time out on the client */ + while ((atomic_read(&pSMBFile->wrtPending) != 0) + && (timeout <= 50000)) { + cERROR(1, ("writes pending, delay free of handle")); + msleep(timeout); + timeout *= 8; + } kfree(pSMBFile->search_resume_name); kfree(file->private_data); file->private_data = NULL; } else rc = -EBADF; + read_lock(&GlobalSMBSeslock); if (list_empty(&(CIFS_I(inode)->openFileList))) { cFYI(1, ("closing last open instance for inode %p", inode)); /* if the file is not open we do not know if we can cache info @@ -535,6 +553,7 @@ #endif /* DEBUG2 */ CIFS_I(inode)->clientCanCacheRead = FALSE; CIFS_I(inode)->clientCanCacheAll = FALSE; } + read_unlock(&GlobalSMBSeslock); if ((rc == 0) && CIFS_I(inode)->write_behind_rc) rc = CIFS_I(inode)->write_behind_rc; FreeXid(xid); @@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd mutex_lock(&fid->lock_mutex); list_for_each_entry_safe(li, tmp, &fid->llist, llist) { if (pfLock->fl_start <= li->offset && - length >= li->length) { + (pfLock->fl_start + length) >= + (li->offset + li->length)) { stored_rc = CIFSSMBLock(xid, pTcon, netfid, li->length, li->offset, @@ -1030,22 +1050,24 @@ struct cifsFileInfo *find_writable_file( (open_file->pfile->f_flags & O_WRONLY))) { atomic_inc(&open_file->wrtPending); read_unlock(&GlobalSMBSeslock); - if ((open_file->invalidHandle) && - (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) { + if (open_file->invalidHandle) { rc = cifs_reopen_file(open_file->pfile, FALSE); /* if it fails, try another handle - might be */ /* dangerous to hold up writepages with retry */ if (rc) { - cFYI(1, - ("failed on reopen file in wp")); + cFYI(1, ("wp failed on reopen file")); read_lock(&GlobalSMBSeslock); /* can not use this handle, no write pending on this one after all */ - atomic_dec - (&open_file->wrtPending); + atomic_dec(&open_file->wrtPending); continue; } } + if (open_file->closePend) { + read_lock(&GlobalSMBSeslock); + atomic_dec(&open_file->wrtPending); + continue; + } return open_file; } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index dd41677..552d68b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -919,18 +919,24 @@ int cifs_mkdir(struct inode *inode, stru goto mkdir_out; } + mode &= ~current->fs->umask; rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, NULL /* netfid */, pInfo, &oplock, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) { + if (rc == -EOPNOTSUPP) { + kfree(pInfo); + goto mkdir_retry_old; + } else if (rc) { cFYI(1, ("posix mkdir returned 0x%x", rc)); d_drop(direntry); } else { int obj_type; - if (pInfo->Type == -1) /* no return info - go query */ + if (pInfo->Type == -1) /* no return info - go query */ { + kfree(pInfo); goto mkdir_get_info; + } /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */ inc_nlink(inode); @@ -940,8 +946,10 @@ int cifs_mkdir(struct inode *inode, stru direntry->d_op = &cifs_dentry_ops; newinode = new_inode(inode->i_sb); - if (newinode == NULL) + if (newinode == NULL) { + kfree(pInfo); goto mkdir_get_info; + } /* Is an i_ino of zero legal? */ /* Are there sanity checks we can use to ensure that the server is really filling in that field? */ @@ -972,7 +980,7 @@ #endif kfree(pInfo); goto mkdir_out; } - +mkdir_retry_old: /* BB add setting the equivalent of mode via CreateX w/ACLs */ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -1377,8 +1385,17 @@ static int cifs_vmtruncate(struct inode } i_size_write(inode, offset); spin_unlock(&inode->i_lock); + /* + * unmap_mapping_range is called twice, first simply for efficiency + * so that truncate_inode_pages does fewer single-page unmaps. However + * after this first call, and before truncate_inode_pages finishes, + * it is possible for private pages to be COWed, which remain after + * truncate_inode_pages finishes, hence the second unmap_mapping_range + * call must be made for correctness. + */ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); truncate_inode_pages(mapping, offset); + unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); goto out_truncate; do_expand: @@ -1469,7 +1486,7 @@ int cifs_setattr(struct dentry *direntry atomic_dec(&open_file->wrtPending); cFYI(1, ("SetFSize for attrs rc = %d", rc)); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { - int bytes_written; + unsigned int bytes_written; rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, &bytes_written, NULL, NULL, @@ -1502,7 +1519,7 @@ int cifs_setattr(struct dentry *direntry cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { - int bytes_written; + unsigned int bytes_written; rc = CIFSSMBWrite(xid, pTcon, netfid, 0, attrs->ia_size, diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 6a85ef7..11f2657 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, c char *tmp_path = NULL; char *tmpbuffer; unsigned char *referrals = NULL; - int num_referrals = 0; + unsigned int num_referrals = 0; int len; __u16 fid; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 916df94..b5a9bff 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ - cERROR(1,("past end of SMB num to fill %d i %d", + cERROR(1, ("past SMB end, num to fill %d i %d", num_to_fill, i)); break; } diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 892be9b..78797c0 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -67,9 +67,8 @@ static __u32 cifs_ssetup_hdr(struct cifs pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; capabilities |= CAP_DFS; } - if (ses->capabilities & CAP_UNIX) { + if (ses->capabilities & CAP_UNIX) capabilities |= CAP_UNIX; - } /* BB check whether to init vcnum BB */ return capabilities; @@ -203,14 +202,11 @@ static int decode_unicode_ssetup(char ** if (len >= words_left) return rc; - if (ses->serverOS) - kfree(ses->serverOS); + kfree(ses->serverOS); /* UTF-8 string will not grow more than four times as big as UCS-16 */ ses->serverOS = kzalloc(4 * len, GFP_KERNEL); - if (ses->serverOS != NULL) { - cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, - nls_cp); - } + if (ses->serverOS != NULL) + cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); data += 2 * (len + 1); words_left -= len + 1; @@ -220,8 +216,7 @@ static int decode_unicode_ssetup(char ** if (len >= words_left) return rc; - if (ses->serverNOS) - kfree(ses->serverNOS); + kfree(ses->serverNOS); ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ if (ses->serverNOS != NULL) { cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, @@ -240,8 +235,7 @@ static int decode_unicode_ssetup(char ** if (len > words_left) return rc; - if (ses->serverDomain) - kfree(ses->serverDomain); + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ if (ses->serverDomain != NULL) { cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, @@ -271,8 +265,7 @@ static int decode_ascii_ssetup(char **pb if (len >= bleft) return rc; - if (ses->serverOS) - kfree(ses->serverOS); + kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1, GFP_KERNEL); if (ses->serverOS) @@ -289,8 +282,7 @@ static int decode_ascii_ssetup(char **pb if (len >= bleft) return rc; - if (ses->serverNOS) - kfree(ses->serverNOS); + kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); if (ses->serverNOS) @@ -479,7 +471,8 @@ #endif if (ses->capabilities & CAP_UNICODE) { if (iov[0].iov_len % 2) { *bcc_ptr = 0; - } bcc_ptr++; + bcc_ptr++; + } unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 746bc94..6684926 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb if (temp == NULL) return temp; else { - memset(temp, 0, sizeof (struct mid_q_entry)); + memset(temp, 0, sizeof(struct mid_q_entry)); temp->mid = smb_buffer->Mid; /* always LE */ temp->pid = current->pid; temp->command = smb_buffer->Command; @@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct iov.iov_len = len; smb_msg.msg_name = sin; - smb_msg.msg_namelen = sizeof (struct sockaddr); + smb_msg.msg_namelen = sizeof(struct sockaddr); smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ @@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct return -ENOTSOCK; /* BB eventually add reconnect code here */ smb_msg.msg_name = sin; - smb_msg.msg_namelen = sizeof (struct sockaddr); + smb_msg.msg_namelen = sizeof(struct sockaddr); smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ @@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesIn } /* else ok - we are setting up session */ } *ppmidQ = AllocMidQEntry(in_buf, ses); - if (*ppmidQ == NULL) { + if (*ppmidQ == NULL) return -ENOMEM; - } return 0; } @@ -572,9 +571,8 @@ #endif rc = map_smb_to_linux_error(midQ->resp_buf); /* convert ByteCount if necessary */ - if (receive_len >= - sizeof (struct smb_hdr) - - 4 /* do not count RFC1001 header */ + + if (receive_len >= sizeof(struct smb_hdr) - 4 + /* do not count RFC1001 header */ + (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) BCC(midQ->resp_buf) = le16_to_cpu(BCC_LE(midQ->resp_buf)); @@ -752,9 +750,8 @@ #endif rc = map_smb_to_linux_error(out_buf); /* convert ByteCount if necessary */ - if (receive_len >= - sizeof (struct smb_hdr) - - 4 /* do not count RFC1001 header */ + + if (receive_len >= sizeof(struct smb_hdr) - 4 + /* do not count RFC1001 header */ + (2 * out_buf->WordCount) + 2 /* bcc */ ) BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); } else { @@ -996,9 +993,8 @@ #endif rc = map_smb_to_linux_error(out_buf); /* convert ByteCount if necessary */ - if (receive_len >= - sizeof (struct smb_hdr) - - 4 /* do not count RFC1001 header */ + + if (receive_len >= sizeof(struct smb_hdr) - 4 + /* do not count RFC1001 header */ + (2 * out_buf->WordCount) + 2 /* bcc */ ) BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); } else {