Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 12001
b: refs/heads/master
c: ac67055
h: refs/heads/master
i:
  11999: 0b015c0
v: v3
  • Loading branch information
Jeremy Allison authored and Steve French committed Jun 23, 2005
1 parent 4c72a48 commit f58ffc6
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dfb7533b5f157ac7135da23883e80d895227d965
refs/heads/master: ac67055ef2378ea95c34b593ddf9d0a0737a240a
1 change: 1 addition & 0 deletions trunk/fs/cifs/cifs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */

struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
Expand Down
7 changes: 7 additions & 0 deletions trunk/fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,13 @@ CIFS_SB(struct super_block *sb)
return sb->s_fs_info;
}

static inline const char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
return '/';
else
return '\\';
}

/* one of these for every pending CIFS request to the server */
struct mid_q_entry {
Expand Down
46 changes: 46 additions & 0 deletions trunk/fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#define TRANS2_FIND_FIRST 0x01
#define TRANS2_FIND_NEXT 0x02
#define TRANS2_QUERY_FS_INFORMATION 0x03
#define TRANS2_SET_FS_INFORMATION 0x04
#define TRANS2_QUERY_PATH_INFORMATION 0x05
#define TRANS2_SET_PATH_INFORMATION 0x06
#define TRANS2_QUERY_FILE_INFORMATION 0x07
Expand Down Expand Up @@ -1411,6 +1412,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
__u8 Pad; /* may be three bytes *//* followed by data area */
} TRANSACTION2_QFSI_RSP;


/* SETFSInfo Levels */
#define SMB_SET_CIFS_UNIX_INFO 0x200
typedef struct smb_com_transaction2_setfsi_req {
struct smb_hdr hdr; /* wct = 15 */
__le16 TotalParameterCount;
__le16 TotalDataCount;
__le16 MaxParameterCount;
__le16 MaxDataCount;
__u8 MaxSetupCount;
__u8 Reserved;
__le16 Flags;
__le32 Timeout;
__u16 Reserved2;
__le16 ParameterCount; /* 4 */
__le16 ParameterOffset;
__le16 DataCount; /* 12 */
__le16 DataOffset;
__u8 SetupCount; /* one */
__u8 Reserved3;
__le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
__le16 ByteCount;
__u8 Pad;
__u16 FileNum; /* Parameters start. */
__le16 InformationLevel;/* Parameters end. */
__le16 ClientUnixMajor; /* Data start. */
__le16 ClientUnixMinor;
__le64 ClientUnixCap; /* Data end */
} TRANSACTION2_SETFSI_REQ;

typedef struct smb_com_transaction2_setfsi_rsp {
struct smb_hdr hdr; /* wct = 10 */
struct trans2_resp t2;
__u16 ByteCount;
} TRANSACTION2_SETFSI_RSP;


typedef struct smb_com_transaction2_get_dfs_refer_req {
struct smb_hdr hdr; /* wct = 15 */
__le16 TotalParameterCount;
Expand Down Expand Up @@ -1551,12 +1589,20 @@ typedef struct {
__le16 MinorVersionNumber;
__le64 Capability;
} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */

/* Version numbers for CIFS UNIX major and minor. */
#define CIFS_UNIX_MAJOR_VERSION 1
#define CIFS_UNIX_MINOR_VERSION 0

/* Linux/Unix extensions capability flags */
#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
#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_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */

#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 */
Expand Down
7 changes: 5 additions & 2 deletions trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
extern char *build_path_from_dentry(struct dentry *);
extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern void renew_parental_timestamps(struct dentry *direntry);
extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
Expand Down Expand Up @@ -89,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,

extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName, const struct nls_table *nls_codepage,
__u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
__u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);

extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
__u16 searchHandle, struct cifs_search_info * psrch_inf);
Expand Down Expand Up @@ -125,6 +125,9 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
int remap);
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct kstatfs *FSData);
extern int CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
__u64 cap);

extern int CIFSSMBQFSAttributeInfo(const int xid,
struct cifsTconInfo *tcon);
extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
Expand Down
77 changes: 74 additions & 3 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName,
const struct nls_table *nls_codepage,
__u16 * pnetfid,
struct cifs_search_info * psrch_inf, int remap)
struct cifs_search_info * psrch_inf, int remap, const char dirsep)
{
/* level 257 SMB_ */
TRANSACTION2_FFIRST_REQ *pSMB = NULL;
Expand All @@ -2443,7 +2443,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
it got remapped to 0xF03A as if it were part of the
directory name instead of a wildcard */
name_len *= 2;
pSMB->FileName[name_len] = '\\';
pSMB->FileName[name_len] = dirsep;
pSMB->FileName[name_len+1] = 0;
pSMB->FileName[name_len+2] = '*';
pSMB->FileName[name_len+3] = 0;
Expand All @@ -2457,7 +2457,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
if(name_len > buffersize-header)
free buffer exit; BB */
strncpy(pSMB->FileName, searchName, name_len);
pSMB->FileName[name_len] = '\\';
pSMB->FileName[name_len] = dirsep;
pSMB->FileName[name_len+1] = '*';
pSMB->FileName[name_len+2] = 0;
name_len += 3;
Expand Down Expand Up @@ -3265,6 +3265,77 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
return rc;
}

