summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/Kconfig16
-rw-r--r--fs/cifs/CHANGES18
-rw-r--r--fs/cifs/README28
-rw-r--r--fs/cifs/cifs_fs_sb.h4
-rw-r--r--fs/cifs/cifsfs.c13
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/cifspdu.h23
-rw-r--r--fs/cifs/cifsproto.h44
-rw-r--r--fs/cifs/cifssmb.c401
-rw-r--r--fs/cifs/connect.c38
-rw-r--r--fs/cifs/dir.c23
-rw-r--r--fs/cifs/inode.c20
-rw-r--r--fs/cifs/smbencrypt.c2
-rw-r--r--fs/cifs/smberr.h3
-rw-r--r--fs/cifs/xattr.c172
-rw-r--r--net/sched/Kconfig3
17 files changed, 734 insertions, 82 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 5e7c10fa8f8f..82810094fdce 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1652,6 +1652,22 @@ config CIFS_STATS
Enabling this option will cause statistics for each server share
mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
+config CIFS_XATTR
+ bool "CIFS extended attributes (EXPERIMENTAL)"
+ depends on CIFS
+ help
+ Extended attributes are name:value pairs associated with inodes by
+ the kernel or by users (see the attr(5) manual page, or visit
+ <http://acl.bestbits.at/> for details). CIFS maps the name of
+ extended attributes beginning with the user namespace prefix
+ to SMB/CIFS EAs. EAs are stored on Windows servers without the
+ user namespace prefix, but their names are seen by Linux cifs clients
+ prefaced by the user namespace prefix. The system namespace
+ (used by some filesystems to store ACLs) is not supported at
+ this time.
+
+ If unsure, say N.
+
config CIFS_POSIX
bool "CIFS POSIX Extensions (EXPERIMENTAL)"
depends on CIFS
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 3f1663754388..a853ec02e494 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,21 @@
+Version 1.22
+------------
+Add config option to enable XATTR (extended attribute) support, mapping
+xattr names in the "user." namespace space to SMB/CIFS EAs.
+
+Version 1.21
+------------
+Add new mount parm to control whether mode check (vfs_permission) is done on
+the client. If Unix extensions are enabled and the uids on the client
+and server do not match, client permission checks are meaningless on
+server uids that do not exist on the client (this does not affect the
+normal ACL check which occurs on the server). Fix default uid
+on mknod to match create and mkdir. Add optional mount parm to allow
+override of the default uid behavior (in which the server sets the uid
+and gid of newly created files). Normally for network filesystem mounts
+user want the server to set the uid/gid on newly created files (rather than
+using uid of the client processes you would in a local filesystem).
+
Version 1.20
------------
Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
diff --git a/fs/cifs/README b/fs/cifs/README
index 59a00eea0b35..799530255b28 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -255,7 +255,33 @@ A partial list of the supported mount options follows:
mount helper will not prompt the user for a password
if guest is specified on the mount options. If no
password is specified a null password will be used.
-
+ perm Client does permission checks (vfs_permission check of uid
+ and gid of the file against the mode and desired operation),
+ Note that this is in addition to the normal ACL check on the
+ target machine done by the server software.
+ Client permission checking is enabled by default.
+ noperm Client does not do permission checks. This can expose
+ files on this mount to access by other users on the local
+ client system. It is typically only needed when the server
+ supports the CIFS Unix Extensions but the UIDs/GIDs on the
+ client and server system do not match closely enough to allow
+ access by the user doing the mount.
+ Note that this does not affect the normal ACL check on the
+ target machine done by the server software (of the server
+ ACL against the user name provided at mount time).
+ setuids If the CIFS Unix extensions are negotiated with the server
+ the client will attempt to set the effective uid and gid of
+ the local process on newly created files, directories, and
+ devices (create, mkdir, mknod).
+ nosetuids The client will not attempt to set the uid and gid on
+ on newly created files, directories, and devices (create,
+ mkdir, mknod) which will result in the server setting the
+ uid and gid to the default (usually the server uid of the
+ usern who mounted the share). Letting the server (rather than
+ the client) set the uid and gid is the default. This
+ parameter has no effect if the CIFS Unix Extensions are not
+ negotiated.
+
The mount.cifs mount helper also accepts a few mount options before -o
including:
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 8007c2e925f5..592af83bcb9c 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -18,6 +18,9 @@
#ifndef _CIFS_FS_SB_H
#define _CIFS_FS_SB_H
+#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
+#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
+
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
struct list_head nested_tcon_q;
@@ -28,5 +31,6 @@ struct cifs_sb_info {
gid_t mnt_gid;
mode_t mnt_file_mode;
mode_t mnt_dir_mode;
+ int mnt_cifs_flags;
};
#endif /* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 0170ad6bcd03..2607ce38a697 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -41,8 +41,6 @@
#include "cifs_fs_sb.h"
#include <linux/mm.h>
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
-/* BB when mempool_resize is added back in, we will resize pool on new mount */
-#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
#ifdef CONFIG_CIFS_QUOTA
static struct quotactl_ops cifs_quotactl_ops;
@@ -192,15 +190,11 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
- struct cifs_sb_info *cifs_sb;
+ struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(inode->i_sb);
+ cifs_sb = CIFS_SB(inode->i_sb);
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
- /* the server supports the Unix-like mode bits and does its
- own permission checks, and therefore we do not allow the file
- mode to be overriden on these mounts - so do not do perm
- check on client side */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
return 0;
} else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for
@@ -746,6 +740,7 @@ init_cifs(void)
*/
atomic_set(&sesInfoAllocCount, 0);
atomic_set(&tconInfoAllocCount, 0);
+ atomic_set(&tcpSesAllocCount,0);
atomic_set(&tcpSesReconnectCount, 0);
atomic_set(&tconInfoReconnectCount, 0);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index eb7809eefcfb..258442eea695 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -32,14 +32,10 @@
#define TRUE 1
#endif
-extern int map_cifs_error(int error_class, int error_code,
- int status_codes_negotiated);
-
extern struct address_space_operations cifs_addr_ops;
/* Functions related to super block operations */
extern struct super_operations cifs_super_ops;
-extern void cifs_put_inode(struct inode *);
extern void cifs_read_inode(struct inode *);
extern void cifs_delete_inode(struct inode *);
/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cfbfac7a74b6..21ac75cf02d7 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -32,6 +32,8 @@
termination then *2 for unicode versions */
#define MAX_PASSWORD_SIZE 16
+#define CIFS_MIN_RCV_POOL 4
+
/*
* MAX_REQ is the maximum number of requests that WE will send
* on one socket concurently. It also matches the most common
@@ -391,7 +393,7 @@ GLOBAL_EXTERN char Local_System_Name[15];
*/
GLOBAL_EXTERN atomic_t sesInfoAllocCount;
GLOBAL_EXTERN atomic_t tconInfoAllocCount;
-
+GLOBAL_EXTERN atomic_t tcpSesAllocCount;
GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 067eb4e3eebb..94646af9f84d 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1046,6 +1046,8 @@ typedef union smb_com_transaction2 {
/* PathInfo/FileInfo infolevels */
#define SMB_INFO_STANDARD 1
+#define SMB_SET_FILE_EA 2
+#define SMB_QUERY_FILE_EA_SIZE 2
#define SMB_INFO_QUERY_EAS_FROM_LIST 3
#define SMB_INFO_QUERY_ALL_EAS 4
#define SMB_INFO_IS_NAME_VALID 6
@@ -1620,6 +1622,19 @@ typedef struct {
char LinkDest[1];
} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
+typedef struct {
+ __u16 CreationDate;
+ __u16 CreationTime;
+ __u16 LastAccessDate;
+ __u16 LastAccessTime;
+ __u16 LastWriteDate;
+ __u16 LastWriteTime;
+ __u32 DataSize; /* File Size (EOF) */
+ __u32 AllocationSize;
+ __u16 Attributes; /* verify not u32 */
+ __u32 EASize;
+} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
+
/* defines for enumerating possible values of the Unix type field below */
#define UNIX_FILE 0
#define UNIX_DIR 1
@@ -1680,12 +1695,12 @@ typedef struct {
} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
struct gea {
- unsigned char cbName;
- char szName[1];
+ unsigned char name_len;
+ char name[1];
};
struct gealist {
- unsigned long cbList;
+ unsigned long list_len;
struct gea list[1];
};
@@ -1693,7 +1708,7 @@ struct fea {
unsigned char EA_flags;
__u8 name_len;
__u16 value_len;
- char szName[1];
+ char name[1];
/* optionally followed by value */
};
/* flags for _FEA.fEA */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 215bbc1960bb..8273700778d3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -128,10 +128,10 @@ extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
- char *fileName, FILE_BASIC_INFO * data,
+ const char *fileName, const FILE_BASIC_INFO * data,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
- char *fileName, __u64 size,int setAllocationSizeFlag,
+ const char *fileName, __u64 size,int setAllocationSizeFlag,
const struct nls_table *nls_codepage);
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
@@ -213,31 +213,6 @@ extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
-
-extern int CIFSBuildServerList(int xid, char *serverBufferList,
- int recordlength, int *entries,
- int *totalEntries, int *topoChangedFlag);
-extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
- struct shareInfo *shareList, int bufferLen,
- int *entries, int *totalEntries);
-extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
- struct aliasInfo *aliasList, int bufferLen,
- int *entries, int *totalEntries);
-extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
- char *aliasName, char *serverName,
- char *shareName, char *comment);
-extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
- char *share, char *comment);
-extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
- char *userName, char *searchName, int *perms);
-extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
-
-extern int CIFSSMBSeek(int xid,
- struct cifsTconInfo *tcon,
- int netfid,
- int pid,
- int whence, unsigned long offset, long long *newoffset);
-
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
const char *fromName,
@@ -247,8 +222,15 @@ extern int CIFSSMBCopy(int xid,
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid,__u32 filter,
const struct nls_table *nls_codepage);
-extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char * EAData, size_t size,
- const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName, char * EAData,
+ size_t bufsize, const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+ const unsigned char * searchName,const unsigned char * ea_name,
+ unsigned char * ea_value, size_t buf_size,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
+ const char *fileName, const char * ea_name,
+ const void * ea_value, const __u16 ea_value_len,
+ const struct nls_table *nls_codepage);
#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c748d158f060..dc9e0fd4edd9 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2287,7 +2287,7 @@ QFSInfoRetry:
}
int
-CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
@@ -2359,7 +2359,7 @@ QFSAttributeRetry:
}
int
-CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
@@ -2432,7 +2432,7 @@ QFSDeviceRetry:
}
int
-CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage)
{
/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
@@ -2512,7 +2512,7 @@ QFSUnixRetry:
in Samba which this routine can run into */
int
-CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
+CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
__u64 size, int SetAllocation, const struct nls_table *nls_codepage)
{
struct smb_com_transaction2_spi_req *pSMB = NULL;
@@ -2692,8 +2692,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
}
int
-CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
- FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
+CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+ const FILE_BASIC_INFO * data,
+ const struct nls_table *nls_codepage)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -2770,6 +2771,89 @@ SetTimesRetry:
return rc;
}
+
+int
+CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+ FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ char *data_offset;
+
+ cFYI(1, ("In SetTimesLegacy"));
+
+SetTimesRetryLegacy:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
+ in parent function, from the better and ususal FILE_BASIC_INFO */
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ /* I doubt that passthrough levels apply to this old
+ preNT info level */
+/* if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+ else*/
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetTimesRetryLegacy;
+
+ return rc;
+}
+
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 mode, __u64 uid, __u64 gid,
@@ -2915,10 +2999,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
return rc;
}
#ifdef CONFIG_CIFS_XATTR
-int
+ssize_t
CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
- char * EAData, size_t size,
+ char * EAData, size_t buf_size,
const struct nls_table *nls_codepage)
{
/* BB assumes one setup word */
@@ -2927,6 +3011,8 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned;
int name_len;
+ struct fea * temp_fea;
+ char * temp_ptr;
cFYI(1, ("In Query All EAs path %s", searchName));
QAllEAsRetry:
@@ -2942,7 +3028,7 @@ QAllEAsRetry:
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
+ } else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
@@ -3001,7 +3087,53 @@ QAllEAsRetry:
ea_response_data = (struct fealist *)
(((char *) &pSMBr->hdr.Protocol) +
pSMBr->DataOffset);
+ ea_response_data->list_len =
+ cpu_to_le32(ea_response_data->list_len);
cFYI(1,("ea length %d",ea_response_data->list_len));
+ name_len = ea_response_data->list_len;
+ if(name_len <= 8) {
+ /* returned EA size zeroed at top of function */
+ cFYI(1,("empty EA list returned from server"));
+ } else {
+ /* account for ea list len */
+ name_len -= 4;
+ temp_fea = ea_response_data->list;
+ temp_ptr = (char *)temp_fea;
+ while(name_len > 0) {
+ name_len -= 4;
+ temp_ptr += 4;
+ rc += temp_fea->name_len;
+ /* account for prefix user. and trailing null */
+ rc = rc + 5 + 1;
+ if(rc<buf_size) {
+ memcpy(EAData,"user.",5);
+ EAData+=5;
+ memcpy(EAData,temp_ptr,temp_fea->name_len);
+ EAData+=temp_fea->name_len;
+ /* null terminate name */
+ *EAData = 0;
+ EAData = EAData + 1;
+ } else if(buf_size == 0) {
+ /* skip copy - calc size only */
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ break;
+ }
+ name_len -= temp_fea->name_len;
+ temp_ptr += temp_fea->name_len;
+ /* account for trailing null */
+ name_len--;
+ temp_ptr++;
+ temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+ name_len -= temp_fea->value_len;
+ temp_ptr += temp_fea->value_len;
+ /* BB check that temp_ptr is still within smb BB*/
+ /* no trailing null to account for in value len */
+ /* go on to next EA */
+ temp_fea = (struct fea *)temp_ptr;
+ }
+ }
}
}
if (pSMB)
@@ -3011,4 +3143,255 @@ QAllEAsRetry:
return rc;
}
+
+ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+ const unsigned char * searchName,const unsigned char * ea_name,
+ unsigned char * ea_value, size_t buf_size,
+ const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ struct fea * temp_fea;
+ char * temp_ptr;
+
+ cFYI(1, ("In Query EA path %s", searchName));
+QEARetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
+ name_len /* includes null */ ;
+ 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 */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in Query EA = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ /* BB also check enough total bytes returned */
+ /* BB we need to improve the validity checking
+ of these trans2 responses */
+ if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
+ rc = -EIO; /* bad smb */
+ /* else if (pFindData){
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset, kl);
+ }*/ else {
+ /* check that length of list is not more than bcc */
+ /* check that each entry does not go beyond length
+ of list */
+ /* check that each element of each entry does not
+ go beyond end of list */
+ struct fealist * ea_response_data;
+ rc = -ENOENT;
+ /* validate_trans2_offsets() */
+ /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+ ea_response_data = (struct fealist *)
+ (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ ea_response_data->list_len =
+ cpu_to_le32(ea_response_data->list_len);
+ cFYI(1,("ea length %d",ea_response_data->list_len));
+ name_len = ea_response_data->list_len;
+ if(name_len <= 8) {
+ /* returned EA size zeroed at top of function */
+ cFYI(1,("empty EA list returned from server"));
+ } else {
+ /* account for ea list len */
+ name_len -= 4;
+ temp_fea = ea_response_data->list;
+ temp_ptr = (char *)temp_fea;
+ /* loop through checking if we have a matching
+ name and then return the associated value */
+ while(name_len > 0) {
+ name_len -= 4;
+ temp_ptr += 4;
+ temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+ /* BB validate that value_len falls within SMB,
+ even though maximum for name_len is 255 */
+ if(memcmp(temp_fea->name,ea_name,
+ temp_fea->name_len) == 0) {
+ /* found a match */
+ rc = temp_fea->value_len;
+ /* account for prefix user. and trailing null */
+ if(rc<=buf_size) {
+ memcpy(ea_value,
+ temp_fea->name+temp_fea->name_len+1,
+ rc);
+ /* ea values, unlike ea names,
+ are not null terminated */
+ } else if(buf_size == 0) {
+ /* skip copy - calc size only */
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ }
+ break;
+ }
+ name_len -= temp_fea->name_len;
+ temp_ptr += temp_fea->name_len;
+ /* account for trailing null */
+ name_len--;
+ temp_ptr++;
+ name_len -= temp_fea->value_len;
+ temp_ptr += temp_fea->value_len;
+ /* no trailing null to account for in value len */
+ /* go on to next EA */
+ temp_fea = (struct fea *)temp_ptr;
+ }
+ }
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QEARetry;
+
+ return rc;
+}
+
+int
+CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+ const char * ea_name, const void * ea_value,
+ const __u16 ea_value_len, const struct nls_table *nls_codepage)
+{
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ struct fealist *parm_data;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In SetEA"));
+SetEARetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+
+ pSMB->ParameterCount = 6 + name_len;
+
+ /* done calculating parms using name_len of file name,
+ now use name_len to calculate length of ea name
+ we are going to create in the inode xattrs */
+ if(ea_name == NULL)
+ name_len = 0;
+ else
+ name_len = strnlen(ea_name,255);
+
+ pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_EA);
+
+ parm_data =
+ (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
+ pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ parm_data->list_len = (__u32)(pSMB->DataCount);
+ parm_data->list[0].EA_flags = 0;
+ /* we checked above that name len is less than 255 */
+ parm_data->list[0].name_len = (__u8)name_len;;
+ /* EA names are always ASCII */
+ strncpy(parm_data->list[0].name,ea_name,name_len);
+ parm_data->list[0].name[name_len] = 0;
+ parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
+ /* caller ensures that ea_value_len is less than 64K but
+ we need to ensure that it fits within the smb */
+
+ /*BB add length check that it would fit in negotiated SMB buffer size BB */
+ /* if(ea_value_len > buffer_size - 512 (enough for header)) */
+ if(ea_value_len)
+ memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
+
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("SetPathInfo (EA) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetEARetry;
+
+ return rc;
+}
+
#endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5c84f9b86993..bb6b0f3b2fb2 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -28,6 +28,7 @@
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
+#include <linux/mempool.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include "cifspdu.h"
@@ -49,6 +50,8 @@ extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
extern int cifs_inet_pton(int, const char *, void *dst);
+extern mempool_t *cifs_req_poolp;
+
struct smb_vol {
char *username;
char *password;
@@ -64,6 +67,8 @@ struct smb_vol {
int rw:1;
int retry:1;
int intr:1;
+ int setuids:1;
+ int noperm:1;
unsigned int rsize;
unsigned int wsize;
unsigned int sockopt;
@@ -202,6 +207,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
current->flags |= PF_MEMALLOC;
server->tsk = current; /* save process info to wake at shutdown */
cFYI(1, ("Demultiplex PID: %d", current->pid));
+ write_lock(&GlobalSMBSeslock);
+ atomic_inc(&tcpSesAllocCount);
+ length = tcpSesAllocCount.counter;
+ write_unlock(&GlobalSMBSeslock);
+ if(length > 1) {
+ mempool_resize(cifs_req_poolp,
+ length + CIFS_MIN_RCV_POOL,
+ GFP_KERNEL);
+ }
while (server->tcpStatus != CifsExiting) {
if (smb_buffer == NULL)
@@ -465,6 +479,16 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
kfree(server);
+ write_lock(&GlobalSMBSeslock);
+ atomic_dec(&tcpSesAllocCount);
+ length = tcpSesAllocCount.counter;
+ write_unlock(&GlobalSMBSeslock);
+ if(length > 0) {
+ mempool_resize(cifs_req_poolp,
+ length + CIFS_MIN_RCV_POOL,
+ GFP_KERNEL);
+ }
+
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/4);
return 0;
@@ -740,6 +764,14 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
vol->retry = 1;
} else if (strnicmp(data, "soft", 4) == 0) {
vol->retry = 0;
+ } else if (strnicmp(data, "perm", 4) == 0) {
+ vol->noperm = 0;
+ } else if (strnicmp(data, "noperm", 6) == 0) {
+ vol->noperm = 1;
+ } else if (strnicmp(data, "setuids", 7) == 0) {
+ vol->setuids = 1;
+ } else if (strnicmp(data, "nosetuids", 9) == 0) {
+ vol->setuids = 0;
} else if (strnicmp(data, "nohard", 6) == 0) {
vol->retry = 0;
} else if (strnicmp(data, "nosoft", 6) == 0) {
@@ -1314,6 +1346,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_file_mode = volume_info.file_mode;
cifs_sb->mnt_dir_mode = volume_info.dir_mode;
cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+
+ if(volume_info.noperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+ if(volume_info.setuids)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+
tcon =
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
volume_info.username);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 95d68da2aaff..91567f61d6dd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -243,11 +243,19 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(oplock & CIFS_CREATE_ACTION))
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+ (__u64)current->euid,
+ (__u64)current->egid,
+ 0 /* dev */,
+ cifs_sb->local_nls);
+ } else {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
+ }
else {
/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
@@ -348,9 +356,16 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
rc = -ENOMEM;
if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
- rc = CIFSSMBUnixSetPerms(xid, pTcon,
- full_path, mode, current->euid, current->egid,
- device_number, cifs_sb->local_nls);
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode,(__u64)current->euid,(__u64)current->egid,
+ device_number, cifs_sb->local_nls);
+ } else {
+ rc = CIFSSMBUnixSetPerms(xid, pTcon,
+ full_path, mode, (__u64)-1, (__u64)-1,
+ device_number, cifs_sb->local_nls);
+ }
+
if(!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8434166488b2..a2965cfd3559 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -480,12 +480,20 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
d_instantiate(direntry, newinode);
if(direntry->d_inode)
direntry->d_inode->i_nlink = 2;
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)-1,
- (__u64)-1,
- 0 /* dev_t */,
- cifs_sb->local_nls);
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+ (__u64)current->euid,
+ (__u64)current->egid,
+ 0 /* dev_t */,
+ cifs_sb->local_nls);
+ } else {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+ (__u64)-1,
+ (__u64)-1,
+ 0 /* dev_t */,
+ cifs_sb->local_nls);
+ }
else { /* BB to be implemented via Windows secrty descriptors*/
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
}
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 18329601b5a9..c6dfc2277cbb 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -70,8 +70,6 @@ void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
void NTLMSSPOWFencrypt(unsigned char passwd[8],
unsigned char *ntlmchalresp, unsigned char p24[24]);
void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
-int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
- int new_pwrd_size, __u32 * new_pw_len);
/*
This implements the X/Open SMB password encryption
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 25a39bf34f58..8db20a0f7edf 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/smberr.h
*
- * Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) International Business Machines Corp., 2002,2004
* Author(s): Steve French (sfrench@us.ibm.com)
*
* See Error Codes section of the SNIA CIFS Specification
@@ -60,6 +60,7 @@
#define ERRinvparm 87
#define ERRdiskfull 112
#define ERRinvname 123
+#define ERRinvlevel 124
#define ERRdirnotempty 145
#define ERRnotlocked 158
#define ERRalreadyexists 183
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index dd6a2c08cd73..5380c349b7db 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -26,27 +26,178 @@
#include "cifsproto.h"
#include "cifs_debug.h"
-int cifs_removexattr(struct dentry * direntry, const char * name)
+#define MAX_EA_VALUE_SIZE 65535
+#define CIFS_XATTR_DOS_ATTRIB "user.DOSATTRIB"
+#define CIFS_XATTR_USER_PREFIX "user."
+#define CIFS_XATTR_SYSTEM_PREFIX "system."
+#define CIFS_XATTR_OS2_PREFIX "OS2." /* BB should check for this someday */
+/* also note could add check for security prefix XATTR_SECURITY_PREFIX */
+
+
+int cifs_removexattr(struct dentry * direntry, const char * ea_name)
{
int rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct super_block * sb;
+ char * full_path;
+
+ if(direntry == NULL)
+ return -EIO;
+ if(direntry->d_inode == NULL)
+ return -EIO;
+ sb = direntry->d_inode->i_sb;
+ if(sb == NULL)
+ return -EIO;
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ if(ea_name == NULL) {
+ cFYI(1,("Null xattr names not supported"));
+ } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+ cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+ /* BB what if no namespace prefix? */
+ /* Should we just pass them to server, except for
+ system and perhaps security prefixes? */
+ } else {
+ ea_name+=5; /* skip past user. prefix */
+ rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,0,
+ (__u16)0, cifs_sb->local_nls);
+ }
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+#endif
return rc;
}
-int cifs_setxattr(struct dentry * direntry, const char * name,
- const void * value, size_t size, int flags)
+int cifs_setxattr(struct dentry * direntry, const char * ea_name,
+ const void * ea_value, size_t value_size, int flags)
{
int rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct super_block * sb;
+ char * full_path;
+
+ if(direntry == NULL)
+ return -EIO;
+ if(direntry->d_inode == NULL)
+ return -EIO;
+ sb = direntry->d_inode->i_sb;
+ if(sb == NULL)
+ return -EIO;
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ /* return dos attributes as pseudo xattr */
+ /* return alt name if available as pseudo attr */
+
+ /* if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+ if(value_size > MAX_EA_VALUE_SIZE) {
+ cFYI(1,("size of EA value too large"));
+ if(full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return -EOPNOTSUPP;
+ }
+
+ if(ea_name == NULL) {
+ cFYI(1,("Null xattr names not supported"));
+ } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+ cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+ /* BB what if no namespace prefix? */
+ /* Should we just pass them to server, except for
+ system and perhaps security prefixes? */
+ } else {
+ ea_name+=5; /* skip past user. prefix */
+ rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
+ (__u16)value_size, cifs_sb->local_nls);
+ }
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+#endif
return rc;
}
-ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
- void * value, size_t size)
+ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
+ void * ea_value, size_t buf_size)
{
ssize_t rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct super_block * sb;
+ char * full_path;
+
+ if(direntry == NULL)
+ return -EIO;
+ if(direntry->d_inode == NULL)
+ return -EIO;
+ sb = direntry->d_inode->i_sb;
+ if(sb == NULL)
+ return -EIO;
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ /* return dos attributes as pseudo xattr */
+ /* return alt name if available as pseudo attr */
+ if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+ cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+ /* BB what if no namespace prefix? */
+ /* Should we just pass them to server, except for system? */
+ } else {
+ /* We could add a check here
+ if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+ ea_name+=5; /* skip past user. */
+ rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
+ buf_size, cifs_sb->local_nls);
+ }
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+#endif
return rc;
}
-ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
+ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
{
ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
@@ -55,6 +206,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
struct cifsTconInfo *pTcon;
struct super_block * sb;
char * full_path;
+
if(direntry == NULL)
return -EIO;
if(direntry->d_inode == NULL)
@@ -74,13 +226,17 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
FreeXid(xid);
return -ENOMEM;
}
- /* return dosattributes as pseudo xattr */
+ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
- rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size,cifs_sb->local_nls);
+ rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
+ cifs_sb->local_nls);
+
+ if (full_path)
+ kfree(full_path);
FreeXid(xid);
#endif
return rc;
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 57b2cc4761e3..08b8ebddefd3 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -37,7 +37,7 @@ config NET_SCH_CLK_GETTIMEOFDAY
config NET_SCH_CLK_CPU
bool "CPU cycle counter"
- depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64
+ depends on X86_TSC || X86_64 || SPARC64 || PPC64 || IA64
help
Say Y here if you want to use the CPU's cycle counter as clock source.
This is a cheap and high resolution clock source, but on some
@@ -47,7 +47,6 @@ config NET_SCH_CLK_CPU
The useable cycle counters are:
x86/x86_64 - Timestamp Counter
- alpha - Cycle Counter
sparc64 - %ticks register
ppc64 - Time base
ia64 - Interval Time Counter