From ebe2e91e000c59aed0300d81815f451c85e0bda6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 10 Nov 2010 10:19:10 -0500 Subject: cifs: fix potential use-after-free in cifs_oplock_break_put cfile may very well be freed after the cifsFileInfo_put. Make sure we have a valid pointer to the superblock for cifs_sb_deactive. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06c3e83..b857ce5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2271,8 +2271,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile) void cifs_oplock_break_put(struct cifsFileInfo *cfile) { + struct super_block *sb = cfile->dentry->d_sb; + cifsFileInfo_put(cfile); - cifs_sb_deactive(cfile->dentry->d_sb); + cifs_sb_deactive(sb); } const struct address_space_operations cifs_addr_ops = { -- cgit v1.1 From a7851ce73b9fdef53f251420e6883cf4f3766534 Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Wed, 10 Nov 2010 21:06:13 +0000 Subject: cifs: fix another memleak, in cifs_root_iget cifs_root_iget allocates full_path through cifs_build_path_to_root, but fails to kfree it upon cifs_get_inode_info* failure. Make all failure exit paths traverse clean up handling at the end of the function. Signed-off-by: Oskar Schirmer Reviewed-by: Jesper Juhl Cc: stable@kernel.org Signed-off-by: Steve French --- fs/cifs/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ef3a55b..ff7d299 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -881,8 +881,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - if (!inode) - return ERR_PTR(rc); + if (!inode) { + inode = ERR_PTR(rc); + goto out; + } #ifdef CONFIG_CIFS_FSCACHE /* populate tcon->resource_id */ @@ -898,13 +900,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; } else if (rc) { - kfree(full_path); - _FreeXid(xid); iget_failed(inode); - return ERR_PTR(rc); + inode = ERR_PTR(rc); } - +out: kfree(full_path); /* can not call macro FreeXid here since in a void func * TODO: This is no longer true -- cgit v1.1 From 987b21d7d91d0335e164a41a312174851c58f333 Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar Date: Wed, 10 Nov 2010 07:50:35 -0600 Subject: cifs: Percolate error up to the caller during get/set acls [try #4] Modify get/set_cifs_acl* calls to reutrn error code and percolate the error code up to the caller. Signed-off-by: Shirish Pargaonkar Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 44 ++++++++++++++++++++++++++------------------ fs/cifs/cifsproto.h | 2 +- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c9b4792..91992ab 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -560,7 +560,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) - return NULL; + return ERR_CAST(tlink); xid = GetXid(); rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); @@ -568,7 +568,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, cifs_put_tlink(tlink); - cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); + cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); + if (rc) + return ERR_PTR(rc); return pntsd; } @@ -583,7 +585,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) - return NULL; + return ERR_CAST(tlink); tcon = tlink_tcon(tlink); xid = GetXid(); @@ -591,18 +593,17 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, &fid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) { - cERROR(1, "Unable to open file to get ACL"); - goto out; + if (!rc) { + rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); + CIFSSMBClose(xid, tcon, fid); } - rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); - cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); - - CIFSSMBClose(xid, tcon, fid); - out: cifs_put_tlink(tlink); FreeXid(xid); + + cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); + if (rc) + return ERR_PTR(rc); return pntsd; } @@ -695,7 +696,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, } /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ -void +int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid) { @@ -711,13 +712,17 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ - if (pntsd) + if (IS_ERR(pntsd)) { + rc = PTR_ERR(pntsd); + cERROR(1, "%s: error %d getting sec desc", __func__, rc); + } else { rc = parse_sec_desc(pntsd, acllen, fattr); - if (rc) - cFYI(1, "parse sec desc failed rc = %d", rc); + kfree(pntsd); + if (rc) + cERROR(1, "parse sec desc failed rc = %d", rc); + } - kfree(pntsd); - return; + return rc; } /* Convert mode bits to an ACL so we can update the ACL on the server */ @@ -736,7 +741,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) /* Add three ACEs for owner, group, everyone getting rid of other ACEs as chmod disables ACEs and set the security descriptor */ - if (pntsd) { + if (IS_ERR(pntsd)) { + rc = PTR_ERR(pntsd); + cERROR(1, "%s: error %d getting sec desc", __func__, rc); + } else { /* allocate memory for the smb header, set security descriptor request security descriptor parameters, and secuirty descriptor itself */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7ed69b6b..6ed59af 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -130,7 +130,7 @@ extern int cifs_get_file_info_unix(struct file *filp); extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid); -extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, +extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid); extern int mode_to_acl(struct inode *inode, const char *path, __u64); -- cgit v1.1 From 59c55ba1fba61ae13fbfff094a674e73407201f1 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 12 Nov 2010 06:30:29 -0500 Subject: cifs: don't take extra tlink reference in initiate_cifs_search It's possible for initiate_cifs_search to be called on a filp that already has private_data attached. If this happens, we'll end up calling cifs_sb_tlink, taking an extra reference to the tlink and attaching that to the cifsFileInfo. This leads to refcount leaks that manifest as a "stuck" cifsd at umount time. Fix this by only looking up the tlink for the cifsFile on the filp's first pass through this function. When called on a filp that already has cifsFileInfo associated with it, just use the tlink reference that it already owns. This patch fixes samba.org bug 7792: https://bugzilla.samba.org/show_bug.cgi?id=7792 Signed-off-by: Jeff Layton Reviewed-and-Tested-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/readdir.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ef7bb7b..32d300e 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file) char *full_path = NULL; struct cifsFileInfo *cifsFile; struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - struct tcon_link *tlink; + struct tcon_link *tlink = NULL; struct cifsTconInfo *pTcon; - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - if (file->private_data == NULL) - file->private_data = - kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); if (file->private_data == NULL) { - rc = -ENOMEM; - goto error_exit; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + + cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); + if (cifsFile == NULL) { + rc = -ENOMEM; + goto error_exit; + } + file->private_data = cifsFile; + cifsFile->tlink = cifs_get_tlink(tlink); + pTcon = tlink_tcon(tlink); + } else { + cifsFile = file->private_data; + pTcon = tlink_tcon(cifsFile->tlink); } - cifsFile = file->private_data; cifsFile->invalidHandle = true; cifsFile->srch_inf.endOfSearch = false; - cifsFile->tlink = cifs_get_tlink(tlink); full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { -- cgit v1.1 From 362d31297fafb150676f4d564ecc7f7f3e3b7fd4 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Nov 2010 03:34:30 +0000 Subject: [CIFS] fs/cifs/Kconfig: CIFS depends on CRYPTO_HMAC linux-2.6.37-rc1: I compiled a kernel with CIFS which subsequently failed with an error indicating it couldn't initialize crypto module "hmacmd5". CONFIG_CRYPTO_HMAC=y fixed the problem. This patch makes CIFS depend on CRYPTO_HMAC in kconfig. Signed-off-by: Jody Bruchon CC: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/cifs') diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0ed2139..3bdbfb0 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -4,6 +4,7 @@ config CIFS select NLS select CRYPTO select CRYPTO_MD5 + select CRYPTO_HMAC select CRYPTO_ARC4 help This is the client VFS module for the Common Internet File System -- cgit v1.1 From 523fb8c867650196bef830d5dd9315d9975a9b7e Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Mon, 29 Nov 2010 22:39:47 +0530 Subject: cifs: trivial comment fix for cifs_invalidate_mapping Only the callers check whether the invalid_mapping flag is set and not cifs_invalidate_mapping(). Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ff7d299..669298f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1670,7 +1670,9 @@ cifs_inode_needs_reval(struct inode *inode) return false; } -/* check invalid_mapping flag and zap the cache if it's set */ +/* + * Zap the cache. Called when invalid_mapping flag is set. + */ static void cifs_invalidate_mapping(struct inode *inode) { -- cgit v1.1 From 78415d2d306bfed0a0ac351aec6c69759d007224 Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar Date: Sat, 27 Nov 2010 11:37:26 -0600 Subject: cifs: Misc. cleanup in cifsacl handling [try #4] Change the name of function mode_to_acl to mode_to_cifs_acl. Handle return code in functions mode_to_cifs_acl and cifs_acl_to_fattr. Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 2 +- fs/cifs/cifsproto.h | 2 +- fs/cifs/inode.c | 20 +++++++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 91992ab..c15e3ee 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -726,7 +726,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, } /* Convert mode bits to an ACL so we can update the ACL on the server */ -int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) +int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) { int rc = 0; __u32 secdesclen = 0; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 6ed59af..b498731 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -133,7 +133,7 @@ extern int cifs_get_inode_info_unix(struct inode **pinode, extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid); -extern int mode_to_acl(struct inode *inode, const char *path, __u64); +extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, const char *); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 669298f..28cb6e7 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -689,8 +689,13 @@ int cifs_get_inode_info(struct inode **pinode, #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"); - cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, + pfid); + if (rc) { + cFYI(1, "%s: Getting ACL failed with error: %d", + __func__, rc); + goto cgii_exit; + } } #endif @@ -2117,9 +2122,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) if (attrs->ia_valid & ATTR_MODE) { rc = 0; #ifdef CONFIG_CIFS_EXPERIMENTAL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) - rc = mode_to_acl(inode, full_path, mode); - else + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + rc = mode_to_cifs_acl(inode, full_path, mode); + if (rc) { + cFYI(1, "%s: Setting ACL failed with error: %d", + __func__, rc); + goto cifs_setattr_exit; + } + } else #endif if (((mode & S_IWUGO) == 0) && (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { -- cgit v1.1 From fbeba8bb16d7c50362e28f3f91a79fb414903199 Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar Date: Sat, 27 Nov 2010 11:37:54 -0600 Subject: cifs: Handle extended attribute name cifs_acl to generate cifs acl blob (try #4) Add extended attribute name system.cifs_acl Get/generate cifs/ntfs acl blob and hand over to the invoker however it wants to parse/process it under experimental configurable option CIFS_ACL. Do not get CIFS/NTFS ACL for xattr for attribute system.posix_acl_access Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/Kconfig | 7 +++++++ fs/cifs/cifsacl.c | 2 +- fs/cifs/cifsproto.h | 2 ++ fs/cifs/xattr.c | 55 +++++++++++++++++++++++++++++------------------------ 4 files changed, 40 insertions(+), 26 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 3bdbfb0..ee45648 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -144,6 +144,13 @@ config CIFS_FSCACHE to be cached locally on disk through the general filesystem cache manager. If unsure, say N. +config CIFS_ACL + bool "Provide CIFS ACL support (EXPERIMENTAL)" + depends on EXPERIMENTAL && CIFS_XATTR + help + Allows to fetch CIFS/NTFS ACL from the server. The DACL blob + is handed over to the application/caller. + config CIFS_EXPERIMENTAL bool "CIFS Experimental Features (EXPERIMENTAL)" depends on CIFS && EXPERIMENTAL diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c15e3ee..c6ebea0 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -608,7 +608,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, } /* Retrieve an ACL from the server */ -static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, +struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, struct inode *inode, const char *path, u32 *pacllen) { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b498731..db961dc 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -134,6 +134,8 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid); extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); +extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, + const char *, u32 *); extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, const char *); diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a264b74..eae2a14 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -30,10 +30,11 @@ #define MAX_EA_VALUE_SIZE 65535 #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" +#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" #define CIFS_XATTR_USER_PREFIX "user." #define CIFS_XATTR_SYSTEM_PREFIX "system." #define CIFS_XATTR_OS2_PREFIX "os2." -#define CIFS_XATTR_SECURITY_PREFIX ".security" +#define CIFS_XATTR_SECURITY_PREFIX "security." #define CIFS_XATTR_TRUSTED_PREFIX "trusted." #define XATTR_TRUSTED_PREFIX_LEN 8 #define XATTR_SECURITY_PREFIX_LEN 9 @@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -#ifdef CONFIG_CIFS_EXPERIMENTAL - else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - __u16 fid; - int oplock = 0; - struct cifs_ntsd *pacl = NULL; - __u32 buflen = 0; - if (experimEnabled) - rc = CIFSSMBOpen(xid, pTcon, full_path, - FILE_OPEN, GENERIC_READ, 0, &fid, - &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - /* else rc is EOPNOTSUPP from above */ - - if (rc == 0) { - rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, - &buflen); - CIFSSMBClose(xid, pTcon, fid); - } - } -#endif /* EXPERIMENTAL */ #else - cFYI(1, "query POSIX ACL not supported yet"); + cFYI(1, "Query POSIX ACL not supported yet"); #endif /* CONFIG_CIFS_POSIX */ } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { @@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); #else - cFYI(1, "query POSIX default ACL not supported yet"); -#endif + cFYI(1, "Query POSIX default ACL not supported yet"); +#endif /* CONFIG_CIFS_POSIX */ + } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, + strlen(CIFS_XATTR_CIFS_ACL)) == 0) { +#ifdef CONFIG_CIFS_ACL + u32 acllen; + struct cifs_ntsd *pacl; + + pacl = get_cifs_acl(cifs_sb, direntry->d_inode, + full_path, &acllen); + if (IS_ERR(pacl)) { + rc = PTR_ERR(pacl); + cERROR(1, "%s: error %zd getting sec desc", + __func__, rc); + } else { + if (ea_value) { + if (acllen > buf_size) + acllen = -ERANGE; + else + memcpy(ea_value, pacl, acllen); + } + rc = acllen; + kfree(pacl); + } +#else + cFYI(1, "Query CIFS ACL not supported yet"); +#endif /* CONFIG_CIFS_ACL */ } else if (strncmp(ea_name, CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { cFYI(1, "Trusted xattr namespace not supported yet"); -- cgit v1.1 From 607a569da4cf289fd8eb3887080ed3b212e3112d Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Wed, 24 Nov 2010 17:49:05 +0530 Subject: cifs: allow fsc mount option only if CONFIG_CIFS_FSCACHE is set Currently, it is possible to specify 'fsc' mount option even if CONFIG_CIFS_FSCACHE has not been set. The option is being ignored silently while the user fscache functionality to work. Fix this by raising error when the CONFIG option is not set. Reported-by: Jeff Layton Reviewed-by: Jeff Layton Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/connect.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 251a17c..32fa4d9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1352,6 +1352,11 @@ cifs_parse_mount_options(char *options, const char *devname, "supported. Instead set " "/proc/fs/cifs/LookupCacheEnabled to 0\n"); } else if (strnicmp(data, "fsc", 3) == 0) { +#ifndef CONFIG_CIFS_FSCACHE + cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" + "kernel config option set"); + return 1; +#endif vol->fsc = true; } else if (strnicmp(data, "mfsymlinks", 10) == 0) { vol->mfsymlinks = true; -- cgit v1.1 From b81209de2455c6051cf67f2acd8ec26ccb8caf83 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Wed, 24 Nov 2010 17:49:06 +0530 Subject: cifs: enable fscache iff fsc mount option is used explicitly Currently, if CONFIG_CIFS_FSCACHE is set, fscache is enabled on files opened as read-only irrespective of the 'fsc' mount option. Fix this by enabling fscache only if 'fsc' mount option is specified explicitly. Remove an extraneous cFYI debug message and fix a typo while at it. Reported-by: Jeff Layton Acked-by: Jeff Layton Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/fscache.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index a2ad94e..297a43d 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -2,7 +2,7 @@ * fs/cifs/fscache.c - CIFS filesystem cache interface * * Copyright (c) 2010 Novell, Inc. - * Author(s): Suresh Jayaraman (sjayaraman@suse.de> + * Author(s): Suresh Jayaraman * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -67,10 +67,12 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) if (cifsi->fscache) return; - cifsi->fscache = fscache_acquire_cookie(tcon->fscache, + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { + cifsi->fscache = fscache_acquire_cookie(tcon->fscache, &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, + cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, cifsi->fscache); + } } void cifs_fscache_release_inode_cookie(struct inode *inode) @@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) { if ((filp->f_flags & O_ACCMODE) != O_RDONLY) cifs_fscache_disable_inode_cookie(inode); - else { + else cifs_fscache_enable_inode_cookie(inode); - cFYI(1, "CIFS: fscache inode cookie set"); - } } void cifs_fscache_reset_inode_cookie(struct inode *inode) -- cgit v1.1 From 476428f8c3bb6679f8f52bf2b935ac40bc9c7358 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Wed, 24 Nov 2010 17:49:07 +0530 Subject: cifs: display fsc in /proc/mounts Reviewed-by: Jeff Layton Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9c37897..76c8a90 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -458,6 +458,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) seq_printf(s, ",acl"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) seq_printf(s, ",mfsymlinks"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) + seq_printf(s, ",fsc"); seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize); -- cgit v1.1 From ba03864872691c0bb580a7fb47388da337ef4aa2 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 30 Nov 2010 15:14:48 -0500 Subject: cifs: fix parsing of hostname in dfs referrals The DFS referral parsing code does a memchr() call to find the '\\' delimiter that separates the hostname in the referral UNC from the sharename. It then uses that value to set the length of the hostname via pointer subtraction. Instead of subtracting the start of the hostname however, it subtracts the start of the UNC, which causes the code to pass in a hostname length that is 2 bytes too long. Regression introduced in commit 1a4240f4. Reported-and-Tested-by: Robbert Kouprie Signed-off-by: Jeff Layton Cc: Wang Lei Cc: David Howells Cc: stable@kernel.org Signed-off-by: Steve French --- fs/cifs/dns_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs') diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 0eb8702..548f062 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) /* Search for server name delimiter */ sep = memchr(hostname, '\\', len); if (sep) - len = sep - unc; + len = sep - hostname; else cFYI(1, "%s: probably server name is whole unc: %s", __func__, unc); -- cgit v1.1