aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-29 01:41:04 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-29 01:41:04 -0400
commitf654bac2227adc5c6956405290eeb4f81f09e9ff (patch)
tree9391321485e530375cb5ce1fced0ece2acc02a67 /fs/cifs
parent1da0c78b32abe122a959d2a57ba3d41563d8e39f (diff)
[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 <torvalds@osdl.org>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES9
-rw-r--r--fs/cifs/cifsfs.h6
-rw-r--r--fs/cifs/cifspdu.h69
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c86
-rw-r--r--fs/cifs/ioctl.c52
6 files changed, 212 insertions, 14 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 5316c8dd6bff..7fd02697b12e 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,14 @@
1Version 1.31 1Version 1.32
2------------ 2------------
3Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one 3Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
4transact response for an SMB request and search entry split across two frames. 4transact response for an SMB request and search entry split across two frames.
5Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server)
6as new protocol extensions. Do not send Get/Set calls for POSIX ACLs
7unless server explicitly claims to support them in CIFS Unix extensions
8POSIX ACL capability bit.
9
10Version 1.31
11------------
5Fix updates of DOS attributes and time fields so that files on NT4 servers 12Fix updates of DOS attributes and time fields so that files on NT4 servers
6do not get marked delete on close. Display sizes of cifs buffer pools in 13do not get marked delete on close. Display sizes of cifs buffer pools in
7cifs stats. Fix oops in unmount when cifsd thread being killed by 14cifs stats. Fix oops in unmount when cifsd thread being killed by
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 451f18af3206..e0e46f4bff97 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -91,8 +91,10 @@ extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
91 const char *symname); 91 const char *symname);
92extern int cifs_removexattr(struct dentry *, const char *); 92extern int cifs_removexattr(struct dentry *, const char *);
93extern int cifs_setxattr(struct dentry *, const char *, const void *, 93extern int cifs_setxattr(struct dentry *, const char *, const void *,
94 size_t, int); 94 size_t, int);
95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); 95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97#define CIFS_VERSION "1.31" 97extern int cifs_ioctl (struct inode * inode, struct file * filep,
98 unsigned int command, unsigned long arg);
99#define CIFS_VERSION "1.32"
98#endif /* _CIFSFS_H */ 100#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index bcd4a6136f08..085109d2b55e 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -762,6 +762,16 @@ typedef struct smb_com_lock_req {
762 LOCKING_ANDX_RANGE Locks[1]; 762 LOCKING_ANDX_RANGE Locks[1];
763} LOCK_REQ; 763} LOCK_REQ;
764 764
765
766typedef struct cifs_posix_lock {
767 __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
768 __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
769 __le32 pid;
770 __le64 start;
771 __le64 length;
772 /* BB what about additional owner info to identify network client */
773} CIFS_POSIX_LOCK;
774
765typedef struct smb_com_lock_rsp { 775typedef struct smb_com_lock_rsp {
766 struct smb_hdr hdr; /* wct = 2 */ 776 struct smb_hdr hdr; /* wct = 2 */
767 __u8 AndXCommand; 777 __u8 AndXCommand;
@@ -1098,6 +1108,8 @@ struct smb_t2_rsp {
1098#define SMB_QUERY_POSIX_ACL 0x204 1108#define SMB_QUERY_POSIX_ACL 0x204
1099#define SMB_QUERY_XATTR 0x205 1109#define SMB_QUERY_XATTR 0x205
1100#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ 1110#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1111#define SMB_QUERY_POSIX_PERMISSION 0x207
1112#define SMB_QUERY_POSIX_LOCK 0x208
1101#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee 1113#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1102#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 1114#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1103#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ 1115#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1116,6 +1128,7 @@ struct smb_t2_rsp {
1116#define SMB_SET_POSIX_ACL 0x204 1128#define SMB_SET_POSIX_ACL 0x204
1117#define SMB_SET_XATTR 0x205 1129#define SMB_SET_XATTR 0x205
1118#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ 1130#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1131#define SMB_SET_POSIX_LOCK 0x208
1119#define SMB_SET_FILE_BASIC_INFO2 0x3ec 1132#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1120#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ 1133#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
1121#define SMB_FILE_ALL_INFO2 0x3fa 1134#define SMB_FILE_ALL_INFO2 0x3fa
@@ -1237,9 +1250,27 @@ struct smb_com_transaction2_sfi_rsp {
1237 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1250 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1238 struct trans2_resp t2; 1251 struct trans2_resp t2;
1239 __u16 ByteCount; 1252 __u16 ByteCount;
1240 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1253 __u16 Reserved2; /* parameter word reserved -
1254 present for infolevels > 100 */
1255};
1256
1257struct smb_t2_qfi_req {
1258 struct smb_hdr hdr;
1259 struct trans2_req t2;
1260 __u8 Pad;
1261 __u16 Pad1;
1262 __u16 Fid;
1263 __le16 InformationLevel;
1264 __u16 Pad2;
1241}; 1265};
1242 1266
1267struct smb_t2_qfi_rsp {
1268 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1269 struct trans2_resp t2;
1270 __u16 ByteCount;
1271 __u16 Reserved2; /* parameter word reserved -
1272 present for infolevels > 100 */
1273};
1243 1274
1244/* 1275/*
1245 * Flags on T2 FINDFIRST and FINDNEXT 1276 * Flags on T2 FINDFIRST and FINDNEXT
@@ -1524,8 +1555,9 @@ typedef struct {
1524} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1555} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1525/* Linux/Unix extensions capability flags */ 1556/* Linux/Unix extensions capability flags */
1526#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1557#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1527#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 1558#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1528#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/ 1559#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1560#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1529 1561
1530typedef struct { 1562typedef struct {
1531 /* For undefined recommended transfer size return -1 in that field */ 1563 /* For undefined recommended transfer size return -1 in that field */
@@ -1971,14 +2003,39 @@ struct xsymlink {
1971 char path[1024]; 2003 char path[1024];
1972}; 2004};
1973 2005
1974typedef struct { 2006typedef struct file_xattr_info {
1975 /* BB do we need another field for flags? BB */ 2007 /* BB do we need another field for flags? BB */
1976 __u32 xattr_name_len; 2008 __u32 xattr_name_len;
1977 __u32 xattr_value_len; 2009 __u32 xattr_value_len;
1978 char xattr_name[0]; 2010 char xattr_name[0];
1979 /* followed by xattr_value[xattr_value_len], no pad */ 2011 /* followed by xattr_value[xattr_value_len], no pad */
1980} FILE_XATTR_INFO; /* extended attribute, info level 205 */ 2012} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
1981 2013
2014
2015/* flags for chattr command */
2016#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */
2017#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */
2018/* Reserved for compress file 0x4 */
2019#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */
2020#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */
2021#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */
2022#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */
2023#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */
2024/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
2025#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */
2026/* 0x2000 reserved for IMAGIC_FL */
2027#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
2028/* 0x8000 reserved for EXT3_NOTAIL_FL */
2029#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */
2030#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */
2031
2032#define EXT_SET_MASK 0x000300FF
2033#define EXT_GET_MASK 0x0003DFFF
2034
2035typedef struct file_chattr_info {
2036 __le64 mask; /* list of all possible attribute bits */
2037 __le64 mode; /* list of actual attribute bits on this inode */
2038} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
1982 2039
1983#endif 2040#endif
1984 2041
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 787eef4d86d3..82ae59d7cf9d 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -264,6 +264,8 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
264 const unsigned char *fileName, 264 const unsigned char *fileName,
265 const char *local_acl, const int buflen, const int acl_type, 265 const char *local_acl, const int buflen, const int acl_type,
266 const struct nls_table *nls_codepage); 266 const struct nls_table *nls_codepage);
267int cifs_ioctl (struct inode * inode, struct file * filep, 267extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
268 const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
269extern int cifs_ioctl (struct inode * inode, struct file * filep,
268 unsigned int command, unsigned long arg); 270 unsigned int command, unsigned long arg);
269#endif /* _CIFSPROTO_H */ 271#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index df6a619a6821..36d3c128a58b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2072,7 +2072,91 @@ setACLerrorExit:
2072 return rc; 2072 return rc;
2073} 2073}
2074 2074
2075#endif 2075/* BB fix tabs in this function FIXME BB */
2076int
2077CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2078 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2079{
2080 int rc = 0;
2081 struct smb_t2_qfi_req *pSMB = NULL;
2082 struct smb_t2_qfi_rsp *pSMBr = NULL;
2083 int bytes_returned;
2084 __u16 params, byte_count;
2085
2086 cFYI(1,("In GetExtAttr"));
2087 if(tcon == NULL)
2088 return -ENODEV;
2089
2090GetExtAttrRetry:
2091 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2092 (void **) &pSMBr);
2093 if (rc)
2094 return rc;
2095
2096 params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */;
2097 pSMB->t2.TotalDataCount = 0;
2098 pSMB->t2.MaxParameterCount = cpu_to_le16(2);
2099 /* BB find exact max data count below from sess structure BB */
2100 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2101 pSMB->t2.MaxSetupCount = 0;
2102 pSMB->t2.Reserved = 0;
2103 pSMB->t2.Flags = 0;
2104 pSMB->t2.Timeout = 0;
2105 pSMB->t2.Reserved2 = 0;
2106 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(
2107 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2108 pSMB->t2.DataCount = 0;
2109 pSMB->t2.DataOffset = 0;
2110 pSMB->t2.SetupCount = 1;
2111 pSMB->t2.Reserved3 = 0;
2112 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2113 byte_count = params + 3 /* pad */ ;
2114 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2115 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2116 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2117 pSMB->Pad1 = 0;
2118 pSMB->Pad2 = 0;
2119 pSMB->Fid = netfid;
2120 pSMB->hdr.smb_buf_length += byte_count;
2121 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2122
2123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2125 if (rc) {
2126 cFYI(1, ("error %d in GetExtAttr", rc));
2127 } else {
2128 /* decode response */
2129 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2130 if (rc || (pSMBr->ByteCount < 2))
2131 /* BB also check enough total bytes returned */
2132 /* If rc should we check for EOPNOSUPP and
2133 disable the srvino flag? or in caller? */
2134 rc = -EIO; /* bad smb */
2135 else {
2136 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2137 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2138 struct file_chattr_info * pfinfo;
2139 /* BB Do we need a cast or hash here ? */
2140 if(count != 16) {
2141 cFYI(1, ("Illegal size ret in GetExtAttr"));
2142 rc = -EIO;
2143 goto GetExtAttrOut;
2144 }
2145 pfinfo = (struct file_chattr_info *)
2146 (data_offset + (char *) &pSMBr->hdr.Protocol);
2147 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2148 *pMask = le64_to_cpu(pfinfo->mask);
2149 }
2150 }
2151GetExtAttrOut:
2152 cifs_buf_release(pSMB);
2153 if (rc == -EAGAIN)
2154 goto GetExtAttrRetry;
2155 return rc;
2156}
2157
2158
2159#endif /* CONFIG_POSIX */
2076 2160
2077int 2161int
2078CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2162CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
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 @@
20 * along with this library; if not, write to the Free Software 20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23
23#include <linux/fs.h> 24#include <linux/fs.h>
24#include <linux/ext2_fs.h> 25#include <linux/ext2_fs.h>
25#include "cifspdu.h" 26#include "cifspdu.h"
@@ -32,18 +33,63 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
32{ 33{
33 int rc = -ENOTTY; /* strange error - but the precedent */ 34 int rc = -ENOTTY; /* strange error - but the precedent */
34#ifdef CONFIG_CIFS_POSIX 35#ifdef CONFIG_CIFS_POSIX
36 __u64 ExtAttrBits = 0;
37 __u64 ExtAttrMask = 0;
38 __u64 caps;
39#endif /* CONFIG_CIFS_POSIX */
40 int xid;
41 struct cifs_sb_info *cifs_sb;
42 struct cifsTconInfo *tcon;
43 struct cifsFileInfo *pSMBFile =
44 (struct cifsFileInfo *)filep->private_data;
45
46 xid = GetXid();
47
48 cifs_sb = CIFS_SB(inode->i_sb);
49 tcon = cifs_sb->tcon;
50 if (pSMBFile == NULL)
51 goto cifs_ioctl_out;
52
53#ifdef CONFIG_CIFS_POSIX
54 if(tcon)
55 caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
56 else {
57 rc = -EIO;
58 goto cifs_ioctl_out;
59 }
60
35 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); 61 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
36 switch(command) { 62 switch(command) {
37 case EXT2_IOC_GETFLAGS: 63 case EXT2_IOC_GETFLAGS:
38 cFYI(1,("get flags not implemented yet")); 64 if(CIFS_UNIX_EXTATTR_CAP & caps) {
39 return -EOPNOTSUPP; 65 rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
66 &ExtAttrBits, &ExtAttrMask);
67 if(rc == 0)
68 rc = put_user(ExtAttrBits &
69 EXT2_FL_USER_VISIBLE,
70 (int __user *)arg);
71 }
72 break;
73
40 case EXT2_IOC_SETFLAGS: 74 case EXT2_IOC_SETFLAGS:
75 if(CIFS_UNIX_EXTATTR_CAP & caps) {
76 if(get_user(ExtAttrBits,(int __user *)arg)) {
77 rc = -EFAULT;
78 goto cifs_ioctl_out;
79 }
80 /* rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
81 extAttrBits, &ExtAttrMask);*/
82
83 }
41 cFYI(1,("set flags not implemented yet")); 84 cFYI(1,("set flags not implemented yet"));
42 return -EOPNOTSUPP; 85 break;
43 default: 86 default:
44 cFYI(1,("unsupported ioctl")); 87 cFYI(1,("unsupported ioctl"));
45 return rc; 88 return rc;
46 } 89 }
47#endif /* CONFIG_CIFS_POSIX */ 90#endif /* CONFIG_CIFS_POSIX */
91
92cifs_ioctl_out:
93 FreeXid(xid);
48 return rc; 94 return rc;
49} 95}