From f654bac2227adc5c6956405290eeb4f81f09e9ff Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: add support for chattr/lsattr in new CIFS POSIX extensions Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/ioctl.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'fs/cifs/ioctl.c') diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index b4b8e201d428..7b84b2bb8c4a 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -20,6 +20,7 @@ * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include #include #include "cifspdu.h" @@ -32,18 +33,63 @@ int cifs_ioctl (struct inode * inode, struct file * filep, { int rc = -ENOTTY; /* strange error - but the precedent */ #ifdef CONFIG_CIFS_POSIX + __u64 ExtAttrBits = 0; + __u64 ExtAttrMask = 0; + __u64 caps; +#endif /* CONFIG_CIFS_POSIX */ + int xid; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *tcon; + struct cifsFileInfo *pSMBFile = + (struct cifsFileInfo *)filep->private_data; + + xid = GetXid(); + + cifs_sb = CIFS_SB(inode->i_sb); + tcon = cifs_sb->tcon; + if (pSMBFile == NULL) + goto cifs_ioctl_out; + +#ifdef CONFIG_CIFS_POSIX + if(tcon) + caps = le64_to_cpu(tcon->fsUnixInfo.Capability); + else { + rc = -EIO; + goto cifs_ioctl_out; + } + cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); switch(command) { case EXT2_IOC_GETFLAGS: - cFYI(1,("get flags not implemented yet")); - return -EOPNOTSUPP; + if(CIFS_UNIX_EXTATTR_CAP & caps) { + rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + &ExtAttrBits, &ExtAttrMask); + if(rc == 0) + rc = put_user(ExtAttrBits & + EXT2_FL_USER_VISIBLE, + (int __user *)arg); + } + break; + case EXT2_IOC_SETFLAGS: + if(CIFS_UNIX_EXTATTR_CAP & caps) { + if(get_user(ExtAttrBits,(int __user *)arg)) { + rc = -EFAULT; + goto cifs_ioctl_out; + } + /* rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + extAttrBits, &ExtAttrMask);*/ + + } cFYI(1,("set flags not implemented yet")); - return -EOPNOTSUPP; + break; default: cFYI(1,("unsupported ioctl")); return rc; } #endif /* CONFIG_CIFS_POSIX */ + +cifs_ioctl_out: + FreeXid(xid); return rc; } -- cgit v1.2.3-59-g8ed1b From c67593a03129967eae8939c4899767182eb6d6cd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: Enable ioctl support in POSIX extensions to handle lsattr remove sparse warnings, unnecessary pad in QueryFileInfo and redundant function define. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 8 ++++++++ fs/cifs/cifspdu.h | 2 -- fs/cifs/cifsproto.h | 2 -- fs/cifs/cifssmb.c | 13 ++++++------- fs/cifs/ioctl.c | 1 + 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'fs/cifs/ioctl.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5082fce3c566..ae48ef042977 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -559,6 +559,10 @@ struct file_operations cifs_file_ops = { .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ + #ifdef CONFIG_CIFS_EXPERIMENTAL .readv = generic_file_readv, .writev = generic_file_writev, @@ -579,6 +583,10 @@ struct file_operations cifs_file_direct_ops = { .fsync = cifs_fsync, .flush = cifs_flush, .sendfile = generic_file_sendfile, /* BB removeme BB */ +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ + #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 085109d2b55e..5b352890f092 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1258,10 +1258,8 @@ struct smb_t2_qfi_req { struct smb_hdr hdr; struct trans2_req t2; __u8 Pad; - __u16 Pad1; __u16 Fid; __le16 InformationLevel; - __u16 Pad2; }; struct smb_t2_qfi_rsp { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 82ae59d7cf9d..1b0070dfc51c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -266,6 +266,4 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const struct nls_table *nls_codepage); extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, const int netfid, __u64 * pExtAttrBits, __u64 *pMask); -extern int cifs_ioctl (struct inode * inode, struct file * filep, - unsigned int command, unsigned long arg); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 36d3c128a58b..237e3bf94bfe 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2093,9 +2093,9 @@ GetExtAttrRetry: if (rc) return rc; - params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */; + params = 2 /* level */ +2 /* fid */; pSMB->t2.TotalDataCount = 0; - pSMB->t2.MaxParameterCount = cpu_to_le16(2); + pSMB->t2.MaxParameterCount = cpu_to_le16(4); /* BB find exact max data count below from sess structure BB */ pSMB->t2.MaxDataCount = cpu_to_le16(4000); pSMB->t2.MaxSetupCount = 0; @@ -2103,19 +2103,18 @@ GetExtAttrRetry: pSMB->t2.Flags = 0; pSMB->t2.Timeout = 0; pSMB->t2.Reserved2 = 0; - pSMB->t2.ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); + pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req, + Fid) - 4); pSMB->t2.DataCount = 0; pSMB->t2.DataOffset = 0; pSMB->t2.SetupCount = 1; pSMB->t2.Reserved3 = 0; pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - byte_count = params + 3 /* pad */ ; + byte_count = params + 1 /* pad */ ; pSMB->t2.TotalParameterCount = cpu_to_le16(params); pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); - pSMB->Pad1 = 0; - pSMB->Pad2 = 0; + pSMB->Pad = 0; pSMB->Fid = netfid; pSMB->hdr.smb_buf_length += byte_count; pSMB->t2.ByteCount = cpu_to_le16(byte_count); diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 7b84b2bb8c4a..a4f1c34a8dc7 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -27,6 +27,7 @@ #include "cifsglob.h" #include "cifsproto.h" #include "cifs_debug.h" +#include "cifsfs.h" int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) -- cgit v1.2.3-59-g8ed1b From f28ac91b0541a49d5bc7bfb9f0efd5289a7dd181 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: CIFS ioctl needed by umount.cifs utility Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 4 ++++ fs/cifs/cifspdu.h | 2 +- fs/cifs/ioctl.c | 31 +++++++++++++++++++++++-------- 3 files changed, 28 insertions(+), 9 deletions(-) (limited to 'fs/cifs/ioctl.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3d5365b9f5ba..461a706b237b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -190,6 +190,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) #ifdef CONFIG_CIFS_EXPERIMENTAL /* 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) rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); @@ -599,6 +600,9 @@ struct file_operations cifs_dir_ops = { #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ }; static void diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 5b352890f092..e3e92615705e 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1556,7 +1556,7 @@ typedef struct { #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ - +#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ typedef struct { /* For undefined recommended transfer size return -1 in that field */ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index a4f1c34a8dc7..711bb7a3a98e 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -29,6 +29,8 @@ #include "cifs_debug.h" #include "cifsfs.h" +#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) + int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) { @@ -36,8 +38,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep, #ifdef CONFIG_CIFS_POSIX __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; - __u64 caps; #endif /* CONFIG_CIFS_POSIX */ + __u64 caps; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; @@ -46,12 +48,11 @@ int cifs_ioctl (struct inode * inode, struct file * filep, xid = GetXid(); + cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); + cifs_sb = CIFS_SB(inode->i_sb); tcon = cifs_sb->tcon; - if (pSMBFile == NULL) - goto cifs_ioctl_out; -#ifdef CONFIG_CIFS_POSIX if(tcon) caps = le64_to_cpu(tcon->fsUnixInfo.Capability); else { @@ -59,10 +60,22 @@ int cifs_ioctl (struct inode * inode, struct file * filep, goto cifs_ioctl_out; } - cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); switch(command) { + case CIFS_IOC_CHECKUMOUNT: + cFYI(1,("User unmount attempted")); + /* BB FIXME - add missing code here FIXME */ + if(cifs_sb->mnt_uid == current->uid) + rc = 0; + else { + rc = -EACCES; + cFYI(1,("uids do not match")); + } + break; +#ifdef CONFIG_CIFS_POSIX case EXT2_IOC_GETFLAGS: if(CIFS_UNIX_EXTATTR_CAP & caps) { + if (pSMBFile == NULL) + goto cifs_ioctl_out; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); if(rc == 0) @@ -78,17 +91,19 @@ int cifs_ioctl (struct inode * inode, struct file * filep, rc = -EFAULT; goto cifs_ioctl_out; } - /* rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + if (pSMBFile == NULL) + goto cifs_ioctl_out; + /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ } cFYI(1,("set flags not implemented yet")); break; +#endif /* CONFIG_CIFS_POSIX */ default: cFYI(1,("unsupported ioctl")); - return rc; + break; } -#endif /* CONFIG_CIFS_POSIX */ cifs_ioctl_out: FreeXid(xid); -- cgit v1.2.3-59-g8ed1b From c81156dd217818c143a09b6a744e797a04571e99 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: cleanup of ifdefs usage so it is more consistent And fix to not needlessly send new POSIX QFSInfo when server does not explicitly claim support for the new protocol extensions. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 21 +++++++++++---------- fs/cifs/cifsglob.h | 4 +++- fs/cifs/ioctl.c | 21 +++++++++++---------- 3 files changed, 25 insertions(+), 21 deletions(-) (limited to 'fs/cifs/ioctl.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 461a706b237b..6322aada491f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -169,7 +169,8 @@ cifs_put_super(struct super_block *sb) static int cifs_statfs(struct super_block *sb, struct kstatfs *buf) { - int xid, rc = -EOPNOTSUPP; + int xid; + int rc = -EOPNOTSUPP; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; @@ -181,17 +182,18 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) 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 length of total path, note that some servers may be - able to support more than this, but best to be safe - since Win2k and others can not handle very long filenames */ + 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 */ buf->f_files = 0; /* undefined */ buf->f_ffree = 0; /* unlimited */ #ifdef CONFIG_CIFS_EXPERIMENTAL /* 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) + 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 @@ -204,9 +206,10 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) int f_type; __fsid_t f_fsid; int f_namelen; */ - /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */ + /* BB get from info in tcon struct at mount time call to QFSAttrInfo */ FreeXid(xid); - return 0; /* always return success? what if volume is no longer available? */ + return 0; /* always return success? what if volume is no + longer available? */ } static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) @@ -600,9 +603,7 @@ struct file_operations cifs_dir_ops = { #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ -#ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ }; static void diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index fe1409799513..322a12450ad3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -318,7 +318,9 @@ struct mid_q_entry { struct task_struct *tsk; /* task waiting for response */ 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 */ + __u8 command; /* smb command code */ + unsigned multiPart:1; /* multiple responses to one SMB request */ + unsigned largeBuf:1; /* if valid response, is pointer to large buf */ }; struct oplock_q_entry { diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 711bb7a3a98e..b0ea6687ab55 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -35,35 +35,37 @@ int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) { int rc = -ENOTTY; /* strange error - but the precedent */ + int xid; + struct cifs_sb_info *cifs_sb; #ifdef CONFIG_CIFS_POSIX __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; -#endif /* CONFIG_CIFS_POSIX */ __u64 caps; - int xid; - struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; struct cifsFileInfo *pSMBFile = (struct cifsFileInfo *)filep->private_data; +#endif /* CONFIG_CIFS_POSIX */ xid = GetXid(); cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb->tcon; +#ifdef CONFIG_CIFS_POSIX + tcon = cifs_sb->tcon; if(tcon) caps = le64_to_cpu(tcon->fsUnixInfo.Capability); else { rc = -EIO; - goto cifs_ioctl_out; + FreeXid(xid); + return -EIO; } +#endif /* CONFIG_CIFS_POSIX */ switch(command) { case CIFS_IOC_CHECKUMOUNT: cFYI(1,("User unmount attempted")); - /* BB FIXME - add missing code here FIXME */ if(cifs_sb->mnt_uid == current->uid) rc = 0; else { @@ -75,7 +77,7 @@ int cifs_ioctl (struct inode * inode, struct file * filep, case EXT2_IOC_GETFLAGS: if(CIFS_UNIX_EXTATTR_CAP & caps) { if (pSMBFile == NULL) - goto cifs_ioctl_out; + break; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); if(rc == 0) @@ -89,10 +91,10 @@ int cifs_ioctl (struct inode * inode, struct file * filep, if(CIFS_UNIX_EXTATTR_CAP & caps) { if(get_user(ExtAttrBits,(int __user *)arg)) { rc = -EFAULT; - goto cifs_ioctl_out; + break; } if (pSMBFile == NULL) - goto cifs_ioctl_out; + break; /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ @@ -105,7 +107,6 @@ int cifs_ioctl (struct inode * inode, struct file * filep, break; } -cifs_ioctl_out: FreeXid(xid); return rc; } -- cgit v1.2.3-59-g8ed1b