int
CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
{
/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
TRANSACTION2_SETFSI_REQ *pSMB = NULL;
TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count;

cFYI(1, ("In SETFSUnixInfo"));
SETFSUnixRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;

params = 4; /* 2 bytes zero followed by info level. */
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
offset = param_offset + params;

pSMB->MaxParameterCount = cpu_to_le16(4);
pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
byte_count = 1 /* pad */ + params + 12;

pSMB->DataCount = cpu_to_le16(12);
pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(param_offset);
pSMB->DataOffset = cpu_to_le16(offset);

/* Params. */
pSMB->FileNum = 0;
pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);

/* Data. */
pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
pSMB->ClientUnixCap = cpu_to_le64(cap);

pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);

rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc) {
rc = -EIO; /* bad smb */
}
}
cifs_buf_release(pSMB);

if (rc == -EAGAIN)
goto SETFSUnixRetry;

return rc;
}



int
CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
Expand Down
20 changes: 20 additions & 0 deletions trunk/fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct smb_vol {
unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
unsigned direct_io:1;
unsigned remap:1; /* set to remap seven reserved chars in filenames */
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
unsigned int rsize;
unsigned int wsize;
unsigned int sockopt;
Expand Down Expand Up @@ -745,6 +746,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE;

/* default is always to request posix paths. */
vol->posix_paths = 1;

if (!options)
return 1;

Expand Down Expand Up @@ -1023,6 +1027,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
vol->remap = 1;
} else if (strnicmp(data, "nomapchars", 10) == 0) {
vol->remap = 0;
} else if (strnicmp(data, "posixpaths", 10) == 0) {
vol->posix_paths = 1;
} else if (strnicmp(data, "noposixpaths", 12) == 0) {
vol->posix_paths = 0;
} else if (strnicmp(data, "setuids", 7) == 0) {
vol->setuids = 1;
} else if (strnicmp(data, "nosetuids", 9) == 0) {
Expand Down Expand Up @@ -1679,6 +1687,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
if(volume_info.no_xattr)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;

if(volume_info.direct_io) {
cERROR(1,("mounting share using direct i/o"));
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
Expand Down Expand Up @@ -1781,6 +1790,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cFYI(1,("server negotiated posix acl support"));
sb->s_flags |= MS_POSIXACL;
}

/* Try and negotiate POSIX pathnames if we can. */
if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
if (!CIFSSMBSETFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP, 0)) {
cFYI(1,("negotiated posix pathnames support"));
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
} else {
cFYI(1,("posix pathnames support requested but not supported"));
}
}
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions trunk/fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ renew_parental_timestamps(struct dentry *direntry)

/* Note: caller must free return buffer */
char *
build_path_from_dentry(struct dentry *direntry)
build_path_from_dentry(struct dentry *direntry, const struct cifs_sb_info *cifs_sb)
{
struct dentry *temp;
int namelen = 0;
Expand Down Expand Up @@ -74,7 +74,7 @@ build_path_from_dentry(struct dentry *direntry)
if (namelen < 0) {
break;
} else {
full_path[namelen] = '\\';
full_path[namelen] = CIFS_DIR_SEP(cifs_sb);
strncpy(full_path + namelen + 1, temp->d_name.name,
temp->d_name.len);
cFYI(0, (" name: %s ", full_path + namelen));
Expand Down Expand Up @@ -138,7 +138,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;

down(&direntry->d_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
full_path = build_path_from_dentry(direntry, cifs_sb);
up(&direntry->d_sb->s_vfs_rename_sem);
if(full_path == NULL) {
FreeXid(xid);
Expand Down Expand Up @@ -299,7 +299,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
pTcon = cifs_sb->tcon;

down(&direntry->d_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
full_path = build_path_from_dentry(direntry, cifs_sb);
up(&direntry->d_sb->s_vfs_rename_sem);
if(full_path == NULL)
rc = -ENOMEM;
Expand Down Expand Up @@ -360,7 +360,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
/* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry);
full_path = build_path_from_dentry(direntry, cifs_sb);
if(full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/cifs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
pTcon = cifs_sb->tcon;

down(&file->f_dentry->d_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(file->f_dentry);
full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
up(&file->f_dentry->d_sb->s_vfs_rename_sem);

if(full_path == NULL) {
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ int cifs_open(struct inode *inode, struct file *file)
}

down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(file->f_dentry);
full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
up(&inode->i_sb->s_vfs_rename_sem);
if (full_path == NULL) {
FreeXid(xid);
Expand Down Expand Up @@ -359,7 +359,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
those that already have the rename sem can end up causing writepage
to get called and if the server was down that means we end up here,
and we can never tell if the caller already has the rename_sem */
full_path = build_path_from_dentry(file->f_dentry);
full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
if (full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
Expand Down
Loading

0 comments on commit f58ffc6

Please sign in to comment.