Commit a44280c6 authored by Steve French's avatar Steve French

Extended Attributes part 1

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent e7bba9c2
...@@ -80,27 +80,13 @@ symlink text beginning with slash ...@@ -80,27 +80,13 @@ symlink text beginning with slash
but recognizes them but recognizes them
3) create of new files to FAT partitions on Windows servers can 3) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows succeed but still return access denied (appears to be Windows
not client problem) and has not been reproduced recently. server not cifs client problem) and has not been reproduced recently.
NTFS partitions do not have this problem. NTFS partitions do not have this problem.
4) debug connectation lock test case 10 which fails against 4) debug connectation lock test case 10 which fails against
Samba (may be unmappable due to POSIX to Windows lock model Samba (may be unmappable due to POSIX to Windows lock model
differences but worth investigating). Also debug Samba to differences but worth investigating). Also debug Samba to
see why lock test case 7 takes longer to complete to Samba see why lock test case 7 takes longer to complete to Samba
than to Windows. than to Windows.
5) prepare_write does not initialize pages properly when partial
page writes begin in the middle of a page (pages can get zeroed).
6) Write caching done incorrectly when files are only opened
with write permission by the application.
7) Rename of files that are hardlinked does not work correctly e.g.
ln source target
mv source target
This should be no op since files are linked but in cifs it causes
the source file to go away. This may require implementation of
the cifs POSIX extensions (Unix Extensions version 2) for
it to be done correctly since Samba is failing the rename,
(rather than ignoring it) so the client not knowing they
are linked proceeds to delete the target and then retry the
move which succeeds this time (but the source is gone).
Misc testing to do Misc testing to do
================== ==================
......
...@@ -247,4 +247,8 @@ extern int CIFSSMBCopy(int xid, ...@@ -247,4 +247,8 @@ extern int CIFSSMBCopy(int xid,
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid,__u32 filter, const int notify_subdirs,const __u16 netfid,__u32 filter,
const struct nls_table *nls_codepage); 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);
#endif /* _CIFSPROTO_H */ #endif /* _CIFSPROTO_H */
...@@ -1596,6 +1596,8 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1596,6 +1596,8 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */ } else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
/* BB also check enough total bytes returned */ /* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */ rc = -EIO; /* bad smb */
else if (pFindData){ else if (pFindData){
...@@ -2879,3 +2881,88 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, ...@@ -2879,3 +2881,88 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
goto NotifyRetry; */ goto NotifyRetry; */
return rc; return rc;
} }
#ifdef CONFIG_CIFS_XATTR
int
CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char * EAData, size_t size,
const struct nls_table *nls_codepage)
{
/* BB assumes one setup word */
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned;
int name_len;
cFYI(1, ("In Query All EAs path %s", searchName));
QAllEAsRetry:
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 QueryAllEAs = %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
rc = -ENOMEM;
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QAllEAsRetry;
return rc;
}
#endif
...@@ -20,6 +20,11 @@ ...@@ -20,6 +20,11 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
int cifs_removexattr(struct dentry * direntry, const char * name) int cifs_removexattr(struct dentry * direntry, const char * name)
{ {
...@@ -44,13 +49,39 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * name, ...@@ -44,13 +49,39 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size) ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
{ {
ssize_t rc = -EOPNOTSUPP; ssize_t rc = -EOPNOTSUPP;
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct super_block * sb;
char * full_path;
#ifdef CONFIG_CIFS_XATTR
if(direntry == NULL)
return -EIO;
if(direntry->d_inode)
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 dosattributes as pseudo xattr */ /* return dosattributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then /* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to search server for EAs or streams to
returns as xattrs */ returns as xattrs */
rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size,cifs_sb->local_nls);
FreeXid(xid);
#endif
return rc; return rc;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment