From 47df1793171771ff9b1622d30433ef6edf0eb280 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 25 Apr 2008 02:01:44 +0000 Subject: [CIFS] Update cifs version number Signed-off-by: Steve French --- fs/cifs/cifsfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index e1dd9f32e1d..503f6aa734a 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -110,5 +110,5 @@ extern int cifs_ioctl(struct inode *inode, struct file *filep, extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.52" +#define CIFS_VERSION "1.53" #endif /* _CIFSFS_H */ -- cgit v1.2.3-70-g09d2 From 0206e61b467fde4d7b50f1a64355182a4fd9576b Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 25 Apr 2008 18:19:40 +0000 Subject: [CIFS] Fix spelling mistake Noticed by Joe Perches Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 9f49c2f3582..a0d26b540d4 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -2050,7 +2050,7 @@ typedef struct { to 0xFFFF00 */ #define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080 #define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */ -#define CIFS_UNIX_TRANPSORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */ +#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */ #define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and QFS PROXY call */ #ifdef CONFIG_CIFS_POSIX -- cgit v1.2.3-70-g09d2 From d09e860cf07e7c9ee12920a09f5080e30a12a23a Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 26 Apr 2008 00:22:23 +0000 Subject: [CIFS] Adds to dns_resolver checking if the server name is an IP addr and skipping upcall in this case. Signed-off-by: Igor Mammedov Signed-off-by: sfrench@us.ibm.com --- fs/cifs/dns_resolve.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 7cc86c41818..939e256f849 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -55,6 +55,32 @@ struct key_type key_type_dns_resolver = { .match = user_match, }; +/* Checks if supplied name is IP address + * returns: + * 1 - name is IP + * 0 - name is not IP + */ +static int is_ip(const char *name) +{ + int rc; + struct sockaddr_in sin_server; + struct sockaddr_in6 sin_server6; + + rc = cifs_inet_pton(AF_INET, name, + &sin_server.sin_addr.s_addr); + + if (rc <= 0) { + /* not ipv4 address, try ipv6 */ + rc = cifs_inet_pton(AF_INET6, name, + &sin_server6.sin6_addr.in6_u); + if (rc > 0) + return 1; + } else { + return 1; + } + /* we failed translating address */ + return 0; +} /* Resolves server name to ip address. * input: @@ -67,8 +93,9 @@ int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) { int rc = -EAGAIN; - struct key *rkey; + struct key *rkey = ERR_PTR(-EAGAIN); char *name; + char *data = NULL; int len; if (!ip_addr || !unc) @@ -97,26 +124,41 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) memcpy(name, unc+2, len); name[len] = 0; + if (is_ip(name)) { + cFYI(1, ("%s: it is IP, skipping dns upcall: %s", + __func__, name)); + data = name; + goto skip_upcall; + } + rkey = request_key(&key_type_dns_resolver, name, ""); if (!IS_ERR(rkey)) { - len = strlen(rkey->payload.data); - *ip_addr = kmalloc(len+1, GFP_KERNEL); - if (*ip_addr) { - memcpy(*ip_addr, rkey->payload.data, len); - (*ip_addr)[len] = '\0'; - cFYI(1, ("%s: resolved: %s to %s", __func__, + data = rkey->payload.data; + cFYI(1, ("%s: resolved: %s to %s", __func__, rkey->description, *ip_addr )); + } else { + cERROR(1, ("%s: unable to resolve: %s", __func__, name)); + goto out; + } + +skip_upcall: + if (data) { + len = strlen(data); + *ip_addr = kmalloc(len+1, GFP_KERNEL); + if (*ip_addr) { + memcpy(*ip_addr, data, len); + (*ip_addr)[len] = '\0'; rc = 0; } else { rc = -ENOMEM; } - key_put(rkey); - } else { - cERROR(1, ("%s: unable to resolve: %s", __func__, name)); + if (!IS_ERR(rkey)) + key_put(rkey); } +out: kfree(name); return rc; } -- cgit v1.2.3-70-g09d2 From 39da9847113a870b20fee9a7c216a848b9a5e9f7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 28 Apr 2008 04:04:34 +0000 Subject: [CIFS] Fix statfs formatting Signed-off-by: Christoph Hellwig Signed-off-by: Steve French --- fs/cifs/CHANGES | 3 +++ fs/cifs/cifsfs.c | 66 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 36 insertions(+), 33 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 05c9da6181c..8355e918fdd 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,6 @@ +Version 1.53 +------------ + Version 1.52 ------------ Fix oops on second mount to server when null auth is used. diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 39c2cbdface..68f1cdf6aed 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -222,50 +222,50 @@ static int cifs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; - int xid; + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + struct cifsTconInfo *tcon = cifs_sb->tcon; int rc = -EOPNOTSUPP; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; + int xid; xid = GetXid(); - cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb->tcon; - buf->f_type = CIFS_MAGIC_NUMBER; - /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ - buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would - presumably be total path, but note - that some servers (includinng Samba 3) - have a shorter maximum path */ + /* + * PATH_MAX may be too long - it would presumably be total path, + * but note that some servers (includinng Samba 3) have a shorter + * maximum path. + * + * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO. + */ + buf->f_namelen = PATH_MAX; buf->f_files = 0; /* undefined */ buf->f_ffree = 0; /* unlimited */ -/* BB we could add a second check for a QFS Unix capability bit */ -/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ - if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & - le64_to_cpu(pTcon->fsUnixInfo.Capability))) - rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); - - /* Only need to call the old QFSInfo if failed - on newer one */ - if (rc) - if (pTcon->ses->capabilities & CAP_NT_SMBS) - rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */ - - /* Some old Windows servers also do not support level 103, retry with - older level one if old server failed the previous call or we - bypassed it because we detected that this was an older LANMAN sess */ + /* + * We could add a second check for a QFS Unix capability bit + */ + if ((tcon->ses->capabilities & CAP_UNIX) && + (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability))) + rc = CIFSSMBQFSPosixInfo(xid, tcon, buf); + + /* + * Only need to call the old QFSInfo if failed on newer one, + * e.g. by OS/2. + **/ + if (rc && (tcon->ses->capabilities & CAP_NT_SMBS)) + rc = CIFSSMBQFSInfo(xid, tcon, buf); + + /* + * Some old Windows servers also do not support level 103, retry with + * older level one if old server failed the previous call or we + * bypassed it because we detected that this was an older LANMAN sess + */ if (rc) - rc = SMBOldQFSInfo(xid, pTcon, buf); - /* int f_type; - __fsid_t f_fsid; - int f_namelen; */ - /* BB get from info in tcon struct at mount time call to QFSAttrInfo */ + rc = SMBOldQFSInfo(xid, tcon, buf); + FreeXid(xid); - return 0; /* always return success? what if volume is no - longer available? */ + return 0; } static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd) -- cgit v1.2.3-70-g09d2 From bf62fd887cab230f5952b611bde25e8e15acb454 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 28 Apr 2008 23:05:58 +0000 Subject: [CIFS] fixed compatibility issue with samba refferal request treeName part is canonicalized to '/' path separator Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 95024c066d8..f6fdecf6598 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -93,15 +93,11 @@ static char *cifs_get_share_name(const char *node_name) /* find sharename end */ pSep++; pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); - if (!pSep) { - cERROR(1, ("%s:2 cant find share name in node name: %s", - __func__, node_name)); - kfree(UNC); - return NULL; + if (pSep) { + /* trim path up to sharename end + * now we have share name in UNC */ + *pSep = 0; } - /* trim path up to sharename end - * * now we have share name in UNC */ - *pSep = 0; return UNC; } @@ -188,7 +184,7 @@ static char *compose_mount_options(const char *sb_mountdata, tkn_e = strchr(tkn_e+1, '\\'); if (tkn_e) { strcat(mountdata, ",prefixpath="); - strcat(mountdata, tkn_e); + strcat(mountdata, tkn_e+1); } } @@ -244,7 +240,8 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry) return NULL; if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) { - /* we should use full path name to correct working with DFS */ + int i; + /* we should use full path name for correct working with DFS */ l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) + strnlen(search_path, MAX_PATHCONF) + 1; tmp_path = kmalloc(l_max_len, GFP_KERNEL); @@ -253,8 +250,14 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry) return NULL; } strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len); - strcat(tmp_path, search_path); tmp_path[l_max_len-1] = 0; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) + for (i = 0; i < l_max_len; i++) { + if (tmp_path[i] == '\\') + tmp_path[i] = '/'; + } + strncat(tmp_path, search_path, l_max_len - strlen(tmp_path)); + full_path = tmp_path; kfree(search_path); } else { -- cgit v1.2.3-70-g09d2 From 4b18f2a9c3964f7612b7403dddc1d1ba5443ae24 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Apr 2008 00:06:05 +0000 Subject: [CIFS] convert usage of implicit booleans to bool Signed-off-by: Joe Perches Signed-off-by: Steve French --- fs/cifs/asn1.c | 10 +++---- fs/cifs/cifsacl.c | 16 +++++------ fs/cifs/cifsfs.c | 6 ++-- fs/cifs/cifsfs.h | 8 ------ fs/cifs/cifsglob.h | 44 ++++++++++++----------------- fs/cifs/cifsproto.h | 13 +++++---- fs/cifs/cifssmb.c | 38 ++++++++++++------------- fs/cifs/connect.c | 80 ++++++++++++++++++++++++++-------------------------- fs/cifs/dir.c | 18 ++++++------ fs/cifs/fcntl.c | 2 +- fs/cifs/file.c | 80 ++++++++++++++++++++++++++-------------------------- fs/cifs/inode.c | 42 +++++++++++++-------------- fs/cifs/link.c | 2 +- fs/cifs/misc.c | 33 +++++++++++----------- fs/cifs/readdir.c | 12 ++++---- fs/cifs/smbencrypt.c | 8 +++--- fs/cifs/xattr.c | 2 +- 17 files changed, 200 insertions(+), 214 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index bcda2c6b6a0..cb52cbbe45f 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -460,8 +460,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, unsigned char *sequence_end; unsigned long *oid = NULL; unsigned int cls, con, tag, oidlen, rc; - int use_ntlmssp = FALSE; - int use_kerberos = FALSE; + bool use_ntlmssp = false; + bool use_kerberos = false; *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ @@ -561,15 +561,15 @@ decode_negTokenInit(unsigned char *security_blob, int length, if (compare_oid(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN)) - use_kerberos = TRUE; + use_kerberos = true; else if (compare_oid(oid, oidlen, KRB5_OID, KRB5_OID_LEN)) - use_kerberos = TRUE; + use_kerberos = true; else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) - use_ntlmssp = TRUE; + use_ntlmssp = true; kfree(oid); } diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index e99d4faf5f0..6fe1bc5bb36 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -559,7 +559,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, const char *path, const __u16 *pfid) { struct cifsFileInfo *open_file = NULL; - int unlock_file = FALSE; + bool unlock_file = false; int xid; int rc = -EIO; __u16 fid; @@ -586,10 +586,10 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, cifs_sb = CIFS_SB(sb); if (open_file) { - unlock_file = TRUE; + unlock_file = true; fid = open_file->netfid; } else if (pfid == NULL) { - int oplock = FALSE; + bool oplock = false; /* open file */ rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0, &fid, &oplock, NULL, @@ -604,7 +604,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); - if (unlock_file == TRUE) /* find_readable_file increments ref count */ + if (unlock_file == true) /* find_readable_file increments ref count */ atomic_dec(&open_file->wrtPending); else if (pfid == NULL) /* if opened above we have to close the handle */ CIFSSMBClose(xid, cifs_sb->tcon, fid); @@ -619,7 +619,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, struct inode *inode, const char *path) { struct cifsFileInfo *open_file; - int unlock_file = FALSE; + bool unlock_file = false; int xid; int rc = -EIO; __u16 fid; @@ -640,10 +640,10 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, open_file = find_readable_file(CIFS_I(inode)); if (open_file) { - unlock_file = TRUE; + unlock_file = true; fid = open_file->netfid; } else { - int oplock = FALSE; + int oplock = 0; /* open file */ rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0, &fid, &oplock, NULL, @@ -658,7 +658,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); - if (unlock_file == TRUE) + if (unlock_file) atomic_dec(&open_file->wrtPending); else CIFSSMBClose(xid, cifs_sb->tcon, fid); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 68f1cdf6aed..427a7c69589 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -306,8 +306,8 @@ cifs_alloc_inode(struct super_block *sb) /* Until the file is open and we have gotten oplock info back from the server, can not assume caching of file data or metadata */ - cifs_inode->clientCanCacheRead = FALSE; - cifs_inode->clientCanCacheAll = FALSE; + cifs_inode->clientCanCacheRead = false; + cifs_inode->clientCanCacheAll = false; cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ /* Can not set i_flags here - they get immediately overwritten @@ -940,7 +940,7 @@ static int cifs_oplock_thread(void *dummyarg) rc = CIFSSMBLock(0, pTcon, netfid, 0 /* len */ , 0 /* offset */, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, - 0 /* wait flag */); + false /* wait flag */); cFYI(1, ("Oplock release rc = %d", rc)); } } else diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 503f6aa734a..cd1301a09b3 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -24,14 +24,6 @@ #define ROOT_I 2 -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 69a2e194254..b7d9f698e63 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -57,14 +57,6 @@ #include "cifspdu.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - #ifndef XATTR_DOS_ATTRIB #define XATTR_DOS_ATTRIB "user.DOSATTRIB" #endif @@ -147,7 +139,7 @@ struct TCP_Server_Info { enum protocolEnum protocolType; char versionMajor; char versionMinor; - unsigned svlocal:1; /* local server or remote */ + bool svlocal:1; /* local server or remote */ atomic_t socketUseCount; /* number of open cifs sessions on socket */ atomic_t inFlight; /* number of requests on the wire to server */ #ifdef CONFIG_CIFS_STATS2 @@ -286,10 +278,10 @@ struct cifsTconInfo { FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ FILE_SYSTEM_UNIX_INFO fsUnixInfo; - unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ - unsigned retry:1; - unsigned nocase:1; - unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol + bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ + bool retry:1; + bool nocase:1; + bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol for this mount even if server would support */ /* BB add field for back pointer to sb struct(s)? */ }; @@ -317,10 +309,10 @@ struct cifs_search_info { char *srch_entries_start; char *presume_name; unsigned int resume_name_len; - unsigned endOfSearch:1; - unsigned emptyDir:1; - unsigned unicode:1; - unsigned smallBuf:1; /* so we know which buf_release function to call */ + bool endOfSearch:1; + bool emptyDir:1; + bool unicode:1; + bool smallBuf:1; /* so we know which buf_release function to call */ }; struct cifsFileInfo { @@ -335,9 +327,9 @@ struct cifsFileInfo { struct inode *pInode; /* needed for oplock break */ struct mutex lock_mutex; struct list_head llist; /* list of byte range locks we have. */ - unsigned closePend:1; /* file is marked to close */ - unsigned invalidHandle:1; /* file closed via session abend */ - unsigned messageMode:1; /* for pipes: message vs byte mode */ + bool closePend:1; /* file is marked to close */ + bool invalidHandle:1; /* file closed via session abend */ + bool messageMode:1; /* for pipes: message vs byte mode */ atomic_t wrtPending; /* handle in use - defer close */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ char *search_resume_name; /* BB removeme BB */ @@ -356,9 +348,9 @@ struct cifsInodeInfo { __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ unsigned long time; /* jiffies of last update/check of inode */ - unsigned clientCanCacheRead:1; /* read oplock */ - unsigned clientCanCacheAll:1; /* read and writebehind oplock */ - unsigned oplockPending:1; + bool clientCanCacheRead:1; /* read oplock */ + bool clientCanCacheAll:1; /* read and writebehind oplock */ + bool oplockPending:1; struct inode vfs_inode; }; @@ -426,9 +418,9 @@ struct mid_q_entry { struct smb_hdr *resp_buf; /* response buffer */ int midState; /* wish this were enum but can not pass to wait_event */ __u8 command; /* smb command code */ - unsigned largeBuf:1; /* if valid response, is pointer to large buf */ - unsigned multiRsp:1; /* multiple trans2 responses for one request */ - unsigned multiEnd:1; /* both received */ + bool largeBuf:1; /* if valid response, is pointer to large buf */ + bool multiRsp:1; /* multiple trans2 responses for one request */ + bool multiEnd:1; /* both received */ }; struct oplock_q_entry { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 50f9fdae19b..a249a29109a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -59,8 +59,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid, struct smb_hdr *out_buf, int *bytes_returned); extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); -extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); -extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); +extern bool is_valid_oplock_break(struct smb_hdr *smb, + struct TCP_Server_Info *); +extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); #ifdef CONFIG_CIFS_EXPERIMENTAL extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); @@ -187,12 +188,12 @@ extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, #endif /* possibly unneeded function */ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, __u64 size, - int setAllocationSizeFlag, + bool setAllocationSizeFlag, const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, __u16 fileHandle, __u32 opener_pid, - int AllocSizeFlag); + bool AllocSizeFlag); extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, char *full_path, __u64 mode, __u64 uid, __u64 gid, dev_t dev, @@ -291,11 +292,11 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 netfid, const __u64 len, const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, - const int waitFlag); + const bool waitFlag); extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const int get_flag, const __u64 len, struct file_lock *, - const __u16 lock_type, const int waitFlag); + const __u16 lock_type, const bool waitFlag); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4728fa982a4..cfd9750852b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -95,7 +95,7 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { open_file = list_entry(tmp, struct cifsFileInfo, tlist); if (open_file) - open_file->invalidHandle = TRUE; + open_file->invalidHandle = true; } write_unlock(&GlobalSMBSeslock); /* BB Add call to invalidate_inodes(sb) for all superblocks mounted @@ -141,7 +141,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if (tcon->ses->server->tcpStatus == CifsNeedReconnect) { /* on "soft" mounts we wait once */ - if ((tcon->retry == FALSE) || + if (!tcon->retry || (tcon->ses->status == CifsExiting)) { cFYI(1, ("gave up waiting on " "reconnect in smb_init")); @@ -289,7 +289,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if (tcon->ses->server->tcpStatus == CifsNeedReconnect) { /* on "soft" mounts we wait once */ - if ((tcon->retry == FALSE) || + if (!tcon->retry || (tcon->ses->status == CifsExiting)) { cFYI(1, ("gave up waiting on " "reconnect in smb_init")); @@ -1686,7 +1686,7 @@ int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const __u64 len, const __u64 offset, const __u32 numUnlock, - const __u32 numLock, const __u8 lockType, const int waitFlag) + const __u32 numLock, const __u8 lockType, const bool waitFlag) { int rc = 0; LOCK_REQ *pSMB = NULL; @@ -1695,7 +1695,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, int timeout = 0; __u16 count; - cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock)); + cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock)); rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); if (rc) @@ -1706,7 +1706,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { timeout = CIFS_ASYNC_OP; /* no response expected */ pSMB->Timeout = 0; - } else if (waitFlag == TRUE) { + } else if (waitFlag) { timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ } else { @@ -1756,7 +1756,7 @@ int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const int get_flag, const __u64 len, struct file_lock *pLockData, const __u16 lock_type, - const int waitFlag) + const bool waitFlag) { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; @@ -3581,9 +3581,9 @@ findFirstRetry: rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc == 0) { if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - psrch_inf->unicode = TRUE; + psrch_inf->unicode = true; else - psrch_inf->unicode = FALSE; + psrch_inf->unicode = false; psrch_inf->ntwrk_buf_start = (char *)pSMBr; psrch_inf->smallBuf = 0; @@ -3594,9 +3594,9 @@ findFirstRetry: le16_to_cpu(pSMBr->t2.ParameterOffset)); if (parms->EndofSearch) - psrch_inf->endOfSearch = TRUE; + psrch_inf->endOfSearch = true; else - psrch_inf->endOfSearch = FALSE; + psrch_inf->endOfSearch = false; psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); @@ -3624,7 +3624,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, cFYI(1, ("In FindNext")); - if (psrch_inf->endOfSearch == TRUE) + if (psrch_inf->endOfSearch) return -ENOENT; rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -3682,7 +3682,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, cifs_stats_inc(&tcon->num_fnext); if (rc) { if (rc == -EBADF) { - psrch_inf->endOfSearch = TRUE; + psrch_inf->endOfSearch = true; rc = 0; /* search probably was closed at end of search*/ } else cFYI(1, ("FindNext returned = %d", rc)); @@ -3692,9 +3692,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, if (rc == 0) { /* BB fixme add lock for file (srch_info) struct here */ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - psrch_inf->unicode = TRUE; + psrch_inf->unicode = true; else - psrch_inf->unicode = FALSE; + psrch_inf->unicode = false; response_data = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.ParameterOffset); parms = (T2_FNEXT_RSP_PARMS *)response_data; @@ -3709,9 +3709,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, psrch_inf->ntwrk_buf_start = (char *)pSMB; psrch_inf->smallBuf = 0; if (parms->EndofSearch) - psrch_inf->endOfSearch = TRUE; + psrch_inf->endOfSearch = true; else - psrch_inf->endOfSearch = FALSE; + psrch_inf->endOfSearch = false; psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); psrch_inf->index_of_last_entry += @@ -4586,7 +4586,7 @@ QFSPosixRetry: int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, - __u64 size, int SetAllocation, + __u64 size, bool SetAllocation, const struct nls_table *nls_codepage, int remap) { struct smb_com_transaction2_spi_req *pSMB = NULL; @@ -4675,7 +4675,7 @@ SetEOFRetry: int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, - __u16 fid, __u32 pid_of_opener, int SetAllocation) + __u16 fid, __u32 pid_of_opener, bool SetAllocation) { struct smb_com_transaction2_sfi_req *pSMB = NULL; char *data_offset; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e1710673016..6c4332f8da6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -71,23 +71,23 @@ struct smb_vol { mode_t file_mode; mode_t dir_mode; unsigned secFlg; - unsigned rw:1; - unsigned retry:1; - unsigned intr:1; - unsigned setuids:1; - unsigned override_uid:1; - unsigned override_gid:1; - unsigned noperm:1; - unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ - unsigned cifs_acl:1; - unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ - unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ - unsigned direct_io:1; - unsigned remap:1; /* set to remap seven reserved chars in filenames */ - unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ - unsigned no_linux_ext:1; - unsigned sfu_emul:1; - unsigned nullauth:1; /* attempt to authenticate with null user */ + bool rw:1; + bool retry:1; + bool intr:1; + bool setuids:1; + bool override_uid:1; + bool override_gid:1; + bool noperm:1; + bool no_psx_acl:1; /* set if posix acl support should be disabled */ + bool cifs_acl:1; + bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ + bool server_ino:1; /* use inode numbers from server ie UniqueId */ + bool direct_io:1; + bool remap:1; /* set to remap seven reserved chars in filenames */ + bool posix_paths:1; /* unset to not ask for posix pathnames. */ + bool no_linux_ext:1; + bool sfu_emul:1; + bool nullauth:1; /* attempt to authenticate with null user */ unsigned nocase; /* request case insensitive filenames */ unsigned nobrl; /* disable sending byte range locks to srv */ unsigned int rsize; @@ -345,8 +345,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; char temp; - int isLargeBuf = FALSE; - int isMultiRsp; + bool isLargeBuf = false; + bool isMultiRsp; int reconnect; current->flags |= PF_MEMALLOC; @@ -390,8 +390,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } else /* if existing small buf clear beginning */ memset(smallbuf, 0, sizeof(struct smb_hdr)); - isLargeBuf = FALSE; - isMultiRsp = FALSE; + isLargeBuf = false; + isMultiRsp = false; smb_buffer = smallbuf; iov.iov_base = smb_buffer; iov.iov_len = 4; @@ -517,7 +517,7 @@ incomplete_rcv: reconnect = 0; if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { - isLargeBuf = TRUE; + isLargeBuf = true; memcpy(bigbuf, smallbuf, 4); smb_buffer = bigbuf; } @@ -582,16 +582,18 @@ incomplete_rcv: (mid_entry->command == smb_buffer->Command)) { if (check2ndT2(smb_buffer,server->maxBuf) > 0) { /* We have a multipart transact2 resp */ - isMultiRsp = TRUE; + isMultiRsp = true; if (mid_entry->resp_buf) { /* merge response - fix up 1st*/ if (coalesce_t2(smb_buffer, mid_entry->resp_buf)) { - mid_entry->multiRsp = 1; + mid_entry->multiRsp = + true; break; } else { /* all parts received */ - mid_entry->multiEnd = 1; + mid_entry->multiEnd = + true; goto multi_t2_fnd; } } else { @@ -603,17 +605,15 @@ incomplete_rcv: /* Have first buffer */ mid_entry->resp_buf = smb_buffer; - mid_entry->largeBuf = 1; + mid_entry->largeBuf = + true; bigbuf = NULL; } } break; } mid_entry->resp_buf = smb_buffer; - if (isLargeBuf) - mid_entry->largeBuf = 1; - else - mid_entry->largeBuf = 0; + mid_entry->largeBuf = isLargeBuf; multi_t2_fnd: task_to_wake = mid_entry->tsk; mid_entry->midState = MID_RESPONSE_RECEIVED; @@ -638,8 +638,8 @@ multi_t2_fnd: smallbuf = NULL; } wake_up_process(task_to_wake); - } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) - && (isMultiRsp == FALSE)) { + } else if (!is_valid_oplock_break(smb_buffer, server) && + !isMultiRsp) { cERROR(1, ("No task to wake, unknown frame received! " "NumMids %d", midCount.counter)); cifs_dump_mem("Received Data is: ", (char *)smb_buffer, @@ -825,7 +825,7 @@ cifs_parse_mount_options(char *options, const char *devname, vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ - vol->rw = TRUE; + vol->rw = true; /* default is always to request posix paths. */ vol->posix_paths = 1; @@ -1181,7 +1181,7 @@ cifs_parse_mount_options(char *options, const char *devname, } else if (strnicmp(data, "guest", 5) == 0) { /* ignore */ } else if (strnicmp(data, "rw", 2) == 0) { - vol->rw = TRUE; + vol->rw = true; } else if ((strnicmp(data, "suid", 4) == 0) || (strnicmp(data, "nosuid", 6) == 0) || (strnicmp(data, "exec", 4) == 0) || @@ -1197,7 +1197,7 @@ cifs_parse_mount_options(char *options, const char *devname, is ok to just ignore them */ continue; } else if (strnicmp(data, "ro", 2) == 0) { - vol->rw = FALSE; + vol->rw = false; } else if (strnicmp(data, "hard", 4) == 0) { vol->retry = 1; } else if (strnicmp(data, "soft", 4) == 0) { @@ -2602,7 +2602,7 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings, static int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, - struct cifsSesInfo *ses, int *pNTLMv2_flag, + struct cifsSesInfo *ses, bool *pNTLMv2_flag, const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; @@ -2625,7 +2625,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, if (ses == NULL) return -EINVAL; domain = ses->domainName; - *pNTLMv2_flag = FALSE; + *pNTLMv2_flag = false; smb_buffer = cifs_buf_get(); if (smb_buffer == NULL) { return -ENOMEM; @@ -2778,7 +2778,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, CIFS_CRYPTO_KEY_SIZE); if (SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) - *pNTLMv2_flag = TRUE; + *pNTLMv2_flag = true; if ((SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) @@ -2939,7 +2939,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, } static int CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *ntlm_session_key, int ntlmv2_flag, + char *ntlm_session_key, bool ntlmv2_flag, const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; @@ -3569,7 +3569,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, { int rc = 0; char ntlm_session_key[CIFS_SESS_KEY_SIZE]; - int ntlmv2_flag = FALSE; + bool ntlmv2_flag = false; int first_time = 0; /* what if server changes its buffer size after dropping the session? */ diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 0f5c62ba403..6ed775986be 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -130,7 +130,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, struct cifsFileInfo *pCifsFile = NULL; struct cifsInodeInfo *pCifsInode; int disposition = FILE_OVERWRITE_IF; - int write_only = FALSE; + bool write_only = false; xid = GetXid(); @@ -152,7 +152,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, if (oflags & FMODE_WRITE) { desiredAccess |= GENERIC_WRITE; if (!(oflags & FMODE_READ)) - write_only = TRUE; + write_only = true; } if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) @@ -254,7 +254,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, d_instantiate(direntry, newinode); } if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || - ((nd->flags & LOOKUP_OPEN) == FALSE)) { + (!(nd->flags & LOOKUP_OPEN))) { /* mknod case - do not leave file open */ CIFSSMBClose(xid, pTcon, fileHandle); } else if (newinode) { @@ -266,8 +266,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; pCifsFile->pInode = newinode; - pCifsFile->invalidHandle = FALSE; - pCifsFile->closePend = FALSE; + pCifsFile->invalidHandle = false; + pCifsFile->closePend = false; init_MUTEX(&pCifsFile->fh_sem); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); @@ -280,7 +280,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pCifsInode = CIFS_I(newinode); if (pCifsInode) { /* if readable file instance put first in list*/ - if (write_only == TRUE) { + if (write_only) { list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); } else { @@ -288,12 +288,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, &pCifsInode->openFileList); } if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = TRUE; - pCifsInode->clientCanCacheRead = TRUE; + pCifsInode->clientCanCacheAll = true; + pCifsInode->clientCanCacheRead = true; cFYI(1, ("Exclusive Oplock inode %p", newinode)); } else if ((oplock & 0xF) == OPLOCK_READ) - pCifsInode->clientCanCacheRead = TRUE; + pCifsInode->clientCanCacheRead = true; } write_unlock(&GlobalSMBSeslock); } diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index 7d1d5aa4c43..5a57581eb4b 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -68,7 +68,7 @@ int cifs_dir_notify(struct file *file, unsigned long arg) { int xid; int rc = -EINVAL; - int oplock = FALSE; + int oplock = 0; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 40b690073fc..31a0a33b9d9 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -51,8 +51,8 @@ static inline struct cifsFileInfo *cifs_init_private( INIT_LIST_HEAD(&private_data->llist); private_data->pfile = file; /* needed for writepage */ private_data->pInode = inode; - private_data->invalidHandle = FALSE; - private_data->closePend = FALSE; + private_data->invalidHandle = false; + private_data->closePend = false; /* we have to track num writers to the inode, since writepages does not tell us which handle the write is for so there can be a close (overlapping with write) of the filehandle that @@ -148,12 +148,12 @@ client_can_cache: full_path, buf, inode->i_sb, xid, NULL); if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = TRUE; - pCifsInode->clientCanCacheRead = TRUE; + pCifsInode->clientCanCacheAll = true; + pCifsInode->clientCanCacheRead = true; cFYI(1, ("Exclusive Oplock granted on inode %p", file->f_path.dentry->d_inode)); } else if ((*oplock & 0xF) == OPLOCK_READ) - pCifsInode->clientCanCacheRead = TRUE; + pCifsInode->clientCanCacheRead = true; return rc; } @@ -247,7 +247,7 @@ int cifs_open(struct inode *inode, struct file *file) if (oplockEnabled) oplock = REQ_OPLOCK; else - oplock = FALSE; + oplock = 0; /* BB pass O_SYNC flag through on file attributes .. BB */ @@ -339,7 +339,7 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile) return rc; } -static int cifs_reopen_file(struct file *file, int can_flush) +static int cifs_reopen_file(struct file *file, bool can_flush) { int rc = -EACCES; int xid, oplock; @@ -360,7 +360,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) xid = GetXid(); down(&pCifsFile->fh_sem); - if (pCifsFile->invalidHandle == FALSE) { + if (!pCifsFile->invalidHandle) { up(&pCifsFile->fh_sem); FreeXid(xid); return 0; @@ -404,7 +404,7 @@ reopen_error_exit: if (oplockEnabled) oplock = REQ_OPLOCK; else - oplock = FALSE; + oplock = 0; /* Can not refresh inode by passing in file_info buf to be returned by SMBOpen and then calling get_inode_info with returned buf @@ -422,7 +422,7 @@ reopen_error_exit: cFYI(1, ("oplock: %d", oplock)); } else { pCifsFile->netfid = netfid; - pCifsFile->invalidHandle = FALSE; + pCifsFile->invalidHandle = false; up(&pCifsFile->fh_sem); pCifsInode = CIFS_I(inode); if (pCifsInode) { @@ -432,8 +432,8 @@ reopen_error_exit: CIFS_I(inode)->write_behind_rc = rc; /* temporarily disable caching while we go to server to get inode info */ - pCifsInode->clientCanCacheAll = FALSE; - pCifsInode->clientCanCacheRead = FALSE; + pCifsInode->clientCanCacheAll = false; + pCifsInode->clientCanCacheRead = false; if (pTcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, xid); @@ -448,16 +448,16 @@ reopen_error_exit: we can not go to the server to get the new inod info */ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = TRUE; - pCifsInode->clientCanCacheRead = TRUE; + pCifsInode->clientCanCacheAll = true; + pCifsInode->clientCanCacheRead = true; cFYI(1, ("Exclusive Oplock granted on inode %p", file->f_path.dentry->d_inode)); } else if ((oplock & 0xF) == OPLOCK_READ) { - pCifsInode->clientCanCacheRead = TRUE; - pCifsInode->clientCanCacheAll = FALSE; + pCifsInode->clientCanCacheRead = true; + pCifsInode->clientCanCacheAll = false; } else { - pCifsInode->clientCanCacheRead = FALSE; - pCifsInode->clientCanCacheAll = FALSE; + pCifsInode->clientCanCacheRead = false; + pCifsInode->clientCanCacheAll = false; } cifs_relock_file(pCifsFile); } @@ -484,7 +484,7 @@ int cifs_close(struct inode *inode, struct file *file) if (pSMBFile) { struct cifsLockInfo *li, *tmp; - pSMBFile->closePend = TRUE; + pSMBFile->closePend = true; if (pTcon) { /* no sense reconnecting to close a file that is already closed */ @@ -553,8 +553,8 @@ int cifs_close(struct inode *inode, struct file *file) 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 on this inode, much less write behind and read ahead */ - CIFS_I(inode)->clientCanCacheRead = FALSE; - CIFS_I(inode)->clientCanCacheAll = FALSE; + CIFS_I(inode)->clientCanCacheRead = false; + CIFS_I(inode)->clientCanCacheAll = false; } read_unlock(&GlobalSMBSeslock); if ((rc == 0) && CIFS_I(inode)->write_behind_rc) @@ -583,9 +583,9 @@ int cifs_closedir(struct inode *inode, struct file *file) pTcon = cifs_sb->tcon; cFYI(1, ("Freeing private data in close dir")); - if ((pCFileStruct->srch_inf.endOfSearch == FALSE) && - (pCFileStruct->invalidHandle == FALSE)) { - pCFileStruct->invalidHandle = TRUE; + if (!pCFileStruct->srch_inf.endOfSearch && + !pCFileStruct->invalidHandle) { + pCFileStruct->invalidHandle = true; rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); cFYI(1, ("Closing uncompleted readdir with rc %d", rc)); @@ -637,12 +637,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) __u32 numLock = 0; __u32 numUnlock = 0; __u64 length; - int wait_flag = FALSE; + bool wait_flag = false; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; __u16 netfid; __u8 lockType = LOCKING_ANDX_LARGE_FILES; - int posix_locking; + bool posix_locking; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -659,7 +659,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) cFYI(1, ("Flock")); if (pfLock->fl_flags & FL_SLEEP) { cFYI(1, ("Blocking lock")); - wait_flag = TRUE; + wait_flag = true; } if (pfLock->fl_flags & FL_ACCESS) cFYI(1, ("Process suspended by mandatory locking - " @@ -794,7 +794,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) stored_rc = CIFSSMBLock(xid, pTcon, netfid, li->length, li->offset, - 1, 0, li->type, FALSE); + 1, 0, li->type, false); if (stored_rc) rc = stored_rc; @@ -866,7 +866,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, filemap_fdatawait from here so tell reopen_file not to flush data to server now */ - rc = cifs_reopen_file(file, FALSE); + rc = cifs_reopen_file(file, false); if (rc != 0) break; } @@ -966,7 +966,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, filemap_fdatawait from here so tell reopen_file not to flush data to server now */ - rc = cifs_reopen_file(file, FALSE); + rc = cifs_reopen_file(file, false); if (rc != 0) break; } @@ -1093,7 +1093,7 @@ refind_writable: read_unlock(&GlobalSMBSeslock); /* Had to unlock since following call can block */ - rc = cifs_reopen_file(open_file->pfile, FALSE); + rc = cifs_reopen_file(open_file->pfile, false); if (!rc) { if (!open_file->closePend) return open_file; @@ -1608,7 +1608,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, int buf_type = CIFS_NO_BUFFER; if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file, TRUE); + rc = cifs_reopen_file(file, true); if (rc != 0) break; } @@ -1693,7 +1693,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, while (rc == -EAGAIN) { if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file, TRUE); + rc = cifs_reopen_file(file, true); if (rc != 0) break; } @@ -1850,7 +1850,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, while (rc == -EAGAIN) { if ((open_file->invalidHandle) && (!open_file->closePend)) { - rc = cifs_reopen_file(file, TRUE); + rc = cifs_reopen_file(file, true); if (rc != 0) break; } @@ -2009,10 +2009,10 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode) refreshing the inode only on increases in the file size but this is tricky to do without racing with writebehind page caching in the current Linux kernel design */ -int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) +bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) { if (!cifsInode) - return 1; + return true; if (is_inode_writable(cifsInode)) { /* This inode is open for write at least once */ @@ -2022,15 +2022,15 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { /* since no page cache to corrupt on directio we can change size safely */ - return 1; + return true; } if (i_size_read(&cifsInode->vfs_inode) < end_of_file) - return 1; + return true; - return 0; + return false; } else - return 1; + return true; } static int cifs_prepare_write(struct file *file, struct page *page, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e1031b9e2c5..8eaa9e72fe8 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -281,7 +281,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, struct cifs_sb_info *cifs_sb, int xid) { int rc; - int oplock = FALSE; + int oplock = 0; __u16 netfid; struct cifsTconInfo *pTcon = cifs_sb->tcon; char buf[24]; @@ -389,7 +389,7 @@ int cifs_get_inode_info(struct inode **pinode, struct cifs_sb_info *cifs_sb = CIFS_SB(sb); const unsigned char *full_path = NULL; char *buf = NULL; - int adjustTZ = FALSE; + bool adjustTZ = bool; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; @@ -425,7 +425,7 @@ try_again_CIFSSMBQPathInfo: pfindData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - adjustTZ = TRUE; + adjustTZ = true; } } /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ @@ -703,7 +703,7 @@ psx_del_no_retry: } else if (rc == -ENOENT) { d_drop(direntry); } else if (rc == -ETXTBSY) { - int oplock = FALSE; + int oplock = 0; __u16 netfid; rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, @@ -736,7 +736,7 @@ psx_del_no_retry: rc = -EOPNOTSUPP; if (rc == -EOPNOTSUPP) { - int oplock = FALSE; + int oplock = 0; __u16 netfid; /* rc = CIFSSMBSetAttrLegacy(xid, pTcon, full_path, @@ -774,7 +774,7 @@ psx_del_no_retry: if (direntry->d_inode) drop_nlink(direntry->d_inode); } else if (rc == -ETXTBSY) { - int oplock = FALSE; + int oplock = 0; __u16 netfid; rc = CIFSSMBOpen(xid, pTcon, full_path, @@ -1149,7 +1149,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, cFYI(1, ("rename rc %d", rc)); if ((rc == -EIO) || (rc == -EEXIST)) { - int oplock = FALSE; + int oplock = 0; __u16 netfid; /* BB FIXME Is Generic Read correct for rename? */ @@ -1186,7 +1186,7 @@ int cifs_revalidate(struct dentry *direntry) struct cifsInodeInfo *cifsInode; loff_t local_size; struct timespec local_mtime; - int invalidate_inode = FALSE; + bool invalidate_inode = false; if (direntry->d_inode == NULL) return -ENOENT; @@ -1268,7 +1268,7 @@ int cifs_revalidate(struct dentry *direntry) only ones who could have modified the file and the server copy is staler than ours */ } else { - invalidate_inode = TRUE; + invalidate_inode = true; } } @@ -1402,8 +1402,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) int rc = -EACCES; struct cifsFileInfo *open_file = NULL; FILE_BASIC_INFO time_buf; - int set_time = FALSE; - int set_dosattr = FALSE; + bool set_time = false; + bool set_dosattr = false; __u64 mode = 0xFFFFFFFFFFFFFFFFULL; __u64 uid = 0xFFFFFFFFFFFFFFFFULL; __u64 gid = 0xFFFFFFFFFFFFFFFFULL; @@ -1464,7 +1464,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) __u16 nfid = open_file->netfid; __u32 npid = open_file->pid; rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, - nfid, npid, FALSE); + nfid, npid, false); atomic_dec(&open_file->wrtPending); cFYI(1, ("SetFSize for attrs rc = %d", rc)); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { @@ -1484,14 +1484,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) it was found or because there was an error setting it by handle */ rc = CIFSSMBSetEOF(xid, pTcon, full_path, - attrs->ia_size, FALSE, + attrs->ia_size, false, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { __u16 netfid; - int oplock = FALSE; + int oplock = 0; rc = SMBLegacyOpen(xid, pTcon, full_path, FILE_OPEN, @@ -1516,7 +1516,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) /* Server is ok setting allocation size implicitly - no need to call: - CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, + CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, true, cifs_sb->local_nls); */ @@ -1564,7 +1564,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) #endif /* not writeable */ if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { - set_dosattr = TRUE; + set_dosattr = true; time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY); @@ -1574,7 +1574,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) not be able to write to it - so if any write bit is enabled for user or group or other we need to at least try to remove r/o dos attr */ - set_dosattr = TRUE; + set_dosattr = true; time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY)); /* Windows ignores set to zero */ @@ -1588,14 +1588,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) } if (attrs->ia_valid & ATTR_ATIME) { - set_time = TRUE; + set_time = true; time_buf.LastAccessTime = cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); } else time_buf.LastAccessTime = 0; if (attrs->ia_valid & ATTR_MTIME) { - set_time = TRUE; + set_time = true; time_buf.LastWriteTime = cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); } else @@ -1606,7 +1606,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) server times */ if (set_time && (attrs->ia_valid & ATTR_CTIME)) { - set_time = TRUE; + set_time = true; /* Although Samba throws this field away it may be useful to Windows - but we do not want to set ctime unless some other @@ -1630,7 +1630,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) rc = -EOPNOTSUPP; if (rc == -EOPNOTSUPP) { - int oplock = FALSE; + int oplock = 0; __u16 netfid; cFYI(1, ("calling SetFileInfo since SetPathInfo for " diff --git a/fs/cifs/link.c b/fs/cifs/link.c index d4e7ec93285..1c2c3ce5020 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -230,7 +230,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) struct inode *inode = direntry->d_inode; int rc = -EACCES; int xid; - int oplock = FALSE; + int oplock = 0; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 2a42d9fedbb..1d69b8014e0 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -496,7 +496,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) } return 0; } -int + +bool is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) { struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; @@ -522,17 +523,17 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) pnotify->Action)); /* BB removeme BB */ /* cifs_dump_mem("Rcvd notify Data: ",buf, sizeof(struct smb_hdr)+60); */ - return TRUE; + return true; } if (pSMBr->hdr.Status.CifsError) { cFYI(1, ("notify err 0x%d", pSMBr->hdr.Status.CifsError)); - return TRUE; + return true; } - return FALSE; + return false; } if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) - return FALSE; + return false; if (pSMB->hdr.Flags & SMBFLG_RESPONSE) { /* no sense logging error on invalid handle on oplock break - harmless race between close request and oplock @@ -541,21 +542,21 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) if ((NT_STATUS_INVALID_HANDLE) == le32_to_cpu(pSMB->hdr.Status.CifsError)) { cFYI(1, ("invalid handle on oplock break")); - return TRUE; + return true; } else if (ERRbadfid == le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { - return TRUE; + return true; } else { - return FALSE; /* on valid oplock brk we get "request" */ + return false; /* on valid oplock brk we get "request" */ } } if (pSMB->hdr.WordCount != 8) - return FALSE; + return false; cFYI(1, ("oplock type 0x%d level 0x%d", pSMB->LockType, pSMB->OplockLevel)); if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) - return FALSE; + return false; /* look up tcon based on tid & uid */ read_lock(&GlobalSMBSeslock); @@ -573,11 +574,11 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) ("file id match, oplock break")); pCifsInode = CIFS_I(netfile->pInode); - pCifsInode->clientCanCacheAll = FALSE; + pCifsInode->clientCanCacheAll = false; if (pSMB->OplockLevel == 0) pCifsInode->clientCanCacheRead - = FALSE; - pCifsInode->oplockPending = TRUE; + = false; + pCifsInode->oplockPending = true; AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); @@ -585,17 +586,17 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) ("about to wake up oplock thread")); if (oplockThread) wake_up_process(oplockThread); - return TRUE; + return true; } } read_unlock(&GlobalSMBSeslock); cFYI(1, ("No matching file for oplock break")); - return TRUE; + return true; } } read_unlock(&GlobalSMBSeslock); cFYI(1, ("Can not process oplock break for non-existent connection")); - return TRUE; + return true; } void diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 32b445edc88..34ec32100c7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -447,8 +447,8 @@ static int initiate_cifs_search(const int xid, struct file *file) if (file->private_data == NULL) return -ENOMEM; cifsFile = file->private_data; - cifsFile->invalidHandle = TRUE; - cifsFile->srch_inf.endOfSearch = FALSE; + cifsFile->invalidHandle = true; + cifsFile->srch_inf.endOfSearch = false; cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); if (cifs_sb == NULL) @@ -485,7 +485,7 @@ ffirst_retry: cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); if (rc == 0) - cifsFile->invalidHandle = FALSE; + cifsFile->invalidHandle = false; if ((rc == -EOPNOTSUPP) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; @@ -670,7 +670,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, (index_to_find < first_entry_in_buffer)) { /* close and restart search */ cFYI(1, ("search backing up - close and restart search")); - cifsFile->invalidHandle = TRUE; + cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); kfree(cifsFile->search_resume_name); cifsFile->search_resume_name = NULL; @@ -692,7 +692,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, } while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && - (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)) { + (rc == 0) && !cifsFile->srch_inf.endOfSearch) { cFYI(1, ("calling findnext2")); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); @@ -1038,7 +1038,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) break; } } /* else { - cifsFile->invalidHandle = TRUE; + cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); } kfree(cifsFile->search_resume_name); diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 58bbfd992cc..ff3232fa101 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -35,11 +35,11 @@ #include "cifs_debug.h" #include "cifsencrypt.h" -#ifndef FALSE -#define FALSE 0 +#ifndef false +#define false 0 #endif -#ifndef TRUE -#define TRUE 1 +#ifndef true +#define true 1 #endif /* following came from the other byteorder.h to avoid include conflicts */ diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 8cd6a445b01..e9527eedc63 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -264,7 +264,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, #ifdef CONFIG_CIFS_EXPERIMENTAL else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { __u16 fid; - int oplock = FALSE; + int oplock = 0; struct cifs_ntsd *pacl = NULL; __u32 buflen = 0; if (experimEnabled) -- cgit v1.2.3-70-g09d2 From 9b1ec9eceabe0c90d12116871f692263b69d476d Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Apr 2008 20:15:43 +0000 Subject: [CIFS] Remove duplicate call to mode_to_acl The current logic in cifs_setattr calls mode_to_acl twice on mode changes if cifsacl is enabled. Remove the duplicate call. Signed-off-by: Jeff Layton CC: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/inode.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8eaa9e72fe8..a1f24bdb656 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1581,10 +1581,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) if (time_buf.Attributes == 0) time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); } -#ifdef CONFIG_CIFS_EXPERIMENTAL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) - mode_to_acl(direntry->d_inode, full_path, mode); -#endif } if (attrs->ia_valid & ATTR_ATIME) { -- cgit v1.2.3-70-g09d2 From 5ade9deaaa3e1f7291467d97b238648e43eae15e Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 2 May 2008 20:56:23 +0000 Subject: [CIFS] fix typo Signed-off-by: Steve French --- fs/cifs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a1f24bdb656..0d9d2e6d7af 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -389,7 +389,7 @@ int cifs_get_inode_info(struct inode **pinode, struct cifs_sb_info *cifs_sb = CIFS_SB(sb); const unsigned char *full_path = NULL; char *buf = NULL; - bool adjustTZ = bool; + bool adjustTZ = false; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; -- cgit v1.2.3-70-g09d2 From dea570e08a69b14808b2cab56d6b0dda72145fa6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 6 May 2008 22:05:51 +0000 Subject: [CIFS] Remove over-indented code in find_unc(). Signed-off-by: Cyrill Gorcunov Signed-off-by: Steve French --- fs/cifs/connect.c | 64 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6c4332f8da6..f2259db075c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1362,45 +1362,43 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) { struct list_head *tmp; struct cifsTconInfo *tcon; + __be32 old_ip; read_lock(&GlobalSMBSeslock); + list_for_each(tmp, &GlobalTreeConnectionList) { cFYI(1, ("Next tcon")); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); - if (tcon->ses) { - if (tcon->ses->server) { - cFYI(1, - ("old ip addr: %x == new ip %x ?", - tcon->ses->server->addr.sockAddr.sin_addr. - s_addr, new_target_ip_addr)); - if (tcon->ses->server->addr.sockAddr.sin_addr. - s_addr == new_target_ip_addr) { - /* BB lock tcon, server and tcp session and increment use count here? */ - /* found a match on the TCP session */ - /* BB check if reconnection needed */ - cFYI(1, - ("IP match, old UNC: %s new: %s", - tcon->treeName, uncName)); - if (strncmp - (tcon->treeName, uncName, - MAX_TREE_SIZE) == 0) { - cFYI(1, - ("and old usr: %s new: %s", - tcon->treeName, uncName)); - if (strncmp - (tcon->ses->userName, - userName, - MAX_USERNAME_SIZE) == 0) { - read_unlock(&GlobalSMBSeslock); - /* matched smb session - (user name */ - return tcon; - } - } - } - } - } + if (!tcon->ses || !tcon->ses->server) + continue; + + old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr; + cFYI(1, ("old ip addr: %x == new ip %x ?", + old_ip, new_target_ip_addr)); + + if (old_ip != new_target_ip_addr) + continue; + + /* BB lock tcon, server, tcp session and increment use count? */ + /* found a match on the TCP session */ + /* BB check if reconnection needed */ + cFYI(1, ("IP match, old UNC: %s new: %s", + tcon->treeName, uncName)); + + if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE)) + continue; + + cFYI(1, ("and old usr: %s new: %s", + tcon->treeName, uncName)); + + if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE)) + continue; + + /* matched smb session (user name) */ + read_unlock(&GlobalSMBSeslock); + return tcon; } + read_unlock(&GlobalSMBSeslock); return NULL; } -- cgit v1.2.3-70-g09d2 From cf432eb50ffd03572c08a006f44e0069957cf300 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 6 May 2008 22:27:16 +0000 Subject: [CIFS] cleanup cifsd completion Was a holdover from the old kernel_thread based cifsd code. We needed to know that the thread had set the task variable before proceeding. Now that kthread_run returns the new task, this doesn't appear to be needed anymore. As best I can tell, this sleep was intended to try to prevent cifs_umount from freeing the cifsSesInfo struct before cifsd had exited. Now that cifsd is using the kthread API, we know that when kthread_stop returns that cifsd has exited, so I don't think this is needed any longer. Signed-off-by: Jeff Layton Acked-by: Christop Hellwig Signed-off-by: Steve French --- fs/cifs/connect.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f2259db075c..957998e8477 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -49,8 +49,6 @@ #define CIFS_PORT 445 #define RFC1001_PORT 139 -static DECLARE_COMPLETION(cifsd_complete); - extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); @@ -356,7 +354,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) atomic_inc(&tcpSesAllocCount); length = tcpSesAllocCount.counter; write_unlock(&GlobalSMBSeslock); - complete(&cifsd_complete); if (length > 1) mempool_resize(cifs_req_poolp, length + cifs_min_rcv, GFP_KERNEL); @@ -1980,7 +1977,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, kfree(srvTcp->hostname); goto out; } - wait_for_completion(&cifsd_complete); rc = 0; memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name, 16); @@ -3553,8 +3549,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) cifs_sb->prepathlen = 0; cifs_sb->prepath = NULL; kfree(tmp); - if (ses) - schedule_timeout_interruptible(msecs_to_jiffies(500)); if (ses) sesInfoFree(ses); -- cgit v1.2.3-70-g09d2 From 7c5e628f95b440b69332b1ed3eb112648fc8f7ff Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 8 May 2008 20:48:42 +0000 Subject: [CIFS] Fixed build warning in is_ip Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 2 +- fs/cifs/connect.c | 3 +++ fs/cifs/netmisc.c | 32 +------------------------------- 3 files changed, 5 insertions(+), 32 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a249a29109a..d481f6c5a2b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -70,7 +70,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, enum securityEnum *secType); -extern int cifs_inet_pton(int, char *source, void *dst); +extern int cifs_inet_pton(const int, const char *source, void *dst); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 957998e8477..791ca5c1a11 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1302,6 +1302,9 @@ cifs_parse_mount_options(char *options, const char *devname, "begin with // or \\\\ \n"); return 1; } + value = strpbrk(vol->UNC+2, "/\\"); + if (value) + *value = '\\'; } else { printk(KERN_WARNING "CIFS: UNC name too long\n"); return 1; diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 3b5a5ce882b..00f4cff400b 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -132,47 +132,17 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { {0, 0} }; - -/* if the mount helper is missing we need to reverse the 1st slash - from '/' to backslash in order to format the UNC properly for - ip address parsing and for tree connect (unless the user - remembered to put the UNC name in properly). Fortunately we do - not have to call this twice (we check for IPv4 addresses - first, so it is already converted by the time we - try IPv6 addresses */ -static int canonicalize_unc(char *cp) -{ - int i; - - for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) { - if (cp[i] == 0) - break; - if (cp[i] == '\\') - break; - if (cp[i] == '/') { - cFYI(DBG2, ("change slash to \\ in malformed UNC")); - cp[i] = '\\'; - return 1; - } - } - return 0; -} - /* Convert string containing dotted ip address to binary form */ /* returns 0 if invalid address */ int -cifs_inet_pton(int address_family, char *cp, void *dst) +cifs_inet_pton(const int address_family, const char *cp, void *dst) { int ret = 0; /* calculate length by finding first slash or NULL */ if (address_family == AF_INET) { ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); - if (ret == 0) { - if (canonicalize_unc(cp)) - ret = in4_pton(cp, -1, dst, '\\', NULL); - } } else if (address_family == AF_INET6) { ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); } -- cgit v1.2.3-70-g09d2 From af4b3c355cbd38703471e55d11f42d8640db4118 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 9 May 2008 03:48:05 +0000 Subject: [CIFS] fix build warning Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 6fe1bc5bb36..34902cff540 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -589,7 +589,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, unlock_file = true; fid = open_file->netfid; } else if (pfid == NULL) { - bool oplock = false; + int oplock = 0; /* open file */ rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0, &fid, &oplock, NULL, -- cgit v1.2.3-70-g09d2 From 1b20d672188bf80baef60d515a123f556871a5ce Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 9 May 2008 18:17:21 +0000 Subject: [CIFS] cifs_find_tcp_session cleanup This patch cleans up cifs_find_tcp_session so it become less indented. Also the error of skipping IPv6 matched addresses fixed. Signed-off-by: Cyrill Gorcunov Signed-off-by: Steve French --- fs/cifs/connect.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 791ca5c1a11..6b520aad7af 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1318,42 +1318,43 @@ cifs_parse_mount_options(char *options, const char *devname, static struct cifsSesInfo * cifs_find_tcp_session(struct in_addr *target_ip_addr, - struct in6_addr *target_ip6_addr, - char *userName, struct TCP_Server_Info **psrvTcp) + struct in6_addr *target_ip6_addr, + char *userName, struct TCP_Server_Info **psrvTcp) { struct list_head *tmp; struct cifsSesInfo *ses; + *psrvTcp = NULL; - read_lock(&GlobalSMBSeslock); + read_lock(&GlobalSMBSeslock); list_for_each(tmp, &GlobalSMBSessionList) { ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); - if (ses->server) { - if ((target_ip_addr && - (ses->server->addr.sockAddr.sin_addr.s_addr - == target_ip_addr->s_addr)) || (target_ip6_addr - && memcmp(&ses->server->addr.sockAddr6.sin6_addr, - target_ip6_addr, sizeof(*target_ip6_addr)))) { - /* BB lock server and tcp session and increment - use count here?? */ - - /* found a match on the TCP session */ - *psrvTcp = ses->server; - - /* BB check if reconnection needed */ - if (strncmp - (ses->userName, userName, - MAX_USERNAME_SIZE) == 0){ - read_unlock(&GlobalSMBSeslock); - /* Found exact match on both TCP and - SMB sessions */ - return ses; - } - } + if (!ses->server) + continue; + + if (target_ip_addr && + ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) + continue; + else if (target_ip6_addr && + memcmp(&ses->server->addr.sockAddr6.sin6_addr, + target_ip6_addr, sizeof(*target_ip6_addr))) + continue; + /* BB lock server and tcp session and increment use count here?? */ + + /* found a match on the TCP session */ + *psrvTcp = ses->server; + + /* BB check if reconnection needed */ + if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { + read_unlock(&GlobalSMBSeslock); + /* Found exact match on both TCP and + SMB sessions */ + return ses; } /* else tcp and smb sessions need reconnection */ } read_unlock(&GlobalSMBSeslock); + return NULL; } -- cgit v1.2.3-70-g09d2 From 02eadeffda169a45946c79270ec19f45eeafb8e7 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 9 May 2008 21:26:11 +0000 Subject: [CIFS] add local struct inode pointer to cifs_setattr Clean up cifs_setattr a bit by adding a local inode pointer, and changing all of the direntry->d_inode references to it. This also adds a bit of micro-optimization. d_inode shouldn't change over the life of this function, so we only need to dereference it once. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- fs/cifs/inode.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6b520aad7af..96505086759 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1339,7 +1339,7 @@ cifs_find_tcp_session(struct in_addr *target_ip_addr, memcmp(&ses->server->addr.sockAddr6.sin6_addr, target_ip6_addr, sizeof(*target_ip6_addr))) continue; - /* BB lock server and tcp session and increment use count here?? */ + /* BB lock server and tcp session; increment use count here?? */ /* found a match on the TCP session */ *psrvTcp = ses->server; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 0d9d2e6d7af..d904a037c83 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1408,18 +1408,19 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) __u64 uid = 0xFFFFFFFFFFFFFFFFULL; __u64 gid = 0xFFFFFFFFFFFFFFFFULL; struct cifsInodeInfo *cifsInode; + struct inode *inode = direntry->d_inode; xid = GetXid(); cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", direntry->d_name.name, attrs->ia_valid)); - cifs_sb = CIFS_SB(direntry->d_inode->i_sb); + cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { /* check if we have permission to change attrs */ - rc = inode_change_ok(direntry->d_inode, attrs); + rc = inode_change_ok(inode, attrs); if (rc < 0) { FreeXid(xid); return rc; @@ -1432,7 +1433,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) FreeXid(xid); return -ENOMEM; } - cifsInode = CIFS_I(direntry->d_inode); + cifsInode = CIFS_I(inode); if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { /* @@ -1443,9 +1444,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) will be truncated anyway? Also, should we error out here if the flush returns error? */ - rc = filemap_write_and_wait(direntry->d_inode->i_mapping); + rc = filemap_write_and_wait(inode->i_mapping); if (rc != 0) { - CIFS_I(direntry->d_inode)->write_behind_rc = rc; + cifsInode->write_behind_rc = rc; rc = 0; } } @@ -1521,9 +1522,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) */ if (rc == 0) { - rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size); - cifs_truncate_page(direntry->d_inode->i_mapping, - direntry->d_inode->i_size); + rc = cifs_vmtruncate(inode, attrs->ia_size); + cifs_truncate_page(inode->i_mapping, inode->i_size); } else goto cifs_setattr_exit; } @@ -1557,7 +1557,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) rc = 0; #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) - rc = mode_to_acl(direntry->d_inode, full_path, mode); + rc = mode_to_acl(inode, full_path, mode); else if ((mode & S_IWUGO) == 0) { #else if ((mode & S_IWUGO) == 0) { @@ -1665,7 +1665,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) /* do not need local check to inode_check_ok since the server does that */ if (!rc) - rc = inode_setattr(direntry->d_inode, attrs); + rc = inode_setattr(inode, attrs); cifs_setattr_exit: kfree(full_path); FreeXid(xid); -- cgit v1.2.3-70-g09d2 From 67750fb9e07940c078d1edb16fd736ccc92a4a4e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 9 May 2008 22:28:02 +0000 Subject: [CIFS] when not using unix extensions, check for and set ATTR_READONLY on create and mkdir When creating a directory on a CIFS share without POSIX extensions, and the given mode has no write bits set, set the ATTR_READONLY bit. When creating a file, set ATTR_READONLY if the create mode has no write bits set and we're not using unix extensions. There are some comments about this being problematic due to the VFS splitting creates into 2 parts. I'm not sure what that's actually talking about, but I'm assuming that it has something to do with how mknod is implemented. In the simple case where we have no unix extensions and we're just creating a regular file, there's no reason we can't set ATTR_READONLY. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 1 + fs/cifs/cifssmb.c | 16 ++++++---------- fs/cifs/dir.c | 16 +++++++++++++--- fs/cifs/inode.c | 15 +++++++++++---- 4 files changed, 31 insertions(+), 17 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a0d26b540d4..c43bf4b7a55 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -340,6 +340,7 @@ #define OPEN_NO_RECALL 0x00400000 #define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */ #define CREATE_OPTIONS_MASK 0x007FFFFF +#define CREATE_OPTION_READONLY 0x10000000 #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */ /* ImpersonationLevel flags */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index cfd9750852b..95fbba4ea7d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1224,11 +1224,8 @@ OldOpenRetry: else /* BB FIXME BB */ pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); - /* if ((omode & S_IWUGO) == 0) - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ - /* Above line causes problems due to vfs splitting create into two - pieces - need to set mode after file created not while it is - being created */ + if (create_options & CREATE_OPTION_READONLY) + pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY); /* BB FIXME BB */ /* pSMB->CreateOptions = cpu_to_le32(create_options & @@ -1331,17 +1328,16 @@ openRetry: pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); else pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); + /* XP does not handle ATTR_POSIX_SEMANTICS */ /* but it helps speed up case sensitive checks for other servers such as Samba */ if (tcon->ses->capabilities & CAP_UNIX) pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); - /* if ((omode & S_IWUGO) == 0) - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ - /* Above line causes problems due to vfs splitting create into two - pieces - need to set mode after file created not while it is - being created */ + if (create_options & CREATE_OPTION_READONLY) + pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); + pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); pSMB->CreateDisposition = cpu_to_le32(openDisposition); pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 6ed775986be..e4e0078a052 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -119,6 +119,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, { int rc = -ENOENT; int xid; + int create_options = CREATE_NOT_DIR; int oplock = 0; int desiredAccess = GENERIC_READ | GENERIC_WRITE; __u16 fileHandle; @@ -176,9 +177,19 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, FreeXid(xid); return -ENOMEM; } + + mode &= ~current->fs->umask; + + /* + * if we're not using unix extensions, see if we need to set + * ATTR_READONLY on the create call + */ + if (!pTcon->unix_ext && (mode & S_IWUGO) == 0) + create_options |= CREATE_OPTION_READONLY; + if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, - desiredAccess, CREATE_NOT_DIR, + desiredAccess, create_options, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); else @@ -187,7 +198,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, if (rc == -EIO) { /* old server, retry the open legacy style */ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, - desiredAccess, CREATE_NOT_DIR, + desiredAccess, create_options, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } @@ -197,7 +208,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, /* If Open reported that we actually created a file then we now have to set the mode if possible */ if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { - mode &= ~current->fs->umask; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)current->fsuid, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d904a037c83..fcbdbb6ad7b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -974,8 +974,8 @@ mkdir_get_info: * failed to get it from the server or was set bogus */ if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) direntry->d_inode->i_nlink = 2; + mode &= ~current->fs->umask; if (pTcon->unix_ext) { - mode &= ~current->fs->umask; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, @@ -994,9 +994,16 @@ mkdir_get_info: CIFS_MOUNT_MAP_SPECIAL_CHR); } } else { - /* BB to be implemented via Windows secrty descriptors - eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, - -1, -1, local_nls); */ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && + (mode & S_IWUGO) == 0) { + FILE_BASIC_INFO pInfo; + memset(&pInfo, 0, sizeof(pInfo)); + pInfo.Attributes = cpu_to_le32(ATTR_READONLY); + CIFSSMBSetTimes(xid, pTcon, full_path, + &pInfo, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } if (direntry->d_inode) { direntry->d_inode->i_mode = mode; direntry->d_inode->i_mode |= S_IFDIR; -- cgit v1.2.3-70-g09d2 From e691b9d1a096fbaaff9d6d6aef1adc593b786e62 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 11 May 2008 15:53:33 +0000 Subject: [CIFS] don't allow demultiplex thread to exit until kthread_stop is called cifs_demultiplex_thread can exit under several conditions: 1) if it's signaled 2) if there's a problem with session setup 3) if kthread_stop is called on it The first two are problems. If kthread_stop is called on the thread, there is no guarantee that it will still be up. We need to have the thread stay up until kthread_stop is called on it. One option would be to not even try to tear things down until after kthread_stop is called. However, in the case where there is a problem setting up the session, there's no real reason to try continuing the loop. This patch allows the thread to clean up and prepare for exit under all three conditions, but it has the thread go to sleep until kthread_stop is called. This allows us to simplify the shutdown code somewhat since we can be reasonably sure that the thread won't exit after being signaled but before kthread_stop is called. It also removes the places where the thread itself set the tsk variable since it appeared that it could have a potential race where the thread might never be shut down. Signed-off-by: Jeff Layton Acked-by: Christoph Hellwig Signed-off-by: Steve French --- fs/cifs/connect.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 96505086759..f428bf3bf1a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) int reconnect; current->flags |= PF_MEMALLOC; - server->tsk = current; /* save process info to wake at shutdown */ cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); write_lock(&GlobalSMBSeslock); atomic_inc(&tcpSesAllocCount); @@ -651,10 +650,20 @@ multi_t2_fnd: spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; - server->tsk = NULL; + spin_unlock(&GlobalMid_Lock); + + /* don't exit until kthread_stop is called */ + set_current_state(TASK_UNINTERRUPTIBLE); + while (!kthread_should_stop()) { + schedule(); + set_current_state(TASK_UNINTERRUPTIBLE); + } + set_current_state(TASK_RUNNING); + /* check if we have blocked requests that need to free */ /* Note that cifs_max_pending is normally 50, but can be set at module install time to as little as two */ + spin_lock(&GlobalMid_Lock); if (atomic_read(&server->inFlight) >= cifs_max_pending) atomic_set(&server->inFlight, cifs_max_pending - 1); /* We do not want to set the max_pending too low or we @@ -2187,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, srvTcp->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); if (srvTcp->tsk) { - struct task_struct *tsk; /* If we could verify that kthread_stop would always wake up processes blocked in tcp in recv_mesg then we could remove the send_sig call */ force_sig(SIGKILL, srvTcp->tsk); - tsk = srvTcp->tsk; - if (tsk) - kthread_stop(tsk); + kthread_stop(srvTcp->tsk); } } /* If find_unc succeeded then rc == 0 so we can not end */ @@ -2211,23 +2217,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if ((temp_rc == -ESHUTDOWN) && (pSesInfo->server) && (pSesInfo->server->tsk)) { - struct task_struct *tsk; force_sig(SIGKILL, pSesInfo->server->tsk); - tsk = pSesInfo->server->tsk; - if (tsk) - kthread_stop(tsk); + kthread_stop(pSesInfo->server->tsk); } } else { cFYI(1, ("No session or bad tcon")); if ((pSesInfo->server) && (pSesInfo->server->tsk)) { - struct task_struct *tsk; force_sig(SIGKILL, pSesInfo->server->tsk); - tsk = pSesInfo->server->tsk; - if (tsk) - kthread_stop(tsk); + kthread_stop(pSesInfo->server->tsk); } } sesInfoFree(pSesInfo); -- cgit v1.2.3-70-g09d2 From d0a9c078db4769f7305ff9774558776d12bfb25b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 May 2008 22:23:49 +0000 Subject: [CIFS] CIFS currently allows for permissions to be changed on files, even when unix extensions and cifsacl support are disabled. These permissions changes are "ephemeral" however. They are lost whenever a share is mounted and unmounted, or when memory pressure forces the inode out of the cache. Because of this, we'd like to introduce a behavior change to make CIFS behave more like local DOS/Windows filesystems. When unix extensions and cifsacl support aren't enabled, then don't silently ignore changes to permission bits that can't be reflected on the server. Still, there may be people relying on the current behavior for certain applications. This patch adds a new "dynperm" (and a corresponding "nodynperm") mount option that will be intended to make the client fall back to legacy behavior when setting these modes. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifs_fs_sb.h | 1 + fs/cifs/connect.c | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 8ad2330ba06..877c85409f1 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -30,6 +30,7 @@ #define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ #define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ +#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f428bf3bf1a..8e2fa6d46c7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -75,6 +75,7 @@ struct smb_vol { bool setuids:1; bool override_uid:1; bool override_gid:1; + bool dynperm:1; bool noperm:1; bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool cifs_acl:1; @@ -1246,6 +1247,10 @@ cifs_parse_mount_options(char *options, const char *devname, vol->setuids = 1; } else if (strnicmp(data, "nosetuids", 9) == 0) { vol->setuids = 0; + } else if (strnicmp(data, "dynperm", 7) == 0) { + vol->dynperm = true; + } else if (strnicmp(data, "nodynperm", 9) == 0) { + vol->dynperm = false; } else if (strnicmp(data, "nohard", 6) == 0) { vol->retry = 0; } else if (strnicmp(data, "nosoft", 6) == 0) { @@ -2125,6 +2130,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; if (volume_info.override_gid) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; + if (volume_info.dynperm) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; if (volume_info.direct_io) { cFYI(1, ("mounting share using direct i/o")); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; -- cgit v1.2.3-70-g09d2 From 6353450a2deefaa79cdb4fd2b72830c7db610256 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 May 2008 19:56:05 -0700 Subject: fix memory leak in CIFSFindNext When CIFSFindNext gets back an -EBADF from a call, it sets the return code of the function to 0 and eventually exits. Doing this makes the cleanup at the end of the function skip freeing the SMB buffer, so we need to make sure we free the buffer explicitly when doing this. If we don't you end up with errors like this when unplugging the cifs kernel module: slab error in kmem_cache_destroy(): cache `cifs_request': Can't free all objects [] kmem_cache_destroy+0x61/0xf3 [] cifs_destroy_request_bufs+0x14/0x28 [cifs] [] exit_cifs+0x1e/0x80 [cifs] [] sys_delete_module+0x192/0x1b8 [] audit_syscall_entry+0x14b/0x17d [] syscall_call+0x7/0xb ======================= Signed-off-by: Jeff Layton --- fs/cifs/CHANGES | 3 ++- fs/cifs/cifssmb.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 8355e918fdd..502a4c2b841 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -12,7 +12,8 @@ Add ability to modify cifs acls for handling chmod (when mounted with cifsacl flag). Fix prefixpath path separator so we can handle mounts with prefixpaths longer than one directory (one path component) when mounted to Windows servers. Fix slow file open when cifsacl -enabled. +enabled. Fix memory leak in FindNext when the SMB call returns -EBADF. + Version 1.51 ------------ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 95fbba4ea7d..641cc8ffc51 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3679,6 +3679,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, if (rc) { if (rc == -EBADF) { psrch_inf->endOfSearch = true; + cifs_buf_release(pSMB); rc = 0; /* search probably was closed at end of search*/ } else cFYI(1, ("FindNext returned = %d", rc)); -- cgit v1.2.3-70-g09d2 From ed5f037005d728de19a0f63678ac35b42064966d Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 13 May 2008 04:01:01 +0000 Subject: [CIFS] CIFSSMBPosixLock should return -EINVAL on error all other codepaths in this function return negative values on errors Signed-off-by: Marcin Slusarz Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 641cc8ffc51..1cbe61524ef 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1767,7 +1767,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, cFYI(1, ("Posix Lock")); if (pLockData == NULL) - return EINVAL; + return -EINVAL; rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); -- cgit v1.2.3-70-g09d2 From 582d21e5e319d38c0485d8b9e92f6f2341f7c79b Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 13 May 2008 04:54:12 +0000 Subject: [CIFS] cleanup old checkpatch warnings Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 6 +++--- fs/cifs/cifssmb.c | 51 +++++++++++++++++++++++++++++++++------------------ fs/cifs/connect.c | 7 ++++--- fs/cifs/netmisc.c | 6 +++--- fs/cifs/ntlmssp.h | 4 ++-- 5 files changed, 45 insertions(+), 29 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d481f6c5a2b..08248e85b78 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -93,7 +93,7 @@ extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); extern int cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, - FILE_ALL_INFO * pfile_info, + FILE_ALL_INFO *pfile_info, struct super_block *sb, int xid, const __u16 *pfid); extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, @@ -130,7 +130,7 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, - FILE_ALL_INFO * findData, + FILE_ALL_INFO *findData, int legacy /* whether to use old info level */, const struct nls_table *nls_codepage, int remap); extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, @@ -141,7 +141,7 @@ extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, - FILE_UNIX_BASIC_INFO * pFindData, + FILE_UNIX_BASIC_INFO *pFindData, const struct nls_table *nls_codepage, int remap); extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1cbe61524ef..3c05c2de50e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1247,7 +1247,7 @@ OldOpenRetry: } else { /* BB verify if wct == 15 */ -/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ +/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/ *netfid = pSMBr->Fid; /* cifs fid stays in le */ /* Let caller know file was created so we can set the mode. */ @@ -1944,7 +1944,7 @@ renameRetry: /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = - cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ @@ -2925,7 +2925,8 @@ setAclRetry: } params = 6 + name_len; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ + /* BB find max SMB size from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -3322,7 +3323,8 @@ QPathInfoRetry: params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(4000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -3388,7 +3390,7 @@ QPathInfoRetry: int CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, - FILE_UNIX_BASIC_INFO * pFindData, + FILE_UNIX_BASIC_INFO *pFindData, const struct nls_table *nls_codepage, int remap) { /* SMB_QUERY_FILE_UNIX_BASIC */ @@ -3922,7 +3924,8 @@ getDFSRetry: pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->MaxParameterCount = 0; - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(4000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4230,7 +4233,8 @@ QFSAttributeRetry: params = 2; /* level */ pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4299,7 +4303,8 @@ QFSDeviceRetry: params = 2; /* level */ pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4370,7 +4375,8 @@ QFSUnixRetry: pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(100); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4445,7 +4451,8 @@ SETFSUnixRetry: offset = param_offset + params; pSMB->MaxParameterCount = cpu_to_le16(4); - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(100); pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); @@ -4513,7 +4520,8 @@ QFSPosixRetry: pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(100); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4703,7 +4711,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, count = sizeof(struct file_end_of_file_info); pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); @@ -4790,7 +4799,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, count = sizeof(FILE_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ + /* BB find max SMB PDU from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); @@ -4857,7 +4867,8 @@ SetTimesRetry: params = 6 + name_len; 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 */ + /* BB find max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4987,7 +4998,8 @@ setPermsRetry: params = 6 + name_len; 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 */ + /* BB find max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -5170,7 +5182,8 @@ QAllEAsRetry: params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(4000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -5318,7 +5331,8 @@ QEARetry: params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ + /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(4000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -5476,7 +5490,8 @@ SetEARetry: count = sizeof(*parm_data) + ea_value_len + name_len; pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ + /* BB find max SMB PDU from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8e2fa6d46c7..7c2e5ea0330 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1820,7 +1820,7 @@ convert_delimiter(char *path, char delim) if (path == NULL) return; - if (delim == '/') + if (delim == '/') old_delim = '\\'; else old_delim = '/'; @@ -2321,9 +2321,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, user = ses->userName; domain = ses->domainName; smb_buffer = cifs_buf_get(); - if (smb_buffer == NULL) { + + if (smb_buffer == NULL) return -ENOMEM; - } + smb_buffer_response = smb_buffer; pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 00f4cff400b..8703d68f5b2 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -141,11 +141,11 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) int ret = 0; /* calculate length by finding first slash or NULL */ - if (address_family == AF_INET) { + if (address_family == AF_INET) ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); - } else if (address_family == AF_INET6) { + else if (address_family == AF_INET6) ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); - } + cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); if (ret > 0) ret = 1; diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 7170a9b70f1..c377d8065d9 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -64,7 +64,7 @@ typedef struct _SECURITY_BUFFER { } __attribute__((packed)) SECURITY_BUFFER; typedef struct _NEGOTIATE_MESSAGE { - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; __le32 MessageType; /* 1 */ __le32 NegotiateFlags; SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ @@ -74,7 +74,7 @@ typedef struct _NEGOTIATE_MESSAGE { } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; typedef struct _CHALLENGE_MESSAGE { - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; __le32 MessageType; /* 2 */ SECURITY_BUFFER TargetName; __le32 NegotiateFlags; -- cgit v1.2.3-70-g09d2 From 77c57ec89682c73785d12d51a6d1f873b292fa42 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 13 May 2008 21:39:32 +0000 Subject: [CIFS] don't explicitly do a FindClose on rewind when directory search has ended Do the following series of operations on a CIFS share: opendir(dir) readdir(dir) unlink(file in dir) rewinddir(dir) readdir(dir) If the readdir read all entries in the directory this will make CIFS throw an error like this: CIFS VFS: Send error in FindClose = -9 CIFS requests "Close at end of search" of the server by setting this bit when issuing FindFirst or FindNext. Therefore when all search entries are returned, the server may return "end of search" and close the search implicitly when this bit is set by the client on the request. We check for this when a readdir is explicitly closed - but when the client notices that a directory has changed after the last operation, we attempt to close the directory before reopening by reissuing a second FindFirst. But, the directory may already been implicitly closed (due to end of search) because the first readdir finished. So we only want to issue a FindClose call in this case when we don't expect it to already be closed. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/readdir.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 34ec32100c7..713c2511019 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -670,8 +670,11 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, (index_to_find < first_entry_in_buffer)) { /* close and restart search */ cFYI(1, ("search backing up - close and restart search")); - cifsFile->invalidHandle = true; - CIFSFindClose(xid, pTcon, cifsFile->netfid); + if (!cifsFile->srch_inf.endOfSearch && + !cifsFile->invalidHandle) { + cifsFile->invalidHandle = true; + CIFSFindClose(xid, pTcon, cifsFile->netfid); + } kfree(cifsFile->search_resume_name); cifsFile->search_resume_name = NULL; if (cifsFile->srch_inf.ntwrk_buf_start) { -- cgit v1.2.3-70-g09d2 From e10f7b551d2a79b113d5ce66b5dc9f3657035445 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 14 May 2008 10:21:33 -0700 Subject: clarify return value of cifs_convert_flags() cifs_convert_flags returns 0x20197 in the default case. It's not immediately evident where that number comes from, so change it to be an or'ed set of flags. The compiler will boil it down anyway. (Thanks to Guenter Kukkukk for clarifying the flags). Signed-off-by: Steve French --- fs/cifs/file.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 31a0a33b9d9..8636cec2642 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -75,7 +75,11 @@ static inline int cifs_convert_flags(unsigned int flags) return (GENERIC_READ | GENERIC_WRITE); } - return 0x20197; + return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | + FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | + FILE_READ_DATA); + + } static inline int cifs_get_disposition(unsigned int flags) -- cgit v1.2.3-70-g09d2 From 35fc37d5175091c36d034a28c057da0f9594ee7e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 14 May 2008 10:22:03 -0700 Subject: add function to convert access flags to legacy open mode SMBLegacyOpen always opens a file as r/w. This could be problematic for files with ATTR_READONLY set. Have it interpret the access_mode into a sane open mode. Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 22 +++++++++++++++------- fs/cifs/inode.c | 3 +-- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3c05c2de50e..9c04ad40455 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1166,6 +1166,20 @@ static __u16 convert_disposition(int disposition) return ofun; } +static int +access_flags_to_smbopen_mode(const int access_flags) +{ + int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); + + if (masked_flags == GENERIC_READ) + return SMBOPEN_READ; + else if (masked_flags == GENERIC_WRITE) + return SMBOPEN_WRITE; + + /* just go for read/write */ + return SMBOPEN_READWRITE; +} + int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int openDisposition, @@ -1207,13 +1221,7 @@ OldOpenRetry: 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 - 1 = write - 2 = rw - 3 = execute - */ - pSMB->Mode = cpu_to_le16(2); + pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags)); pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ /* set file as system file if special file such as fifo and server expecting SFU style and diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fcbdbb6ad7b..2d53b436d51 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1502,8 +1502,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) int oplock = 0; rc = SMBLegacyOpen(xid, pTcon, full_path, - FILE_OPEN, - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, + FILE_OPEN, GENERIC_WRITE, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & -- cgit v1.2.3-70-g09d2 From 646dd539878a194bc14b104621c0b2b33587e40f Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 15 May 2008 01:50:56 +0000 Subject: [CIFS] Fix paths when share is in DFS to include proper prefix Some versions of Samba (3.2-pre e.g.) are stricter about checking to make sure that paths in DFS name spaces are sent in the form \\server\share\dir\subdir ... instead of \dir\subdir Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 3 --- fs/cifs/connect.c | 26 +++------------------ fs/cifs/dir.c | 28 ++++++++++++++++++----- fs/cifs/inode.c | 65 +++++++---------------------------------------------- fs/cifs/link.c | 42 +++------------------------------- 5 files changed, 37 insertions(+), 127 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 08248e85b78..845b18e1abe 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -150,9 +150,6 @@ extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, unsigned int *number_of_UNC_in_array, const struct nls_table *nls_codepage, int remap); -extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, - const char *old_path, - const struct nls_table *nls_codepage, int remap); extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, const struct nls_table *nls_codepage, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7c2e5ea0330..d5747e30f1c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1418,27 +1418,6 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) return NULL; } -int -connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, - const char *old_path, const struct nls_table *nls_codepage, - int remap) -{ - struct dfs_info3_param *referrals = NULL; - unsigned int num_referrals; - int rc = 0; - - rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage, - &num_referrals, &referrals, remap); - - /* BB Add in code to: if valid refrl, if not ip address contact - the helper that resolves tcp names, mount to it, try to - tcon to it unmount it if fail */ - - kfree(referrals); - - return rc; -} - int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, const struct nls_table *nls_codepage, unsigned int *pnum_referrals, @@ -2161,10 +2140,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if ((strchr(volume_info.UNC + 3, '\\') == NULL) && (strchr(volume_info.UNC + 3, '/') == NULL)) { - rc = connect_to_dfs_path(xid, pSesInfo, +/* rc = connect_to_dfs_path(xid, pSesInfo, "", cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFS_MOUNT_MAP_SPECIAL_CHR);*/ + cFYI(1, ("DFS root not supported")); rc = -ENODEV; goto out; } else { diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e4e0078a052..05afe33ea64 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -49,18 +49,25 @@ build_path_from_dentry(struct dentry *direntry) struct dentry *temp; int namelen; int pplen; + int dfsplen; char *full_path; char dirsep; + struct cifs_sb_info *cifs_sb; if (direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ - dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); - pplen = CIFS_SB(direntry->d_sb)->prepathlen; + cifs_sb = CIFS_SB(direntry->d_sb); + dirsep = CIFS_DIR_SEP(cifs_sb); + pplen = cifs_sb->prepathlen; + if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) + dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); + else + dfsplen = 0; cifs_bp_rename_retry: - namelen = pplen; + namelen = pplen + dfsplen; for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; @@ -91,7 +98,7 @@ cifs_bp_rename_retry: return NULL; } } - if (namelen != pplen) { + if (namelen != pplen + dfsplen) { cERROR(1, ("did not end path lookup where expected namelen is %d", namelen)); @@ -107,7 +114,18 @@ cifs_bp_rename_retry: since the '\' is a valid posix character so we can not switch those safely to '/' if any are found in the middle of the prepath */ /* BB test paths to Windows with '/' in the midst of prepath */ - strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); + + if (dfsplen) { + strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { + int i; + for (i = 0; i < dfsplen; i++) { + if (full_path[i] == '\\') + full_path[i] = '/'; + } + } + } + strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen); return full_path; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2d53b436d51..9d9b56a9c08 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -161,52 +161,18 @@ static void cifs_unix_info_to_inode(struct inode *inode, spin_unlock(&inode->i_lock); } -static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb, - const char *search_path) -{ - int tree_len; - int path_len; - int i; - char *tmp_path; - struct cifsTconInfo *pTcon = cifs_sb->tcon; - - if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) - return search_path; - - /* use full path name for working with DFS */ - tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); - path_len = strnlen(search_path, MAX_PATHCONF); - - tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); - if (tmp_path == NULL) - return search_path; - - strncpy(tmp_path, pTcon->treeName, tree_len); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - for (i = 0; i < tree_len; i++) { - if (tmp_path[i] == '\\') - tmp_path[i] = '/'; - } - strncpy(tmp_path+tree_len, search_path, path_len); - tmp_path[tree_len+path_len] = 0; - return tmp_path; -} - int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *search_path, struct super_block *sb, int xid) + const unsigned char *full_path, struct super_block *sb, int xid) { int rc = 0; FILE_UNIX_BASIC_INFO findData; struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - const unsigned char *full_path; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; - cFYI(1, ("Getting info on %s", search_path)); - - full_path = cifs_get_search_path(cifs_sb, search_path); + cFYI(1, ("Getting info on %s", full_path)); try_again_CIFSSMBUnixQPathInfo: /* could have done a find first instead but this returns more info */ @@ -218,10 +184,6 @@ try_again_CIFSSMBUnixQPathInfo: if (rc) { if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; - if (full_path != search_path) { - kfree(full_path); - full_path = search_path; - } goto try_again_CIFSSMBUnixQPathInfo; } goto cgiiu_exit; @@ -271,8 +233,6 @@ try_again_CIFSSMBUnixQPathInfo: cifs_set_ops(inode, is_dfs_referral); } cgiiu_exit: - if (full_path != search_path) - kfree(full_path); return rc; } @@ -380,20 +340,19 @@ static int get_sfu_mode(struct inode *inode, } int cifs_get_inode_info(struct inode **pinode, - const unsigned char *search_path, FILE_ALL_INFO *pfindData, + const unsigned char *full_path, FILE_ALL_INFO *pfindData, struct super_block *sb, int xid, const __u16 *pfid) { int rc = 0; struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - const unsigned char *full_path = NULL; char *buf = NULL; bool adjustTZ = false; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; - cFYI(1, ("Getting info on %s", search_path)); + cFYI(1, ("Getting info on %s", full_path)); if ((pfindData == NULL) && (*pinode != NULL)) { if (CIFS_I(*pinode)->clientCanCacheRead) { @@ -409,8 +368,6 @@ int cifs_get_inode_info(struct inode **pinode, return -ENOMEM; pfindData = (FILE_ALL_INFO *)buf; - full_path = cifs_get_search_path(cifs_sb, search_path); - try_again_CIFSSMBQPathInfo: /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, @@ -432,10 +389,6 @@ try_again_CIFSSMBQPathInfo: if (rc) { if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; - if (full_path != search_path) { - kfree(full_path); - full_path = search_path; - } goto try_again_CIFSSMBQPathInfo; } goto cgii_exit; @@ -470,7 +423,7 @@ try_again_CIFSSMBQPathInfo: __u64 inode_num; rc1 = CIFSGetSrvInodeNumber(xid, pTcon, - search_path, &inode_num, + full_path, &inode_num, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -539,7 +492,7 @@ try_again_CIFSSMBQPathInfo: (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), - search_path, + full_path, cifs_sb, xid)) cFYI(1, ("Unrecognized sfu inode type")); @@ -582,12 +535,12 @@ try_again_CIFSSMBQPathInfo: /* fill in 0777 bits from ACL */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { cFYI(1, ("Getting mode bits from ACL")); - acl_to_uid_mode(inode, search_path, pfid); + acl_to_uid_mode(inode, full_path, pfid); } #endif if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { /* fill in remaining high mode bits e.g. SUID, VTX */ - get_sfu_mode(inode, search_path, cifs_sb, xid); + get_sfu_mode(inode, full_path, cifs_sb, xid); } else if (atomic_read(&cifsInfo->inUse) == 0) { inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; @@ -599,8 +552,6 @@ try_again_CIFSSMBQPathInfo: cifs_set_ops(inode, is_dfs_referral); } cgii_exit: - if (full_path != search_path) - kfree(full_path); kfree(buf); return rc; } diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1c2c3ce5020..316f9830ce3 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -295,45 +295,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) cFYI(1, ("Error closing junction point " "(open for ioctl)")); } - /* BB unwind this long, nested function, or remove BB */ - if (rc == -EIO) { - /* Query if DFS Junction */ - unsigned int num_referrals = 0; - struct dfs_info3_param *refs = NULL; - tmp_path = - kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, - GFP_KERNEL); - if (tmp_path) { - strncpy(tmp_path, pTcon->treeName, - MAX_TREE_SIZE); - strncat(tmp_path, full_path, - MAX_PATHCONF); - rc = get_dfs_path(xid, pTcon->ses, - tmp_path, - cifs_sb->local_nls, - &num_referrals, &refs, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, ("Get DFS for %s rc = %d ", - tmp_path, rc)); - if ((num_referrals == 0) && (rc == 0)) - rc = -EACCES; - else { - cFYI(1, ("num referral: %d", - num_referrals)); - if (refs && refs->path_name) { - strncpy(tmpbuffer, - refs->path_name, - len-1); - } - } - kfree(refs); - kfree(tmp_path); -} - /* BB add code like else decode referrals - then memcpy to tmpbuffer and free referrals - string array BB */ - } + /* If it is a DFS junction earlier we would have gotten + PATH_NOT_COVERED returned from server so we do + not need to request the DFS info here */ } } /* BB Anything else to do to handle recursive links? */ -- cgit v1.2.3-70-g09d2 From c32916374b2b4f4d2b7ccdb357fe7989f3b407a6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 15 May 2008 05:41:54 +0000 Subject: [CIFS] suppress duplicate warning fs/cifs/dir.c: In function 'cifs_ci_compare': fs/cifs/dir.c:582: warning: passing argument 1 of 'memcpy' discards qualifiers from pointer target type Signed-off-by: Andrew Morton Signed-off-by: Steve French --- fs/cifs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 05afe33ea64..f0b5b5f3dd2 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -608,7 +608,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, * case take precedence. If a is not a negative dentry, this * should have no side effects */ - memcpy(a->name, b->name, a->len); + memcpy((void *)a->name, b->name, a->len); return 0; } return 1; -- cgit v1.2.3-70-g09d2 From f9ddcca4cf7d95238beb295484d1de7c0bf490dd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 15 May 2008 05:51:55 +0000 Subject: [CIFS] BKL-removal: convert CIFS over to unlocked_ioctl cifs_ioctl doesn't seem to need the BKL for anything, so convert it over to use unlocked_ioctl. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 10 +++++----- fs/cifs/cifsfs.h | 3 +-- fs/cifs/ioctl.c | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 427a7c69589..b6436b888cf 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -657,7 +657,7 @@ const struct file_operations cifs_file_ops = { .splice_read = generic_file_splice_read, .llseek = cifs_llseek, #ifdef CONFIG_CIFS_POSIX - .ioctl = cifs_ioctl, + .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ #ifdef CONFIG_CIFS_EXPERIMENTAL @@ -677,7 +677,7 @@ const struct file_operations cifs_file_direct_ops = { .flush = cifs_flush, .splice_read = generic_file_splice_read, #ifdef CONFIG_CIFS_POSIX - .ioctl = cifs_ioctl, + .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ .llseek = cifs_llseek, #ifdef CONFIG_CIFS_EXPERIMENTAL @@ -697,7 +697,7 @@ const struct file_operations cifs_file_nobrl_ops = { .splice_read = generic_file_splice_read, .llseek = cifs_llseek, #ifdef CONFIG_CIFS_POSIX - .ioctl = cifs_ioctl, + .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ #ifdef CONFIG_CIFS_EXPERIMENTAL @@ -716,7 +716,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { .flush = cifs_flush, .splice_read = generic_file_splice_read, #ifdef CONFIG_CIFS_POSIX - .ioctl = cifs_ioctl, + .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ .llseek = cifs_llseek, #ifdef CONFIG_CIFS_EXPERIMENTAL @@ -731,7 +731,7 @@ const struct file_operations cifs_dir_ops = { #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ - .ioctl = cifs_ioctl, + .unlocked_ioctl = cifs_ioctl, }; static void diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index cd1301a09b3..25a6cbd1552 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -95,8 +95,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, 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, - unsigned int command, unsigned long arg); +extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); #ifdef CONFIG_CIFS_EXPERIMENTAL extern const struct export_operations cifs_export_ops; diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 5c792df13d6..0088a5b5256 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -30,9 +30,9 @@ #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) -int cifs_ioctl(struct inode *inode, struct file *filep, - unsigned int command, unsigned long arg) +long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) { + struct inode *inode = filep->f_dentry->d_inode; int rc = -ENOTTY; /* strange error - but the precedent */ int xid; struct cifs_sb_info *cifs_sb; -- cgit v1.2.3-70-g09d2 From c2cf07d591ef7bc25c220249822d9bdf0f44c75c Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 15 May 2008 06:20:02 +0000 Subject: [CIFS] Finishup DFS code Fixup GetDFSRefer to prepare for cleanup of SMB response processing Fix build warning in link.c Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 4 +- fs/cifs/cifssmb.c | 169 ++++++++++++++++++++++++---------------------------- fs/cifs/connect.c | 3 +- fs/cifs/link.c | 1 - 4 files changed, 80 insertions(+), 97 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 845b18e1abe..b9f5e935f82 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -146,8 +146,8 @@ extern int CIFSSMBUnixQPathInfo(const int xid, extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, - unsigned char **targetUNCs, - unsigned int *number_of_UNC_in_array, + struct dfs_info3_param **target_nodes, + unsigned int *number_of_nodes_in_array, const struct nls_table *nls_codepage, int remap); extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9c04ad40455..fc297383cb0 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3870,8 +3870,8 @@ GetInodeNumOut: int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, - unsigned char **targetUNCs, - unsigned int *number_of_UNC_in_array, + struct dfs_info3_param **target_nodes, + unsigned int *num_of_nodes, const struct nls_table *nls_codepage, int remap) { /* TRANS2_GET_DFS_REFERRAL */ @@ -3884,8 +3884,8 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, unsigned int i; char *temp; __u16 params, byte_count; - *number_of_UNC_in_array = 0; - *targetUNCs = NULL; + *num_of_nodes = 0; + *target_nodes = NULL; cFYI(1, ("In GetDFSRefer the path %s", searchName)); if (ses == NULL) @@ -3955,99 +3955,84 @@ getDFSRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in GetDFSRefer = %d", rc)); - } else { /* decode response */ -/* BB Add logic to parse referrals here */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - /* BB Also check if enough total bytes returned? */ - if (rc || (pSMBr->ByteCount < 17)) - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); - - cFYI(1, - ("Decoding GetDFSRefer response BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - referrals = - (struct dfs_referral_level_3 *) - (8 /* sizeof start of data block */ + - data_offset + - (char *) &pSMBr->hdr.Protocol); - cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" - "for referral one refer size: 0x%x srv " - "type: 0x%x refer flags: 0x%x ttl: 0x%x", - le16_to_cpu(pSMBr->NumberOfReferrals), - le16_to_cpu(pSMBr->DFSFlags), - le16_to_cpu(referrals->ReferralSize), - le16_to_cpu(referrals->ServerType), - le16_to_cpu(referrals->ReferralFlags), - le16_to_cpu(referrals->TimeToLive))); - /* BB This field is actually two bytes in from start of - data block so we could do safety check that DataBlock - begins at address of pSMBr->NumberOfReferrals */ - *number_of_UNC_in_array = - le16_to_cpu(pSMBr->NumberOfReferrals); - - /* BB Fix below so can return more than one referral */ - if (*number_of_UNC_in_array > 1) - *number_of_UNC_in_array = 1; - - /* get the length of the strings describing refs */ - name_len = 0; - for (i = 0; i < *number_of_UNC_in_array; i++) { - /* make sure that DfsPathOffset not past end */ - __u16 offset = - le16_to_cpu(referrals->DfsPathOffset); - if (offset > data_count) { - /* if invalid referral, stop here and do - not try to copy any more */ - *number_of_UNC_in_array = i; - break; - } - temp = ((char *)referrals) + offset; + goto GetDFSRefExit; + } + rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len += UniStrnlen((wchar_t *)temp, - data_count); - } else { - name_len += strnlen(temp, data_count); - } - referrals++; - /* BB add check that referral pointer does - not fall off end PDU */ - } - /* BB add check for name_len bigger than bcc */ - *targetUNCs = - kmalloc(name_len+1+(*number_of_UNC_in_array), - GFP_KERNEL); - if (*targetUNCs == NULL) { - rc = -ENOMEM; - goto GetDFSRefExit; + /* BB Also check if enough total bytes returned? */ + if (rc || (pSMBr->ByteCount < 17)) + rc = -EIO; /* bad smb */ + else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); + + cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", + pSMBr->ByteCount, data_offset)); + referrals = + (struct dfs_referral_level_3 *) + (8 /* sizeof start of data block */ + + data_offset + + (char *) &pSMBr->hdr.Protocol); + cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" + "for referral one refer size: 0x%x srv " + "type: 0x%x refer flags: 0x%x ttl: 0x%x", + le16_to_cpu(pSMBr->NumberOfReferrals), + le16_to_cpu(pSMBr->DFSFlags), + le16_to_cpu(referrals->ReferralSize), + le16_to_cpu(referrals->ServerType), + le16_to_cpu(referrals->ReferralFlags), + le16_to_cpu(referrals->TimeToLive))); + /* BB This field is actually two bytes in from start of + data block so we could do safety check that DataBlock + begins at address of pSMBr->NumberOfReferrals */ + *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); + + /* BB Fix below so can return more than one referral */ + if (*num_of_nodes > 1) + *num_of_nodes = 1; + + /* get the length of the strings describing refs */ + name_len = 0; + for (i = 0; i < *num_of_nodes; i++) { + /* make sure that DfsPathOffset not past end */ + __u16 offset = le16_to_cpu(referrals->DfsPathOffset); + if (offset > data_count) { + /* if invalid referral, stop here and do + not try to copy any more */ + *num_of_nodes = i; + break; } - /* copy the ref strings */ - referrals = (struct dfs_referral_level_3 *) - (8 /* sizeof data hdr */ + data_offset + - (char *) &pSMBr->hdr.Protocol); - - for (i = 0; i < *number_of_UNC_in_array; i++) { - temp = ((char *)referrals) + - le16_to_cpu(referrals->DfsPathOffset); - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - cifs_strfromUCS_le(*targetUNCs, - (__le16 *) temp, - name_len, - nls_codepage); - } else { - strncpy(*targetUNCs, temp, name_len); - } - /* BB update target_uncs pointers */ - referrals++; + temp = ((char *)referrals) + offset; + + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len += UniStrnlen((wchar_t *)temp, + data_count); + } else { + name_len += strnlen(temp, data_count); } - temp = *targetUNCs; - temp[name_len] = 0; + referrals++; + /* BB add check that referral pointer does + not fall off end PDU */ + } + /* BB add check for name_len bigger than bcc */ + *target_nodes = + kmalloc(name_len+1+(*num_of_nodes), + GFP_KERNEL); + if (*target_nodes == NULL) { + rc = -ENOMEM; + goto GetDFSRefExit; } + referrals = (struct dfs_referral_level_3 *) + (8 /* sizeof data hdr */ + data_offset + + (char *) &pSMBr->hdr.Protocol); + + for (i = 0; i < *num_of_nodes; i++) { + temp = ((char *)referrals) + + le16_to_cpu(referrals->DfsPathOffset); + /* BB update target_uncs pointers */ + referrals++; + } } GetDFSRefExit: if (pSMB) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d5747e30f1c..c397fcfd9f1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1425,7 +1425,6 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, { char *temp_unc; int rc = 0; - unsigned char *targetUNCs; *pnum_referrals = 0; *preferrals = NULL; @@ -1448,7 +1447,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, kfree(temp_unc); } if (rc == 0) - rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &targetUNCs, + rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, pnum_referrals, nls_codepage, remap); /* BB map targetUNCs to dfs_info3 structures, here or in CIFSGetDFSRefer BB */ diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 316f9830ce3..63f644000ce 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -234,7 +234,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; - char *tmp_path = NULL; char *tmpbuffer; int len; __u16 fid; -- cgit v1.2.3-70-g09d2 From 95b1cb90b79896c4bf5ea484bee2b41d7d293f43 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 15 May 2008 16:44:38 +0000 Subject: [CIFS] enable parsing for transport encryption mount parm Samba now supports transport encryption on particular exports (mounted tree ids can be encrypted for servers which support the unix extensions). This adds parsing support to cifs mount option parsing for this. Signed-off-by: Steve French --- fs/cifs/README | 5 +++++ fs/cifs/cifsglob.h | 1 + fs/cifs/connect.c | 25 +++++++++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/README b/fs/cifs/README index 621aa1a8597..2bd6fe556f8 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -483,6 +483,11 @@ A partial list of the supported mount options follows: sign Must use packet signing (helps avoid unwanted data modification by intermediate systems in the route). Note that signing does not work with lanman or plaintext authentication. + seal Must seal (encrypt) all data on this mounted share before + sending on the network. Requires support for Unix Extensions. + Note that this differs from the sign mount option in that it + causes encryption of data sent over this mounted share but other + shares mounted to the same server are unaffected. sec Security mode. Allowed values are: none attempt to connection as a null user (no name) krb5 Use Kerberos version 5 authentication diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b7d9f698e63..08914053242 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -281,6 +281,7 @@ struct cifsTconInfo { bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ bool retry:1; bool nocase:1; + bool seal:1; /* transport encryption for this mounted share */ bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol for this mount even if server would support */ /* BB add field for back pointer to sb struct(s)? */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c397fcfd9f1..023434f72c1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -60,7 +60,7 @@ struct smb_vol { char *domainname; char *UNC; char *UNCip; - char *in6_addr; /* ipv6 address as human readable form of in6_addr */ + char *in6_addr; /* ipv6 address as human readable form of in6_addr */ char *iocharset; /* local code page for mapping to and from Unicode */ char source_rfc1001_name[16]; /* netbios name of client */ char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ @@ -82,13 +82,14 @@ struct smb_vol { bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ bool server_ino:1; /* use inode numbers from server ie UniqueId */ bool direct_io:1; - bool remap:1; /* set to remap seven reserved chars in filenames */ - bool posix_paths:1; /* unset to not ask for posix pathnames. */ + bool remap:1; /* set to remap seven reserved chars in filenames */ + bool posix_paths:1; /* unset to not ask for posix pathnames. */ bool no_linux_ext:1; bool sfu_emul:1; - bool nullauth:1; /* attempt to authenticate with null user */ - unsigned nocase; /* request case insensitive filenames */ - unsigned nobrl; /* disable sending byte range locks to srv */ + bool nullauth:1; /* attempt to authenticate with null user */ + bool nocase:1; /* request case insensitive filenames */ + bool nobrl:1; /* disable sending byte range locks to srv */ + bool seal:1; /* request transport encryption on share */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -1273,8 +1274,12 @@ cifs_parse_mount_options(char *options, const char *devname, vol->no_psx_acl = 1; } else if (strnicmp(data, "sign", 4) == 0) { vol->secFlg |= CIFSSEC_MUST_SIGN; -/* } else if (strnicmp(data, "seal",4) == 0) { - vol->secFlg |= CIFSSEC_MUST_SEAL; */ + } else if (strnicmp(data, "seal", 4) == 0) { + /* we do not do the following in secFlags because seal + is a per tree connection (mount) not a per socket + or per-smb connection option in the protocol */ + /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ + vol->seal = 1; } else if (strnicmp(data, "direct", 6) == 0) { vol->direct_io = 1; } else if (strnicmp(data, "forcedirectio", 13) == 0) { @@ -2126,6 +2131,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, for the retry flag is used */ tcon->retry = volume_info.retry; tcon->nocase = volume_info.nocase; + if (tcon->seal != volume_info.seal) + cERROR(1, ("transport encryption setting " + "conflicts with existing tid")); } else { tcon = tconInfoAlloc(); if (tcon == NULL) @@ -2159,6 +2167,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, atomic_inc(&pSesInfo->inUse); tcon->retry = volume_info.retry; tcon->nocase = volume_info.nocase; + tcon->seal = volume_info.seal; } } } -- cgit v1.2.3-70-g09d2 From de2db8d790b058fcd75d603780b913bd824972b3 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 16 May 2008 13:10:32 +0400 Subject: Fixed DFS code to work with new 'build_path_from_dentry', that returns full path if share in the dfs, now. Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 49 +------------------------------------------------ 1 file changed, 1 insertion(+), 48 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f6fdecf6598..d82374c9e32 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -219,53 +219,6 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, } -static char *build_full_dfs_path_from_dentry(struct dentry *dentry) -{ - char *full_path = NULL; - char *search_path; - char *tmp_path; - size_t l_max_len; - struct cifs_sb_info *cifs_sb; - - if (dentry->d_inode == NULL) - return NULL; - - cifs_sb = CIFS_SB(dentry->d_inode->i_sb); - - if (cifs_sb->tcon == NULL) - return NULL; - - search_path = build_path_from_dentry(dentry); - if (search_path == NULL) - return NULL; - - if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) { - int i; - /* we should use full path name for correct working with DFS */ - l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) + - strnlen(search_path, MAX_PATHCONF) + 1; - tmp_path = kmalloc(l_max_len, GFP_KERNEL); - if (tmp_path == NULL) { - kfree(search_path); - return NULL; - } - strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len); - tmp_path[l_max_len-1] = 0; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - for (i = 0; i < l_max_len; i++) { - if (tmp_path[i] == '\\') - tmp_path[i] = '/'; - } - strncat(tmp_path, search_path, l_max_len - strlen(tmp_path)); - - full_path = tmp_path; - kfree(search_path); - } else { - full_path = search_path; - } - return full_path; -} - static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, struct list_head *mntlist) { @@ -333,7 +286,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) goto out_err; } - full_path = build_full_dfs_path_from_dentry(dentry); + full_path = build_path_from_dentry(dentry); if (full_path == NULL) { rc = -ENOMEM; goto out_err; -- cgit v1.2.3-70-g09d2 From fec4585fd71cc5ec35d134e8c3854f6e8c4503f0 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 16 May 2008 13:06:30 +0400 Subject: CIFSGetDFSRefer cleanup + dfs_referral_level_3 fixed to conform REFERRAL_V3 the MS-DFSC spec. Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 16 ++--- fs/cifs/cifssmb.c | 205 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 139 insertions(+), 82 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index c43bf4b7a55..93d5ee02a25 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1906,17 +1906,15 @@ typedef struct smb_com_transaction2_get_dfs_refer_req { typedef struct dfs_referral_level_3 { __le16 VersionNumber; - __le16 ReferralSize; - __le16 ServerType; /* 0x0001 = CIFS server */ - __le16 ReferralFlags; /* or proximity - not clear which since it is - always set to zero - SNIA spec says 0x01 - means strip off PathConsumed chars before - submitting RequestFileName to remote node */ - __le16 TimeToLive; - __le16 Proximity; + __le16 Size; + __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ + __le16 ReferralEntryFlags; /* 0x0200 bit set only for domain + or DC referral responce */ + __le32 TimeToLive; __le16 DfsPathOffset; __le16 DfsAlternatePathOffset; - __le16 NetworkAddressOffset; + __le16 NetworkAddressOffset; /* offset of the link target */ + __le16 ServiceSiteGuid; } __attribute__((packed)) REFERRAL3; typedef struct smb_com_transaction_get_dfs_refer_rsp { diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fc297383cb0..6f8ed93a4ae 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -81,6 +81,39 @@ static struct { #endif /* CONFIG_CIFS_WEAK_PW_HASH */ #endif /* CIFS_POSIX */ +/* Allocates buffer into dst and copies smb string from src to it. + * caller is responsible for freeing dst if function returned 0. + * returns: + * on success - 0 + * on failure - errno + */ +static int +cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, + const bool is_unicode, const struct nls_table *nls_codepage) +{ + int plen; + + if (is_unicode) { + plen = UniStrnlen((wchar_t *)src, maxlen); + *dst = kmalloc(plen + 2, GFP_KERNEL); + if (!*dst) + goto cifs_strncpy_to_host_ErrExit; + cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); + } else { + plen = strnlen(src, maxlen); + *dst = kmalloc(plen + 2, GFP_KERNEL); + if (!*dst) + goto cifs_strncpy_to_host_ErrExit; + strncpy(*dst, src, plen); + } + (*dst)[plen] = 0; + return 0; + +cifs_strncpy_to_host_ErrExit: + cERROR(1, ("Failed to allocate buffer for string\n")); + return -ENOMEM; +} + /* Mark as invalid, all open files on tree connections since they were closed when session to server was lost */ @@ -3867,6 +3900,96 @@ GetInodeNumOut: return rc; } +/* parses DFS refferal V3 structure + * caller is responsible for freeing target_nodes + * returns: + * on success - 0 + * on failure - errno + */ +static int +parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, + unsigned int *num_of_nodes, + struct dfs_info3_param **target_nodes, + const struct nls_table *nls_codepage) +{ + int i, rc = 0; + char *data_end; + bool is_unicode; + struct dfs_referral_level_3 *ref; + + is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE; + *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); + + if (*num_of_nodes < 1) { + cERROR(1, ("num_referrals: must be at least > 0," + "but we get num_referrals = %d\n", *num_of_nodes)); + rc = -EINVAL; + goto parse_DFS_REFERRALS_exit; + } + + ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); + if (ref->VersionNumber != 3) { + cERROR(1, ("Referrals of V%d version are not supported," + "should be V3", ref->VersionNumber)); + rc = -EINVAL; + goto parse_DFS_REFERRALS_exit; + } + + /* get the upper boundary of the resp buffer */ + data_end = (char *)(&(pSMBr->PathConsumed)) + + le16_to_cpu(pSMBr->t2.DataCount); + + cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", + *num_of_nodes, + le16_to_cpu(pSMBr->DFSFlags))); + + *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * + *num_of_nodes, GFP_KERNEL); + if (*target_nodes == NULL) { + cERROR(1, ("Failed to allocate buffer for target_nodes\n")); + rc = -ENOMEM; + goto parse_DFS_REFERRALS_exit; + } + + /* collect neccessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { + char *temp; + int max_len; + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le16_to_cpu(pSMBr->DFSFlags); + node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); + + /* copy DfsPath */ + temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); + max_len = data_end - temp; + rc = cifs_strncpy_to_host(&(node->path_name), temp, + max_len, is_unicode, nls_codepage); + if (rc) + goto parse_DFS_REFERRALS_exit; + + /* copy link target UNC */ + temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); + max_len = data_end - temp; + rc = cifs_strncpy_to_host(&(node->node_name), temp, + max_len, is_unicode, nls_codepage); + if (rc) + goto parse_DFS_REFERRALS_exit; + + ref += ref->Size; + } + +parse_DFS_REFERRALS_exit: + if (rc) { + free_dfs_info_array(*target_nodes, *num_of_nodes); + *target_nodes = NULL; + *num_of_nodes = 0; + } + return rc; +} + int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, @@ -3877,12 +4000,9 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, /* TRANS2_GET_DFS_REFERRAL */ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; - struct dfs_referral_level_3 *referrals = NULL; int rc = 0; int bytes_returned; int name_len; - unsigned int i; - char *temp; __u16 params, byte_count; *num_of_nodes = 0; *target_nodes = NULL; @@ -3960,80 +4080,19 @@ getDFSRetry: rc = validate_t2((struct smb_t2_rsp *)pSMBr); /* BB Also check if enough total bytes returned? */ - if (rc || (pSMBr->ByteCount < 17)) + if (rc || (pSMBr->ByteCount < 17)) { rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); - - cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - referrals = - (struct dfs_referral_level_3 *) - (8 /* sizeof start of data block */ + - data_offset + - (char *) &pSMBr->hdr.Protocol); - cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" - "for referral one refer size: 0x%x srv " - "type: 0x%x refer flags: 0x%x ttl: 0x%x", - le16_to_cpu(pSMBr->NumberOfReferrals), - le16_to_cpu(pSMBr->DFSFlags), - le16_to_cpu(referrals->ReferralSize), - le16_to_cpu(referrals->ServerType), - le16_to_cpu(referrals->ReferralFlags), - le16_to_cpu(referrals->TimeToLive))); - /* BB This field is actually two bytes in from start of - data block so we could do safety check that DataBlock - begins at address of pSMBr->NumberOfReferrals */ - *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); - - /* BB Fix below so can return more than one referral */ - if (*num_of_nodes > 1) - *num_of_nodes = 1; - - /* get the length of the strings describing refs */ - name_len = 0; - for (i = 0; i < *num_of_nodes; i++) { - /* make sure that DfsPathOffset not past end */ - __u16 offset = le16_to_cpu(referrals->DfsPathOffset); - if (offset > data_count) { - /* if invalid referral, stop here and do - not try to copy any more */ - *num_of_nodes = i; - break; - } - temp = ((char *)referrals) + offset; + goto GetDFSRefExit; + } - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len += UniStrnlen((wchar_t *)temp, - data_count); - } else { - name_len += strnlen(temp, data_count); - } - referrals++; - /* BB add check that referral pointer does - not fall off end PDU */ - } - /* BB add check for name_len bigger than bcc */ - *target_nodes = - kmalloc(name_len+1+(*num_of_nodes), - GFP_KERNEL); - if (*target_nodes == NULL) { - rc = -ENOMEM; - goto GetDFSRefExit; - } + cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", + pSMBr->ByteCount, + le16_to_cpu(pSMBr->t2.DataOffset))); - referrals = (struct dfs_referral_level_3 *) - (8 /* sizeof data hdr */ + data_offset + - (char *) &pSMBr->hdr.Protocol); + /* parse returned result into more usable form */ + rc = parse_DFS_REFERRALS(pSMBr, num_of_nodes, + target_nodes, nls_codepage); - for (i = 0; i < *num_of_nodes; i++) { - temp = ((char *)referrals) + - le16_to_cpu(referrals->DfsPathOffset); - /* BB update target_uncs pointers */ - referrals++; - } - } GetDFSRefExit: if (pSMB) cifs_buf_release(pSMB); -- cgit v1.2.3-70-g09d2 From a1fe78f16eac7d03d3c391dd5d54559826574982 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 16 May 2008 18:48:38 +0000 Subject: [CIFS] Add missing defines for DFS Also has minor cleanup of previous patch CC: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 9 +++++++++ fs/cifs/cifssmb.c | 17 +++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 93d5ee02a25..65d58b4e6a6 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1904,6 +1904,15 @@ typedef struct smb_com_transaction2_get_dfs_refer_req { char RequestFileName[1]; } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; +#define DFS_VERSION cpu_to_le16(0x0003) + +/* DFS server target type */ +#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */ +#define DFS_TYPE_ROOT 0x0001 + +/* Referral Entry Flags */ +#define DFS_NAME_LIST_REF 0x0200 + typedef struct dfs_referral_level_3 { __le16 VersionNumber; __le16 Size; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6f8ed93a4ae..7b9938445b0 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -107,6 +107,7 @@ cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, strncpy(*dst, src, plen); } (*dst)[plen] = 0; + (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ return 0; cifs_strncpy_to_host_ErrExit: @@ -3907,7 +3908,7 @@ GetInodeNumOut: * on failure - errno */ static int -parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, +parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, unsigned int *num_of_nodes, struct dfs_info3_param **target_nodes, const struct nls_table *nls_codepage) @@ -3924,7 +3925,7 @@ parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, cERROR(1, ("num_referrals: must be at least > 0," "but we get num_referrals = %d\n", *num_of_nodes)); rc = -EINVAL; - goto parse_DFS_REFERRALS_exit; + goto parse_DFS_referrals_exit; } ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); @@ -3932,7 +3933,7 @@ parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, cERROR(1, ("Referrals of V%d version are not supported," "should be V3", ref->VersionNumber)); rc = -EINVAL; - goto parse_DFS_REFERRALS_exit; + goto parse_DFS_referrals_exit; } /* get the upper boundary of the resp buffer */ @@ -3948,7 +3949,7 @@ parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, if (*target_nodes == NULL) { cERROR(1, ("Failed to allocate buffer for target_nodes\n")); rc = -ENOMEM; - goto parse_DFS_REFERRALS_exit; + goto parse_DFS_referrals_exit; } /* collect neccessary data from referrals */ @@ -3968,7 +3969,7 @@ parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, rc = cifs_strncpy_to_host(&(node->path_name), temp, max_len, is_unicode, nls_codepage); if (rc) - goto parse_DFS_REFERRALS_exit; + goto parse_DFS_referrals_exit; /* copy link target UNC */ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); @@ -3976,12 +3977,12 @@ parse_DFS_REFERRALS(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, rc = cifs_strncpy_to_host(&(node->node_name), temp, max_len, is_unicode, nls_codepage); if (rc) - goto parse_DFS_REFERRALS_exit; + goto parse_DFS_referrals_exit; ref += ref->Size; } -parse_DFS_REFERRALS_exit: +parse_DFS_referrals_exit: if (rc) { free_dfs_info_array(*target_nodes, *num_of_nodes); *target_nodes = NULL; @@ -4090,7 +4091,7 @@ getDFSRetry: le16_to_cpu(pSMBr->t2.DataOffset))); /* parse returned result into more usable form */ - rc = parse_DFS_REFERRALS(pSMBr, num_of_nodes, + rc = parse_DFS_referrals(pSMBr, num_of_nodes, target_nodes, nls_codepage); GetDFSRefExit: -- cgit v1.2.3-70-g09d2 From 2b280fab12b6697b6a7a24a13aaf9f4339edd075 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 17 May 2008 03:12:45 +0000 Subject: [CIFS] add more complete mount options to cifs_show_options adds various options to cifs_show_options (displayed when you cat /proc/mounts with a cifs mount). I limited the new ones to values that are associated with the mount with the exception of "seal" (which is a per tree connection property, but I thought was important enough to show through). Eventually cifs's parse_mount_options also needs to be rewritten to use the match_token API but that would be a big enough change that I would prefer that changing parse_mount_options wait until next release. Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b6436b888cf..57e40c49d3b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifsfs.c * - * Copyright (C) International Business Machines Corp., 2002,2007 + * Copyright (C) International Business Machines Corp., 2002,2008 * Author(s): Steve French (sfrench@us.ibm.com) * * Common Internet FileSystem (CIFS) client @@ -353,9 +353,38 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || !(cifs_sb->tcon->unix_ext)) seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); + if (!cifs_sb->tcon->unix_ext) { + seq_printf(s, ",file_mode=0%o,dir_mode=0%o", + cifs_sb->mnt_file_mode, + cifs_sb->mnt_dir_mode); + } + if (cifs_sb->tcon->seal) + seq_printf(s, ",seal"); + seq_printf(s, ",nocase"); } if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) seq_printf(s, ",posixpaths"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) + seq_printf(s, ",setuids"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + seq_printf(s, ",serverino"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + seq_printf(s, ",directio"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + seq_printf(s, ",nouser_xattr"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) + seq_printf(s, ",mapchars"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) + seq_printf(s, ",sfu"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) + seq_printf(s, ",nobrl"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) + seq_printf(s, ",cifsacl"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) + seq_printf(s, ",dynperm"); + if (m->mnt_sb->s_flags & MS_POSIXACL) + seq_printf(s, ",acl"); + seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize); } -- cgit v1.2.3-70-g09d2 From 89562b777c50d100d1694db7b1b023279839b9ae Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 19 May 2008 22:26:42 +0000 Subject: [CIFS] add missing seq_printf to cifs_show_options for hard mount option Also Kari Hurtta noticed a missing check in the same function which is now fixed. CC: Kari Hurtta Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 57e40c49d3b..5df93fd6303 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -360,7 +360,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) } if (cifs_sb->tcon->seal) seq_printf(s, ",seal"); + if (cifs_sb->tcon->nocase) seq_printf(s, ",nocase"); + if (cifs_sb->tcon->retry) + seq_printf(s, ",hard"); } if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) seq_printf(s, ",posixpaths"); -- cgit v1.2.3-70-g09d2 From 0e4bbde94fdc33f5b3d793166b21bf768ca3e098 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 20 May 2008 19:50:46 +0000 Subject: [CIFS] Enable DFS support for Unix query path info Final piece for handling DFS in unix_query_path_info, constructing a fake inode for the junction directory which the submount will cover. Acked-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/AUTHORS | 1 + fs/cifs/CHANGES | 2 + fs/cifs/TODO | 15 ++++---- fs/cifs/inode.c | 117 +++++++++++++++++++++++++++++++++++--------------------- 4 files changed, 85 insertions(+), 50 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 8848e4dfa02..9c136d7803d 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -36,6 +36,7 @@ Miklos Szeredi Kazeon team for various fixes especially for 2.4 version. Asser Ferno (Change Notify support) Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup +Igor Mammedov (DFS support) Test case and Bug Report contributors ------------------------------------- diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 502a4c2b841..28e3d5c5fca 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,5 +1,7 @@ Version 1.53 ------------ +DFS support added (Microsoft Distributed File System client support needed +for referrals which enable a hierarchical name space among servers). Version 1.52 ------------ diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 92c9feac440..5aff46c61e5 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -Version 1.52 January 3, 2008 +Version 1.53 May 20, 2008 A Partial List of Missing Features ================================== @@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in fs/cifs/connect.c and add back in NTLMSSP code if any servers need it -e) ms-dfs and ms-dfs host name resolution cleanup - -f) fix NTLMv2 signing when two mounts with different users to same +e) fix NTLMv2 signing when two mounts with different users to same server. -g) Directory entry caching relies on a 1 second timer, rather than +f) Directory entry caching relies on a 1 second timer, rather than using FindNotify or equivalent. - (started) -h) quota support (needs minor kernel change since quota calls +g) quota support (needs minor kernel change since quota calls to make it to network filesystems or deviceless filesystems) -i) investigate sync behavior (including syncpage) and check +h) investigate sync behavior (including syncpage) and check for proper behavior of intr/nointr +i) improve support for very old servers (OS/2 and Win9x for example) +Including support for changing the time remotely (utimes command). + j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the extra copy in/out of the socket buffers in some cases. diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9d9b56a9c08..422d4e219fa 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -161,77 +161,108 @@ static void cifs_unix_info_to_inode(struct inode *inode, spin_unlock(&inode->i_lock); } +static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, + struct super_block *sb) +{ + struct inode *pinode = NULL; + + memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); + +/* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); + __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); + __u64 UniqueId = 0; */ + pfnd_dat->LastStatusChange = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->LastAccessTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->LastModificationTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->Type = cpu_to_le32(UNIX_DIR); + pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); + pfnd_dat->Nlinks = cpu_to_le64(2); + if (sb->s_root) + pinode = sb->s_root->d_inode; + if (pinode == NULL) + return; + + /* fill in default values for the remaining based on root + inode since we can not query the server for this inode info */ + pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); + pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); + pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); + pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); +} + int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *full_path, struct super_block *sb, int xid) { int rc = 0; - FILE_UNIX_BASIC_INFO findData; + FILE_UNIX_BASIC_INFO find_data; struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); bool is_dfs_referral = false; + struct cifsInodeInfo *cifsInfo; + __u64 num_of_bytes; + __u64 end_of_file; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); -try_again_CIFSSMBUnixQPathInfo: /* could have done a find first instead but this returns more info */ - rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, + rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -/* dump_mem("\nUnixQPathInfo return data", &findData, - sizeof(findData)); */ if (rc) { if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; - goto try_again_CIFSSMBUnixQPathInfo; + cERROR(1, ("DFS ref")); /* BB removeme BB */ + /* for DFS, server does not give us real inode data */ + fill_fake_finddataunix(&find_data, sb); + rc = 0; } - goto cgiiu_exit; - } else { - struct cifsInodeInfo *cifsInfo; - __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); - __u64 end_of_file = le64_to_cpu(findData.EndOfFile); + } + num_of_bytes = le64_to_cpu(find_data.NumOfBytes); + end_of_file = le64_to_cpu(find_data.EndOfFile); - /* get new inode */ + /* get new inode */ + if (*pinode == NULL) { + *pinode = new_inode(sb); if (*pinode == NULL) { - *pinode = new_inode(sb); - if (*pinode == NULL) { - rc = -ENOMEM; - goto cgiiu_exit; - } - /* 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? */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - (*pinode)->i_ino = - (unsigned long)findData.UniqueId; - } /* note ino incremented to unique num in new_inode */ - if (sb->s_flags & MS_NOATIME) - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; - - insert_inode_hash(*pinode); + rc = -ENOMEM; + goto cgiiu_exit; } + /* Is an i_ino of zero legal? */ + /* note ino incremented to unique num in new_inode */ + /* Are there sanity checks we can use to ensure that + the server is really filling in that field? */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + (*pinode)->i_ino = (unsigned long)find_data.UniqueId; - inode = *pinode; - cifsInfo = CIFS_I(inode); + if (sb->s_flags & MS_NOATIME) + (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - /* this is ok to set on every inode revalidate */ - atomic_set(&cifsInfo->inUse, 1); + insert_inode_hash(*pinode); + } - cifs_unix_info_to_inode(inode, &findData, 0); + inode = *pinode; + cifsInfo = CIFS_I(inode); + cFYI(1, ("Old time %ld", cifsInfo->time)); + cifsInfo->time = jiffies; + cFYI(1, ("New time %ld", cifsInfo->time)); + /* this is ok to set on every inode revalidate */ + atomic_set(&cifsInfo->inUse, 1); - if (num_of_bytes < end_of_file) - cFYI(1, ("allocation size less than end of file")); - cFYI(1, ("Size %ld and blocks %llu", - (unsigned long) inode->i_size, - (unsigned long long)inode->i_blocks)); + cifs_unix_info_to_inode(inode, &find_data, 0); - cifs_set_ops(inode, is_dfs_referral); - } + if (num_of_bytes < end_of_file) + cFYI(1, ("allocation size less than end of file")); + cFYI(1, ("Size %ld and blocks %llu", + (unsigned long) inode->i_size, + (unsigned long long)inode->i_blocks)); + + cifs_set_ops(inode, is_dfs_referral); cgiiu_exit: return rc; } -- cgit v1.2.3-70-g09d2 From b9a3260f25ab5d2ba5c8b9508e7952848b9d704b Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 20 May 2008 21:52:32 +0000 Subject: [CIFS] Enable DFS support for Windows query path info Final piece for handling DFS in query_path_info, constructing a fake inode for the junction directory which the submount will cover. This handles the non-Unix (Windows etc.) code path. Signed-off-by: Steve French --- fs/cifs/inode.c | 324 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 178 insertions(+), 146 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 422d4e219fa..1cf43e10194 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -161,6 +161,12 @@ static void cifs_unix_info_to_inode(struct inode *inode, spin_unlock(&inode->i_lock); } + +/* + * Needed to setup inode data for the directory which is the + * junction to the new submount (ie to setup the fake directory + * which represents a DFS referral) + */ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, struct super_block *sb) { @@ -370,11 +376,42 @@ static int get_sfu_mode(struct inode *inode, #endif } +/* + * Needed to setup inode data for the directory which is the + * junction to the new submount (ie to setup the fake directory + * which represents a DFS referral) + */ +static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, + struct super_block *sb) +{ + memset(pfnd_dat, sizeof(FILE_ALL_INFO), 0); + +/* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); + __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); + __u8 pfnd_dat->DeletePending = 0; + __u8 pfnd_data->Directory = 0; + __le32 pfnd_dat->EASize = 0; + __u64 pfnd_dat->IndexNumber = 0; + __u64 pfnd_dat->IndexNumber1 = 0; */ + pfnd_dat->CreationTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->LastAccessTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->LastWriteTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->ChangeTime = + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); + pfnd_dat->NumberOfLinks = cpu_to_le32(2); +} + int cifs_get_inode_info(struct inode **pinode, const unsigned char *full_path, FILE_ALL_INFO *pfindData, struct super_block *sb, int xid, const __u16 *pfid) { int rc = 0; + __u32 attr; + struct cifsInodeInfo *cifsInfo; struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); @@ -399,7 +436,6 @@ int cifs_get_inode_info(struct inode **pinode, return -ENOMEM; pfindData = (FILE_ALL_INFO *)buf; -try_again_CIFSSMBQPathInfo: /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, 0 /* not legacy */, @@ -417,171 +453,167 @@ try_again_CIFSSMBQPathInfo: } } /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ - if (rc) { - if (rc == -EREMOTE && !is_dfs_referral) { - is_dfs_referral = true; - goto try_again_CIFSSMBQPathInfo; - } + if (rc == -EREMOTE) { + is_dfs_referral = true; + fill_fake_finddata(pfindData, sb); + rc = 0; + } else if (rc) goto cgii_exit; - } else { - struct cifsInodeInfo *cifsInfo; - __u32 attr = le32_to_cpu(pfindData->Attributes); - /* get new inode */ + attr = le32_to_cpu(pfindData->Attributes); + + /* get new inode */ + if (*pinode == NULL) { + *pinode = new_inode(sb); if (*pinode == NULL) { - *pinode = new_inode(sb); - if (*pinode == NULL) { - rc = -ENOMEM; - goto cgii_exit; - } - /* Is an i_ino of zero legal? Can we use that to check - if the server supports returning inode numbers? Are - there other sanity checks we can use to ensure that - the server is really filling in that field? */ + rc = -ENOMEM; + goto cgii_exit; + } + /* Is an i_ino of zero legal? Can we use that to check + if the server supports returning inode numbers? Are + there other sanity checks we can use to ensure that + the server is really filling in that field? */ - /* We can not use the IndexNumber field by default from - Windows or Samba (in ALL_INFO buf) but we can request - it explicitly. It may not be unique presumably if - the server has multiple devices mounted under one - share */ + /* We can not use the IndexNumber field by default from + Windows or Samba (in ALL_INFO buf) but we can request + it explicitly. It may not be unique presumably if + the server has multiple devices mounted under one share */ - /* There may be higher info levels that work but are - there Windows server or network appliances for which - IndexNumber field is not guaranteed unique? */ + /* There may be higher info levels that work but are + there Windows server or network appliances for which + IndexNumber field is not guaranteed unique? */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - int rc1 = 0; - __u64 inode_num; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + int rc1 = 0; + __u64 inode_num; - rc1 = CIFSGetSrvInodeNumber(xid, pTcon, + rc1 = CIFSGetSrvInodeNumber(xid, pTcon, full_path, &inode_num, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc1) { - cFYI(1, ("GetSrvInodeNum rc %d", rc1)); - /* BB EOPNOSUPP disable SERVER_INUM? */ - } else /* do we need cast or hash to ino? */ - (*pinode)->i_ino = inode_num; - } /* else ino incremented to unique num in new_inode*/ - if (sb->s_flags & MS_NOATIME) - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; - insert_inode_hash(*pinode); - } - inode = *pinode; - cifsInfo = CIFS_I(inode); - cifsInfo->cifsAttrs = attr; - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - - /* blksize needs to be multiple of two. So safer to default to - blksize and blkbits set in superblock so 2**blkbits and blksize - will match rather than setting to: - (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ - - /* Linux can not store file creation time so ignore it */ - if (pfindData->LastAccessTime) - inode->i_atime = cifs_NTtimeToUnix - (le64_to_cpu(pfindData->LastAccessTime)); - else /* do not need to use current_fs_time - time not stored */ - inode->i_atime = CURRENT_TIME; - inode->i_mtime = + if (rc1) { + cFYI(1, ("GetSrvInodeNum rc %d", rc1)); + /* BB EOPNOSUPP disable SERVER_INUM? */ + } else /* do we need cast or hash to ino? */ + (*pinode)->i_ino = inode_num; + } /* else ino incremented to unique num in new_inode*/ + if (sb->s_flags & MS_NOATIME) + (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; + insert_inode_hash(*pinode); + } + inode = *pinode; + cifsInfo = CIFS_I(inode); + cifsInfo->cifsAttrs = attr; + cFYI(1, ("Old time %ld", cifsInfo->time)); + cifsInfo->time = jiffies; + cFYI(1, ("New time %ld", cifsInfo->time)); + + /* blksize needs to be multiple of two. So safer to default to + blksize and blkbits set in superblock so 2**blkbits and blksize + will match rather than setting to: + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ + + /* Linux can not store file creation time so ignore it */ + if (pfindData->LastAccessTime) + inode->i_atime = cifs_NTtimeToUnix + (le64_to_cpu(pfindData->LastAccessTime)); + else /* do not need to use current_fs_time - time not stored */ + inode->i_atime = CURRENT_TIME; + inode->i_mtime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); - inode->i_ctime = - cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); - cFYI(0, ("Attributes came in as 0x%x", attr)); - if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { - inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; - inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; - } + inode->i_ctime = + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); + cFYI(DBG2, ("Attributes came in as 0x%x", attr)); + if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { + inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; + inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; + } - /* set default mode. will override for dirs below */ - if (atomic_read(&cifsInfo->inUse) == 0) - /* new inode, can safely set these fields */ - inode->i_mode = cifs_sb->mnt_file_mode; - else /* since we set the inode type below we need to mask off - to avoid strange results if type changes and both - get orred in */ - inode->i_mode &= ~S_IFMT; -/* if (attr & ATTR_REPARSE) */ - /* We no longer handle these as symlinks because we could not - follow them due to the absolute path with drive letter */ - if (attr & ATTR_DIRECTORY) { - /* override default perms since we do not do byte range locking - on dirs */ - inode->i_mode = cifs_sb->mnt_dir_mode; - inode->i_mode |= S_IFDIR; - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM) && - /* No need to le64 convert size of zero */ - (pfindData->EndOfFile == 0)) { - inode->i_mode = cifs_sb->mnt_file_mode; - inode->i_mode |= S_IFIFO; + /* set default mode. will override for dirs below */ + if (atomic_read(&cifsInfo->inUse) == 0) + /* new inode, can safely set these fields */ + inode->i_mode = cifs_sb->mnt_file_mode; + else /* since we set the inode type below we need to mask off + to avoid strange results if type changes and both + get orred in */ + inode->i_mode &= ~S_IFMT; +/* if (attr & ATTR_REPARSE) */ + /* We no longer handle these as symlinks because we could not + follow them due to the absolute path with drive letter */ + if (attr & ATTR_DIRECTORY) { + /* override default perms since we do not do byte range locking + on dirs */ + inode->i_mode = cifs_sb->mnt_dir_mode; + inode->i_mode |= S_IFDIR; + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (cifsInfo->cifsAttrs & ATTR_SYSTEM) && + /* No need to le64 convert size of zero */ + (pfindData->EndOfFile == 0)) { + inode->i_mode = cifs_sb->mnt_file_mode; + inode->i_mode |= S_IFIFO; /* BB Finish for SFU style symlinks and devices */ - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { - if (decode_sfu_inode(inode, - le64_to_cpu(pfindData->EndOfFile), - full_path, - cifs_sb, xid)) - cFYI(1, ("Unrecognized sfu inode type")); - - cFYI(1, ("sfu mode 0%o", inode->i_mode)); - } else { - inode->i_mode |= S_IFREG; - /* treat the dos attribute of read-only as read-only - mode e.g. 555 */ - if (cifsInfo->cifsAttrs & ATTR_READONLY) - inode->i_mode &= ~(S_IWUGO); - else if ((inode->i_mode & S_IWUGO) == 0) - /* the ATTR_READONLY flag may have been */ - /* changed on server -- set any w bits */ - /* allowed by mnt_file_mode */ - inode->i_mode |= (S_IWUGO & - cifs_sb->mnt_file_mode); - /* BB add code here - - validate if device or weird share or device type? */ - } + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { + if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), + full_path, cifs_sb, xid)) + cFYI(1, ("Unrecognized sfu inode type")); - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifsInfo, - le64_to_cpu(pfindData->EndOfFile))) { - /* can not safely shrink the file size here if the - client is writing to it due to potential races */ - i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); - - /* 512 bytes (2**9) is the fake blocksize that must be - used for this calculation */ - inode->i_blocks = (512 - 1 + le64_to_cpu( - pfindData->AllocationSize)) >> 9; - } - spin_unlock(&inode->i_lock); + cFYI(1, ("sfu mode 0%o", inode->i_mode)); + } else { + inode->i_mode |= S_IFREG; + /* treat dos attribute of read-only as read-only mode eg 555 */ + if (cifsInfo->cifsAttrs & ATTR_READONLY) + inode->i_mode &= ~(S_IWUGO); + else if ((inode->i_mode & S_IWUGO) == 0) + /* the ATTR_READONLY flag may have been */ + /* changed on server -- set any w bits */ + /* allowed by mnt_file_mode */ + inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); + /* BB add code to validate if device or weird share or device type? */ + } + + spin_lock(&inode->i_lock); + if (is_size_safe_to_change(cifsInfo, + le64_to_cpu(pfindData->EndOfFile))) { + /* can not safely shrink the file size here if the + client is writing to it due to potential races */ + i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); + + /* 512 bytes (2**9) is the fake blocksize that must be + used for this calculation */ + inode->i_blocks = (512 - 1 + le64_to_cpu( + pfindData->AllocationSize)) >> 9; + } + spin_unlock(&inode->i_lock); - inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); + inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); - /* BB fill in uid and gid here? with help from winbind? - or retrieve from NTFS stream extended attribute */ + /* BB fill in uid and gid here? with help from winbind? + or retrieve from NTFS stream extended attribute */ #ifdef CONFIG_CIFS_EXPERIMENTAL - /* fill in 0777 bits from ACL */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - cFYI(1, ("Getting mode bits from ACL")); - acl_to_uid_mode(inode, full_path, pfid); - } + /* fill in 0777 bits from ACL */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + cFYI(1, ("Getting mode bits from ACL")); + acl_to_uid_mode(inode, full_path, pfid); + } #endif - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - /* fill in remaining high mode bits e.g. SUID, VTX */ - get_sfu_mode(inode, full_path, cifs_sb, xid); - } else if (atomic_read(&cifsInfo->inUse) == 0) { - inode->i_uid = cifs_sb->mnt_uid; - inode->i_gid = cifs_sb->mnt_gid; - /* set so we do not keep refreshing these fields with - bad data after user has changed them in memory */ - atomic_set(&cifsInfo->inUse, 1); - } - - cifs_set_ops(inode, is_dfs_referral); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + /* fill in remaining high mode bits e.g. SUID, VTX */ + get_sfu_mode(inode, full_path, cifs_sb, xid); + } else if (atomic_read(&cifsInfo->inUse) == 0) { + inode->i_uid = cifs_sb->mnt_uid; + inode->i_gid = cifs_sb->mnt_gid; + /* set so we do not keep refreshing these fields with + bad data after user has changed them in memory */ + atomic_set(&cifsInfo->inUse, 1); } + + cifs_set_ops(inode, is_dfs_referral); + + + + cgii_exit: kfree(buf); return rc; -- cgit v1.2.3-70-g09d2 From 5651ced3ab196b5e7dc485c5777f210aa41e2d8d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 20 May 2008 13:02:01 +0400 Subject: Fix possible access to undefined memory region. Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/dns_resolve.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 939e256f849..f730ef35499 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -134,10 +134,6 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) rkey = request_key(&key_type_dns_resolver, name, ""); if (!IS_ERR(rkey)) { data = rkey->payload.data; - cFYI(1, ("%s: resolved: %s to %s", __func__, - rkey->description, - *ip_addr - )); } else { cERROR(1, ("%s: unable to resolve: %s", __func__, name)); goto out; @@ -150,6 +146,11 @@ skip_upcall: if (*ip_addr) { memcpy(*ip_addr, data, len); (*ip_addr)[len] = '\0'; + if (!IS_ERR(rkey)) + cFYI(1, ("%s: resolved: %s to %s", __func__, + name, + *ip_addr + )); rc = 0; } else { rc = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 397d71ddfda5b11b85e396d6ea822011c132b962 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 21 May 2008 03:49:46 +0000 Subject: [CIFS] Remove debug statement Signed-off-by: Steve French --- fs/cifs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1cf43e10194..00ced97bd53 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -222,7 +222,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, if (rc) { if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; - cERROR(1, ("DFS ref")); /* BB removeme BB */ + cFYI(DBG2, ("DFS ref")); /* for DFS, server does not give us real inode data */ fill_fake_finddataunix(&find_data, sb); rc = 0; -- cgit v1.2.3-70-g09d2 From 0d817bc0d6cdd92ff1ab2e98dd5878659a48659c Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 22 May 2008 02:02:03 +0000 Subject: [CIFS] Remove redundant NULL check Noticed by Coverity checker. Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7b9938445b0..9b8b4cfdf99 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2159,8 +2159,7 @@ copyRetry: cFYI(1, ("Send error in copy = %d with %d files copied", rc, le16_to_cpu(pSMBr->CopyCount))); } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto copyRetry; @@ -2249,8 +2248,7 @@ createSymLinkRetry: if (rc) cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto createSymLinkRetry; @@ -4095,8 +4093,7 @@ getDFSRetry: target_nodes, nls_codepage); GetDFSRefExit: - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto getDFSRetry; @@ -5117,8 +5114,7 @@ setPermsRetry: if (rc) cFYI(1, ("SetPathInfo (perms) returned %d", rc)); - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto setPermsRetry; return rc; @@ -5340,8 +5336,7 @@ QAllEAsRetry: } } } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto QAllEAsRetry; @@ -5490,8 +5485,7 @@ QEARetry: } } } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto QEARetry; -- cgit v1.2.3-70-g09d2 From e4058245ac0c4d9a517cda688a35aef065cb7f4e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 2 Apr 2008 17:33:47 +0400 Subject: Adds username in the upcall key for unattended mounts with keytab Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifs_spnego.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 6653e29637a..7013aaff6ae 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -119,6 +119,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); + dp = description + strlen(description); + sprintf(dp, ";user=%s", sesInfo->userName); + cFYI(1, ("key description = %s", description)); spnego_key = request_key(&cifs_spnego_key_type, description, ""); -- cgit v1.2.3-70-g09d2 From 0a891adccc867c28b022128bc342a779e476c816 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 22 May 2008 14:20:21 +0000 Subject: [CIFS] Fix reversed memset arguments Signed-off-by: Dave Jones Signed-off-by: Steve French --- fs/cifs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 00ced97bd53..129dbfe4dca 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -172,7 +172,7 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, { struct inode *pinode = NULL; - memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); + memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); @@ -384,7 +384,7 @@ static int get_sfu_mode(struct inode *inode, static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, struct super_block *sb) { - memset(pfnd_dat, sizeof(FILE_ALL_INFO), 0); + memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); -- cgit v1.2.3-70-g09d2 From aaa9bbe039febf1d3a0f3a374deea0680d9f5758 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 23 May 2008 17:38:32 +0000 Subject: [CIFS] remove unused variables CC: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 3 +-- fs/cifs/cifssmb.c | 6 ++---- fs/cifs/file.c | 7 ------- fs/cifs/misc.c | 3 +-- fs/cifs/readdir.c | 6 +----- 5 files changed, 5 insertions(+), 20 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 08914053242..9cfcf326ead 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -333,7 +333,6 @@ struct cifsFileInfo { bool messageMode:1; /* for pipes: message vs byte mode */ atomic_t wrtPending; /* handle in use - defer close */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ - char *search_resume_name; /* BB removeme BB */ struct cifs_search_info srch_inf; }; @@ -626,7 +625,7 @@ GLOBAL_EXTERN atomic_t tcpSesAllocCount; GLOBAL_EXTERN atomic_t tcpSesReconnectCount; GLOBAL_EXTERN atomic_t tconInfoReconnectCount; -/* Various Debug counters to remove someday (BB) */ +/* Various Debug counters */ GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ #ifdef CONFIG_CIFS_STATS2 GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9b8b4cfdf99..174bf8aca23 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1728,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, { int rc = 0; LOCK_REQ *pSMB = NULL; - LOCK_RSP *pSMBr = NULL; +/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ int bytes_returned; int timeout = 0; __u16 count; @@ -1739,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (rc) return rc; - pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ - if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { timeout = CIFS_ASYNC_OP; /* no response expected */ pSMB->Timeout = 0; @@ -1774,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (waitFlag) { rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); + (struct smb_hdr *) pSMB, &bytes_returned); cifs_small_buf_release(pSMB); } else { rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8636cec2642..0aac824371a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -546,7 +546,6 @@ int cifs_close(struct inode *inode, struct file *file) msleep(timeout); timeout *= 8; } - kfree(pSMBFile->search_resume_name); kfree(file->private_data); file->private_data = NULL; } else @@ -605,12 +604,6 @@ int cifs_closedir(struct inode *inode, struct file *file) else cifs_buf_release(ptmp); } - ptmp = pCFileStruct->search_resume_name; - if (ptmp) { - cFYI(1, ("closedir free resume name")); - pCFileStruct->search_resume_name = NULL; - kfree(ptmp); - } kfree(file->private_data); file->private_data = NULL; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1d69b8014e0..4b17f8fe315 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -519,8 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) pnotify = (struct file_notify_information *) ((char *)&pSMBr->hdr.Protocol + data_offset); cFYI(1, ("dnotify on %s Action: 0x%x", - pnotify->FileName, - pnotify->Action)); /* BB removeme BB */ + pnotify->FileName, pnotify->Action)); /* cifs_dump_mem("Rcvd notify Data: ",buf, sizeof(struct smb_hdr)+60); */ return true; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 713c2511019..df2c3c466ee 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -675,8 +675,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); } - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = NULL; if (cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1, ("freeing SMB ff cache buf on search rewind")); if (cifsFile->srch_inf.smallBuf) @@ -1043,9 +1041,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) } /* else { cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); - } - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = NULL; */ + } */ rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); -- cgit v1.2.3-70-g09d2 From 4468eb3fd102cad559e51594a01cbc65b994d264 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 22 May 2008 09:31:40 -0400 Subject: on non-posix shares, clear write bits in mode when ATTR_READONLY is set When mounting a share with posix extensions disabled, cifs_get_inode_info turns off all the write bits in the mode for regular files if ATTR_READONLY is set. Directories and other inode types, however, can also have ATTR_READONLY set, but the mode gives no indication of this. This patch makes this apply to other inode types besides regular files. It also cleans up how modes are set in cifs_get_inode_info for both the "normal" and "dynperm" cases. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 76 ++++++++++++++++++++++++++----------------------------- fs/cifs/readdir.c | 71 ++++++++++++++++++++++++++++----------------------- 2 files changed, 75 insertions(+), 72 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 129dbfe4dca..ae5bcaf2031 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode, char *buf = NULL; bool adjustTZ = false; bool is_dfs_referral = false; + umode_t default_mode; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); @@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode, inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; } - /* set default mode. will override for dirs below */ - if (atomic_read(&cifsInfo->inUse) == 0) - /* new inode, can safely set these fields */ - inode->i_mode = cifs_sb->mnt_file_mode; - else /* since we set the inode type below we need to mask off - to avoid strange results if type changes and both - get orred in */ - inode->i_mode &= ~S_IFMT; -/* if (attr & ATTR_REPARSE) */ - /* We no longer handle these as symlinks because we could not - follow them due to the absolute path with drive letter */ - if (attr & ATTR_DIRECTORY) { - /* override default perms since we do not do byte range locking - on dirs */ - inode->i_mode = cifs_sb->mnt_dir_mode; - inode->i_mode |= S_IFDIR; - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM) && - /* No need to le64 convert size of zero */ - (pfindData->EndOfFile == 0)) { - inode->i_mode = cifs_sb->mnt_file_mode; - inode->i_mode |= S_IFIFO; -/* BB Finish for SFU style symlinks and devices */ - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { - if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), - full_path, cifs_sb, xid)) - cFYI(1, ("Unrecognized sfu inode type")); - - cFYI(1, ("sfu mode 0%o", inode->i_mode)); + /* get default inode mode */ + if (attr & ATTR_DIRECTORY) + default_mode = cifs_sb->mnt_dir_mode; + else + default_mode = cifs_sb->mnt_file_mode; + + /* set permission bits */ + if (atomic_read(&cifsInfo->inUse) == 0 || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + inode->i_mode = default_mode; + else { + /* just reenable write bits if !ATTR_READONLY */ + if ((inode->i_mode & S_IWUGO) == 0 && + (attr & ATTR_READONLY) == 0) + inode->i_mode |= (S_IWUGO & default_mode); + inode->i_mode &= ~S_IFMT; + } + /* clear write bits if ATTR_READONLY is set */ + if (attr & ATTR_READONLY) + inode->i_mode &= ~S_IWUGO; + + /* set inode type */ + if ((attr & ATTR_SYSTEM) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { + /* no need to fix endianness on 0 */ + if (pfindData->EndOfFile == 0) + inode->i_mode |= S_IFIFO; + else if (decode_sfu_inode(inode, + le64_to_cpu(pfindData->EndOfFile), + full_path, cifs_sb, xid)) + cFYI(1, ("unknown SFU file type\n")); } else { - inode->i_mode |= S_IFREG; - /* treat dos attribute of read-only as read-only mode eg 555 */ - if (cifsInfo->cifsAttrs & ATTR_READONLY) - inode->i_mode &= ~(S_IWUGO); - else if ((inode->i_mode & S_IWUGO) == 0) - /* the ATTR_READONLY flag may have been */ - /* changed on server -- set any w bits */ - /* allowed by mnt_file_mode */ - inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); - /* BB add code to validate if device or weird share or device type? */ + if (attr & ATTR_DIRECTORY) + inode->i_mode |= S_IFDIR; + else + inode->i_mode |= S_IFREG; } spin_lock(&inode->i_lock); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index df2c3c466ee..83f30695488 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, __u32 attr; __u64 allocation_size; __u64 end_of_file; + umode_t default_mode; /* save mtime and size */ local_mtime = tmp_inode->i_mtime; @@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, if (atomic_read(&cifsInfo->inUse) == 0) { tmp_inode->i_uid = cifs_sb->mnt_uid; tmp_inode->i_gid = cifs_sb->mnt_gid; - /* set default mode. will override for dirs below */ - tmp_inode->i_mode = cifs_sb->mnt_file_mode; - } else { - /* mask off the type bits since it gets set - below and we do not want to get two type - bits set */ + } + + if (attr & ATTR_DIRECTORY) + default_mode = cifs_sb->mnt_dir_mode; + else + default_mode = cifs_sb->mnt_file_mode; + + /* set initial permissions */ + if ((atomic_read(&cifsInfo->inUse) == 0) || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + tmp_inode->i_mode = default_mode; + else { + /* just reenable write bits if !ATTR_READONLY */ + if ((tmp_inode->i_mode & S_IWUGO) == 0 && + (attr & ATTR_READONLY) == 0) + tmp_inode->i_mode |= (S_IWUGO & default_mode); + tmp_inode->i_mode &= ~S_IFMT; } - if (attr & ATTR_DIRECTORY) { - *pobject_type = DT_DIR; - /* override default perms since we do not lock dirs */ - if (atomic_read(&cifsInfo->inUse) == 0) - tmp_inode->i_mode = cifs_sb->mnt_dir_mode; - tmp_inode->i_mode |= S_IFDIR; - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (attr & ATTR_SYSTEM)) { + /* clear write bits if ATTR_READONLY is set */ + if (attr & ATTR_READONLY) + tmp_inode->i_mode &= ~S_IWUGO; + + /* set inode type */ + if ((attr & ATTR_SYSTEM) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { if (end_of_file == 0) { - *pobject_type = DT_FIFO; tmp_inode->i_mode |= S_IFIFO; + *pobject_type = DT_FIFO; } else { - /* rather than get the type here, we mark the - inode as needing revalidate and get the real type - (blk vs chr vs. symlink) later ie in lookup */ - *pobject_type = DT_REG; + /* + * trying to get the type can be slow, so just call + * this a regular file for now, and mark for reval + */ tmp_inode->i_mode |= S_IFREG; + *pobject_type = DT_REG; cifsInfo->time = 0; } -/* we no longer mark these because we could not follow them */ -/* } else if (attr & ATTR_REPARSE) { - *pobject_type = DT_LNK; - tmp_inode->i_mode |= S_IFLNK; */ } else { - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - if (attr & ATTR_READONLY) - tmp_inode->i_mode &= ~(S_IWUGO); - else if ((tmp_inode->i_mode & S_IWUGO) == 0) - /* the ATTR_READONLY flag may have been changed on */ - /* server -- set any w bits allowed by mnt_file_mode */ - tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); - } /* could add code here - to validate if device or weird share type? */ + if (attr & ATTR_DIRECTORY) { + tmp_inode->i_mode |= S_IFDIR; + *pobject_type = DT_DIR; + } else { + tmp_inode->i_mode |= S_IFREG; + *pobject_type = DT_REG; + } + } /* can not fill in nlink here as in qpathinfo version and Unx search */ if (atomic_read(&cifsInfo->inUse) == 0) -- cgit v1.2.3-70-g09d2 From b0fd30d3e7e768aad5e398caaea6ae5a5c814eab Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 22 May 2008 09:33:34 -0400 Subject: when creating new inodes, use file_mode/dir_mode exclusively on mount without unix extensions When CIFS creates a new inode on a mount without unix extensions, it temporarily assigns the mode that was passed to it in the create/mkdir call. Eventually, when the inode is revalidated, it changes to have the file_mode or dir_mode for the mount. This is confusing to users who expect that the mode shouldn't change this way. It's also problematic since only the mode is treated this way, not the uid or gid. Suppose you have a CIFS mount that's mounted with: uid=0,gid=0,file_mode=0666,dir_mode=0777 ...if an unprivileged user comes along and does this on the mount: mkdir -m 0700 foo touch foo/bar ...there is a period of time where the touch will fail, since the dir will initially be owned by root and have mode 0700. If the user waits long enough, then "foo" will be revalidated and will get the correct dir_mode permissions. This patch changes cifs_mkdir and cifs_create to not overwrite the mode found by the initial cifs_get_inode_info call after the inode is created on the server. Legacy behavior can be reenabled with the new "dynperm" mount option. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/dir.c | 4 +++- fs/cifs/inode.c | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f0b5b5f3dd2..fb69c1fa85c 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -260,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, buf, inode->i_sb, xid, &fileHandle); if (newinode) { - newinode->i_mode = mode; + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_DYNPERM) + newinode->i_mode = mode; if ((oplock & CIFS_CREATE_ACTION) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ae5bcaf2031..12667d6bf30 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1015,8 +1015,11 @@ mkdir_get_info: CIFS_MOUNT_MAP_SPECIAL_CHR); } if (direntry->d_inode) { - direntry->d_inode->i_mode = mode; - direntry->d_inode->i_mode |= S_IFDIR; + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_DYNPERM) + direntry->d_inode->i_mode = + (mode | S_IFDIR); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { direntry->d_inode->i_uid = -- cgit v1.2.3-70-g09d2 From 4e94a105ed0df78e25b20ff8ed6761f5937662b1 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 23 May 2008 18:22:46 +0000 Subject: [CIFS] remove trailing whitespace Signed-off-by: Steve French --- fs/cifs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 12667d6bf30..ae6b725b366 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1019,7 +1019,7 @@ mkdir_get_info: CIFS_MOUNT_DYNPERM) direntry->d_inode->i_mode = (mode | S_IFDIR); - + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { direntry->d_inode->i_uid = -- cgit v1.2.3-70-g09d2 From 4ca691a892e8ab4f79583de1394f17a7dcfa2b57 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 22 May 2008 09:33:34 -0400 Subject: silently ignore ownership changes unless unix extensions are enabled or we're faking uid changes CIFS currently allows you to change the ownership of a file, but unless unix extensions are enabled this change is not passed off to the server. Have CIFS silently ignore ownership changes that can't be persistently stored on the server unless the "setuids" option is explicitly specified. We could return an error here (-EOPNOTSUPP or something), but this is how most disk-based windows filesystems on behave on Linux (e.g. VFAT, NTFS, etc). With cifsacl support and proper Windows to Unix idmapping support, we may be able to do this more properly in the future. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ae6b725b366..fe752fdb26c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1546,13 +1546,26 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) } else goto cifs_setattr_exit; } - if (attrs->ia_valid & ATTR_UID) { - cFYI(1, ("UID changed to %d", attrs->ia_uid)); - uid = attrs->ia_uid; - } - if (attrs->ia_valid & ATTR_GID) { - cFYI(1, ("GID changed to %d", attrs->ia_gid)); - gid = attrs->ia_gid; + + /* + * Without unix extensions we can't send ownership changes to the + * server, so silently ignore them. This is consistent with how + * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With + * CIFSACL support + proper Windows to Unix idmapping, we may be + * able to support this in the future. + */ + if (!pTcon->unix_ext && + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { + attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); + } else { + if (attrs->ia_valid & ATTR_UID) { + cFYI(1, ("UID changed to %d", attrs->ia_uid)); + uid = attrs->ia_uid; + } + if (attrs->ia_valid & ATTR_GID) { + cFYI(1, ("GID changed to %d", attrs->ia_gid)); + gid = attrs->ia_gid; + } } time_buf.Attributes = 0; -- cgit v1.2.3-70-g09d2 From 27adb44c4f671d15932eb0702a09d27244a8a7c1 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 23 May 2008 19:43:29 +0000 Subject: [CIFS] warn if both dynperm and cifsacl mount options specified Signed-off-by: Steve French --- fs/cifs/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 023434f72c1..d49e274f8eb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2120,6 +2120,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; } + if ((volume_info.cifs_acl) && (volume_info.dynperm)) + cERROR(1, ("mount option dynperm ignored if cifsacl " + "mount option supported")); + tcon = find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, volume_info.username); -- cgit v1.2.3-70-g09d2 From b7206153f61bb63ee2cffa63905b57ec01d20e6e Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 23 May 2008 20:35:07 +0000 Subject: [CIFS] Correct incorrect obscure open flag Also add defines for pipe subcommand codes Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 65d58b4e6a6..0f327c224da 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -79,6 +79,19 @@ #define TRANS2_GET_DFS_REFERRAL 0x10 #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 +/* SMB Transact (Named Pipe) subcommand codes */ +#define TRANS_SET_NMPIPE_STATE 0x0001 +#define TRANS_RAW_READ_NMPIPE 0x0011 +#define TRANS_QUERY_NMPIPE_STATE 0x0021 +#define TRANS_QUERY_NMPIPE_INFO 0x0022 +#define TRANS_PEEK_NMPIPE 0x0023 +#define TRANS_TRANSACT_NMPIPE 0x0026 +#define TRANS_RAW_WRITE_NMPIPE 0x0031 +#define TRANS_READ_NMPIPE 0x0036 +#define TRANS_WRITE_NMPIPE 0x0037 +#define TRANS_WAIT_NMPIPE 0x0053 +#define TRANS_CALL_NMPIPE 0x0054 + /* NT Transact subcommand codes */ #define NT_TRANSACT_CREATE 0x01 #define NT_TRANSACT_IOCTL 0x02 @@ -328,12 +341,13 @@ #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ #define CREATE_NO_EA_KNOWLEDGE 0x00000200 #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete - open for recovery flag - should - be zero */ + "open for recovery" flag - should + be zero in any case */ +#define CREATE_OPEN_FOR_RECOVERY 0x00000400 #define CREATE_RANDOM_ACCESS 0x00000800 #define CREATE_DELETE_ON_CLOSE 0x00001000 #define CREATE_OPEN_BY_ID 0x00002000 -#define CREATE_OPEN_BACKUP_INTN 0x00004000 +#define CREATE_OPEN_BACKUP_INTENT 0x00004000 #define CREATE_NO_COMPRESSION 0x00008000 #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ #define OPEN_REPARSE_POINT 0x00200000 @@ -722,7 +736,6 @@ typedef struct smb_com_tconx_rsp_ext { #define SMB_CSC_CACHE_AUTO_REINT 0x0004 #define SMB_CSC_CACHE_VDO 0x0008 #define SMB_CSC_NO_CACHING 0x000C - #define SMB_UNIQUE_FILE_NAME 0x0010 #define SMB_EXTENDED_SIGNATURES 0x0020 @@ -806,7 +819,7 @@ typedef struct smb_com_findclose_req { #define ICOUNT_MASK 0x00FF #define PIPE_READ_MODE 0x0100 #define NAMED_PIPE_TYPE 0x0400 -#define PIPE_END_POINT 0x0800 +#define PIPE_END_POINT 0x4000 #define BLOCKING_NAMED_PIPE 0x8000 typedef struct smb_com_open_req { /* also handles create */ -- cgit v1.2.3-70-g09d2 From 5132861a7a44498ebb18357473f8b8d4cdc70e9f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 22 May 2008 09:33:34 -0400 Subject: disable most mode changes on non-unix/non-cifsacl mounts CIFS currently allows you to change the mode of an inode on a share that doesn't have unix extensions enabled, and isn't using cifsacl. The inode in this case *only* has its mode changed in memory on the client. This is problematic since it can change any time the inode is purged from the cache. This patch makes cifs_setattr silently ignore most mode changes when unix extensions and cifsacl support are not enabled, and when the share is not mounted with the "dynperm" option. The exceptions are: When a mode change would remove all write access to an inode we turn on the ATTR_READONLY bit on the server and remove all write bits from the inode's mode in memory. When a mode change would add a write bit to an inode that previously had them all turned off, it turns off the ATTR_READONLY bit on the server, and resets the mode back to what it would normally be (generally, the file_mode or dir_mode of the share). Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fe752fdb26c..722be543cee 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1575,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) attrs->ia_valid &= ~ATTR_MODE; if (attrs->ia_valid & ATTR_MODE) { - cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); + cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); mode = attrs->ia_mode; } @@ -1590,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) rc = mode_to_acl(inode, full_path, mode); - else if ((mode & S_IWUGO) == 0) { -#else - if ((mode & S_IWUGO) == 0) { + else #endif - /* not writeable */ - if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { - set_dosattr = true; - time_buf.Attributes = - cpu_to_le32(cifsInode->cifsAttrs | - ATTR_READONLY); - } - } else if (cifsInode->cifsAttrs & ATTR_READONLY) { + if (((mode & S_IWUGO) == 0) && + (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { + set_dosattr = true; + time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | + ATTR_READONLY); + /* fix up mode if we're not using dynperm */ + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + attrs->ia_mode = inode->i_mode & ~S_IWUGO; + } else if ((mode & S_IWUGO) && + (cifsInode->cifsAttrs & ATTR_READONLY)) { /* If file is readonly on server, we would not be able to write to it - so if any write bit is enabled for user or group or other we @@ -1612,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) /* Windows ignores set to zero */ if (time_buf.Attributes == 0) time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); + + /* reset local inode permissions to normal */ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { + attrs->ia_mode &= ~(S_IALLUGO); + if (S_ISDIR(inode->i_mode)) + attrs->ia_mode |= + cifs_sb->mnt_dir_mode; + else + attrs->ia_mode |= + cifs_sb->mnt_file_mode; + } + } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { + /* ignore mode change - ATTR_READONLY hasn't changed */ + attrs->ia_valid &= ~ATTR_MODE; } } -- cgit v1.2.3-70-g09d2 From 1d92cfd54a51ff1b9593019fdde56793b66ba6a9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 2 Jun 2008 10:59:02 +0100 Subject: cifs endianness fixes __le16 fields used as host-endian. Signed-off-by: Al Viro Acked-by: Steve French Signed-off-by: Linus Torvalds --- fs/cifs/cifssmb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9b8b4cfdf99..fb655b4593c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3927,9 +3927,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, } ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); - if (ref->VersionNumber != 3) { + if (ref->VersionNumber != cpu_to_le16(3)) { cERROR(1, ("Referrals of V%d version are not supported," - "should be V3", ref->VersionNumber)); + "should be V3", le16_to_cpu(ref->VersionNumber))); rc = -EINVAL; goto parse_DFS_referrals_exit; } @@ -3977,7 +3977,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, if (rc) goto parse_DFS_referrals_exit; - ref += ref->Size; + ref += le16_to_cpu(ref->Size); } parse_DFS_referrals_exit: -- cgit v1.2.3-70-g09d2 From ddb2c43594f22843e9f3153da151deaba1a834c5 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 4 Jun 2008 09:16:33 -0700 Subject: asn1: additional sanity checking during BER decoding - Don't trust a length which is greater than the working buffer. An invalid length could cause overflow when calculating buffer size for decoding oid. - An oid length of zero is invalid and allows for an off-by-one error when decoding oid because the first subid actually encodes first 2 subids. - A primitive encoding may not have an indefinite length. Thanks to Wei Wang from McAfee for report. Cc: Steven French Cc: stable@kernel.org Acked-by: Patrick McHardy Signed-off-by: Chris Wright Signed-off-by: Linus Torvalds --- fs/cifs/asn1.c | 14 ++++++++++++++ net/ipv4/netfilter/nf_nat_snmp_basic.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index cb52cbbe45f..f58e41d3ba4 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -186,6 +186,11 @@ asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) } } } + + /* don't trust len bigger than ctx buffer */ + if (*len > ctx->end - ctx->pointer) + return 0; + return 1; } @@ -203,6 +208,10 @@ asn1_header_decode(struct asn1_ctx *ctx, if (!asn1_length_decode(ctx, &def, &len)) return 0; + /* primitive shall be definite, indefinite shall be constructed */ + if (*con == ASN1_PRI && !def) + return 0; + if (def) *eoc = ctx->pointer + len; else @@ -389,6 +398,11 @@ asn1_oid_decode(struct asn1_ctx *ctx, unsigned long *optr; size = eoc - ctx->pointer + 1; + + /* first subid actually encodes first two subids */ + if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) + return 0; + *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); if (*oid == NULL) return 0; diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 5daefad3d19..7750c97fde7 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -232,6 +232,11 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx, } } } + + /* don't trust len bigger than ctx buffer */ + if (*len > ctx->end - ctx->pointer) + return 0; + return 1; } @@ -250,6 +255,10 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx, if (!asn1_length_decode(ctx, &def, &len)) return 0; + /* primitive shall be definite, indefinite shall be constructed */ + if (*con == ASN1_PRI && !def) + return 0; + if (def) *eoc = ctx->pointer + len; else @@ -434,6 +443,11 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx, unsigned long *optr; size = eoc - ctx->pointer + 1; + + /* first subid actually encodes first two subids */ + if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) + return 0; + *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); if (*oid == NULL) { if (net_ratelimit()) -- cgit v1.2.3-70-g09d2 From dbdbb87636e882042cbe53d5d4eac94206f8db83 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 10 Jun 2008 21:21:56 +0000 Subject: [CIFS] Fix hang in mount when negprot causes server to kill tcp session Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 5 +++++ fs/cifs/connect.c | 1 + 2 files changed, 6 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 28e3d5c5fca..1f3465201fd 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -2,6 +2,11 @@ Version 1.53 ------------ DFS support added (Microsoft Distributed File System client support needed for referrals which enable a hierarchical name space among servers). +Disable temporary caching of mode bits to servers which do not support +storing of mode (e.g. Windows servers, when client mounts without cifsacl +mount option) and add new "dynperm" mount option to enable temporary caching +of mode (enable old behavior). Fix hang on mount caused when server crashes +tcp session during negotiate protocol. Version 1.52 ------------ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d49e274f8eb..e8fa46c7cff 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -653,6 +653,7 @@ multi_t2_fnd: spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); + wake_up_all(&server->response_q); /* don't exit until kthread_stop is called */ set_current_state(TASK_UNINTERRUPTIBLE); -- cgit v1.2.3-70-g09d2 From 79ee9a8b2d328243488fee8b55bfacc822049a2a Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 10 Jun 2008 21:37:02 +0000 Subject: [CIFS] cifs: fix oops on mount when CONFIG_CIFS_DFS_UPCALL is enabled simple "mount -t cifs //xxx /mnt" oopsed on strlen of options http://kerneloops.org/guilty.php?guilty=cifs_get_sb&version=2.6.25-release&start=16711 \ 68&end=1703935&class=oops Signed-off-by: Marcin Slusarz Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5df93fd6303..86b4d5f405a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -97,9 +97,6 @@ cifs_read_super(struct super_block *sb, void *data, { struct inode *inode; struct cifs_sb_info *cifs_sb; -#ifdef CONFIG_CIFS_DFS_UPCALL - int len; -#endif int rc = 0; /* BB should we make this contingent on mount parm? */ @@ -117,15 +114,17 @@ cifs_read_super(struct super_block *sb, void *data, * complex operation (mount), and in case of fail * just exit instead of doing mount and attempting * undo it if this copy fails?*/ - len = strlen(data); - cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); - if (cifs_sb->mountdata == NULL) { - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - return -ENOMEM; + if (data) { + int len = strlen(data); + cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); + if (cifs_sb->mountdata == NULL) { + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; + } + strncpy(cifs_sb->mountdata, data, len + 1); + cifs_sb->mountdata[len] = '\0'; } - strncpy(cifs_sb->mountdata, data, len + 1); - cifs_sb->mountdata[len] = '\0'; #endif rc = cifs_mount(sb, cifs_sb, data, devname); -- cgit v1.2.3-70-g09d2