[CIFS] Support deep tree mounts (e.g. mounts to //server/share/path)
Samba bugzilla #4040 Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Родитель
b835bebe95
Коммит
2fe87f02a0
|
@ -1,3 +1,7 @@
|
||||||
|
Version 1.46
|
||||||
|
------------
|
||||||
|
Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps.
|
||||||
|
|
||||||
Version 1.45
|
Version 1.45
|
||||||
------------
|
------------
|
||||||
Do not time out lockw calls when using posix extensions. Do not
|
Do not time out lockw calls when using posix extensions. Do not
|
||||||
|
@ -6,7 +10,8 @@ on requests on other threads. Improve POSIX locking emulation,
|
||||||
(lock cancel now works, and unlock of merged range works even
|
(lock cancel now works, and unlock of merged range works even
|
||||||
to Windows servers now). Fix oops on mount to lanman servers
|
to Windows servers now). Fix oops on mount to lanman servers
|
||||||
(win9x, os/2 etc.) when null password. Do not send listxattr
|
(win9x, os/2 etc.) when null password. Do not send listxattr
|
||||||
(SMB to query all EAs) if nouser_xattr specified.
|
(SMB to query all EAs) if nouser_xattr specified. Fix SE Linux
|
||||||
|
problem (instantiate inodes/dentries in right order for readdir).
|
||||||
|
|
||||||
Version 1.44
|
Version 1.44
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -40,5 +40,7 @@ struct cifs_sb_info {
|
||||||
mode_t mnt_file_mode;
|
mode_t mnt_file_mode;
|
||||||
mode_t mnt_dir_mode;
|
mode_t mnt_dir_mode;
|
||||||
int mnt_cifs_flags;
|
int mnt_cifs_flags;
|
||||||
|
int prepathlen;
|
||||||
|
char * prepath;
|
||||||
};
|
};
|
||||||
#endif /* _CIFS_FS_SB_H */
|
#endif /* _CIFS_FS_SB_H */
|
||||||
|
|
|
@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||||
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
unsigned int command, unsigned long arg);
|
unsigned int command, unsigned long arg);
|
||||||
#define CIFS_VERSION "1.45"
|
#define CIFS_VERSION "1.46"
|
||||||
#endif /* _CIFSFS_H */
|
#endif /* _CIFSFS_H */
|
||||||
|
|
|
@ -1344,6 +1344,7 @@ struct smb_t2_rsp {
|
||||||
#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
|
#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
|
||||||
#define SMB_QUERY_POSIX_PERMISSION 0x207
|
#define SMB_QUERY_POSIX_PERMISSION 0x207
|
||||||
#define SMB_QUERY_POSIX_LOCK 0x208
|
#define SMB_QUERY_POSIX_LOCK 0x208
|
||||||
|
/* #define SMB_POSIX_OPEN 0x209 */
|
||||||
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
|
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
|
||||||
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
|
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
|
||||||
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
|
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
|
||||||
|
@ -1363,6 +1364,7 @@ struct smb_t2_rsp {
|
||||||
#define SMB_SET_XATTR 0x205
|
#define SMB_SET_XATTR 0x205
|
||||||
#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
|
#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
|
||||||
#define SMB_SET_POSIX_LOCK 0x208
|
#define SMB_SET_POSIX_LOCK 0x208
|
||||||
|
#define SMB_POSIX_OPEN 0x209
|
||||||
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
|
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
|
||||||
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
|
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
|
||||||
#define SMB_FILE_ALL_INFO2 0x3fa
|
#define SMB_FILE_ALL_INFO2 0x3fa
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct smb_vol {
|
||||||
unsigned int wsize;
|
unsigned int wsize;
|
||||||
unsigned int sockopt;
|
unsigned int sockopt;
|
||||||
unsigned short int port;
|
unsigned short int port;
|
||||||
|
char * prepath;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ipv4_connect(struct sockaddr_in *psin_server,
|
static int ipv4_connect(struct sockaddr_in *psin_server,
|
||||||
|
@ -993,6 +994,28 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
printk(KERN_WARNING "CIFS: domain name too long\n");
|
printk(KERN_WARNING "CIFS: domain name too long\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (strnicmp(data, "prefixpath", 10) == 0) {
|
||||||
|
if (!value || !*value) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"CIFS: invalid path prefix\n");
|
||||||
|
return 1; /* needs_arg; */
|
||||||
|
}
|
||||||
|
if ((temp_len = strnlen(value, 1024)) < 1024) {
|
||||||
|
if(value[0] != '/')
|
||||||
|
temp_len++; /* missing leading slash */
|
||||||
|
vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
|
||||||
|
if(vol->prepath == NULL)
|
||||||
|
return 1;
|
||||||
|
if(value[0] != '/') {
|
||||||
|
vol->prepath[0] = '/';
|
||||||
|
strcpy(vol->prepath+1,value);
|
||||||
|
} else
|
||||||
|
strcpy(vol->prepath,value);
|
||||||
|
cFYI(1,("prefix path %s",vol->prepath));
|
||||||
|
} else {
|
||||||
|
printk(KERN_WARNING "CIFS: prefix too long\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if (strnicmp(data, "iocharset", 9) == 0) {
|
} else if (strnicmp(data, "iocharset", 9) == 0) {
|
||||||
if (!value || !*value) {
|
if (!value || !*value) {
|
||||||
printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
|
printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
|
||||||
|
@ -1605,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
|
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1619,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
locations such as env variables and files on disk */
|
locations such as env variables and files on disk */
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1639,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
/* we failed translating address */
|
/* we failed translating address */
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1651,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
cERROR(1,("Connecting to DFS root not implemented yet"));
|
cERROR(1,("Connecting to DFS root not implemented yet"));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else /* which servers DFS root would we conect to */ {
|
} else /* which servers DFS root would we conect to */ {
|
||||||
|
@ -1658,6 +1685,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
|
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1672,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
|
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ELIBACC;
|
return -ELIBACC;
|
||||||
}
|
}
|
||||||
|
@ -1688,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
else {
|
else {
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1710,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
sock_release(csocket);
|
sock_release(csocket);
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1720,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
sock_release(csocket);
|
sock_release(csocket);
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1744,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
sock_release(csocket);
|
sock_release(csocket);
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1831,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
/* Windows ME may prefer this */
|
/* Windows ME may prefer this */
|
||||||
cFYI(1,("readsize set to minimum 2048"));
|
cFYI(1,("readsize set to minimum 2048"));
|
||||||
}
|
}
|
||||||
|
/* calculate prepath */
|
||||||
|
cifs_sb->prepath = volume_info.prepath;
|
||||||
|
if(cifs_sb->prepath) {
|
||||||
|
cifs_sb->prepathlen = strlen(cifs_sb->prepath);
|
||||||
|
cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
|
||||||
|
volume_info.prepath = NULL;
|
||||||
|
} else
|
||||||
|
cifs_sb->prepathlen = 0;
|
||||||
cifs_sb->mnt_uid = volume_info.linux_uid;
|
cifs_sb->mnt_uid = volume_info.linux_uid;
|
||||||
cifs_sb->mnt_gid = volume_info.linux_gid;
|
cifs_sb->mnt_gid = volume_info.linux_gid;
|
||||||
cifs_sb->mnt_file_mode = volume_info.file_mode;
|
cifs_sb->mnt_file_mode = volume_info.file_mode;
|
||||||
|
@ -2008,6 +2049,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
the password ptr is put in the new session structure (in which case the
|
the password ptr is put in the new session structure (in which case the
|
||||||
password will be freed at unmount time) */
|
password will be freed at unmount time) */
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
|
kfree(volume_info.prepath);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -3195,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
||||||
int xid;
|
int xid;
|
||||||
struct cifsSesInfo *ses = NULL;
|
struct cifsSesInfo *ses = NULL;
|
||||||
struct task_struct *cifsd_task;
|
struct task_struct *cifsd_task;
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
|
@ -3228,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_sb->tcon = NULL;
|
cifs_sb->tcon = NULL;
|
||||||
|
tmp = cifs_sb->prepath;
|
||||||
|
cifs_sb->prepathlen = 0;
|
||||||
|
cifs_sb->prepath = NULL;
|
||||||
|
kfree(tmp);
|
||||||
if (ses)
|
if (ses)
|
||||||
schedule_timeout_interruptible(msecs_to_jiffies(500));
|
schedule_timeout_interruptible(msecs_to_jiffies(500));
|
||||||
if (ses)
|
if (ses)
|
||||||
|
|
|
@ -46,7 +46,8 @@ char *
|
||||||
build_path_from_dentry(struct dentry *direntry)
|
build_path_from_dentry(struct dentry *direntry)
|
||||||
{
|
{
|
||||||
struct dentry *temp;
|
struct dentry *temp;
|
||||||
int namelen = 0;
|
int namelen;
|
||||||
|
int pplen;
|
||||||
char *full_path;
|
char *full_path;
|
||||||
char dirsep;
|
char dirsep;
|
||||||
|
|
||||||
|
@ -56,7 +57,9 @@ build_path_from_dentry(struct dentry *direntry)
|
||||||
when the server crashed */
|
when the server crashed */
|
||||||
|
|
||||||
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
||||||
|
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
|
||||||
cifs_bp_rename_retry:
|
cifs_bp_rename_retry:
|
||||||
|
namelen = pplen;
|
||||||
for (temp = direntry; !IS_ROOT(temp);) {
|
for (temp = direntry; !IS_ROOT(temp);) {
|
||||||
namelen += (1 + temp->d_name.len);
|
namelen += (1 + temp->d_name.len);
|
||||||
temp = temp->d_parent;
|
temp = temp->d_parent;
|
||||||
|
@ -70,7 +73,6 @@ cifs_bp_rename_retry:
|
||||||
if(full_path == NULL)
|
if(full_path == NULL)
|
||||||
return full_path;
|
return full_path;
|
||||||
full_path[namelen] = 0; /* trailing null */
|
full_path[namelen] = 0; /* trailing null */
|
||||||
|
|
||||||
for (temp = direntry; !IS_ROOT(temp);) {
|
for (temp = direntry; !IS_ROOT(temp);) {
|
||||||
namelen -= 1 + temp->d_name.len;
|
namelen -= 1 + temp->d_name.len;
|
||||||
if (namelen < 0) {
|
if (namelen < 0) {
|
||||||
|
@ -79,7 +81,7 @@ cifs_bp_rename_retry:
|
||||||
full_path[namelen] = dirsep;
|
full_path[namelen] = dirsep;
|
||||||
strncpy(full_path + namelen + 1, temp->d_name.name,
|
strncpy(full_path + namelen + 1, temp->d_name.name,
|
||||||
temp->d_name.len);
|
temp->d_name.len);
|
||||||
cFYI(0, (" name: %s ", full_path + namelen));
|
cFYI(0, ("name: %s", full_path + namelen));
|
||||||
}
|
}
|
||||||
temp = temp->d_parent;
|
temp = temp->d_parent;
|
||||||
if(temp == NULL) {
|
if(temp == NULL) {
|
||||||
|
@ -88,18 +90,23 @@ cifs_bp_rename_retry:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (namelen != 0) {
|
if (namelen != pplen) {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
("We did not end path lookup where we expected namelen is %d",
|
("did not end path lookup where expected namelen is %d",
|
||||||
namelen));
|
namelen));
|
||||||
/* presumably this is only possible if we were racing with a rename
|
/* presumably this is only possible if racing with a rename
|
||||||
of one of the parent directories (we can not lock the dentries
|
of one of the parent directories (we can not lock the dentries
|
||||||
above us to prevent this, but retrying should be harmless) */
|
above us to prevent this, but retrying should be harmless) */
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
namelen = 0;
|
|
||||||
goto cifs_bp_rename_retry;
|
goto cifs_bp_rename_retry;
|
||||||
}
|
}
|
||||||
|
/* DIR_SEP already set for byte 0 / vs \ but not for
|
||||||
|
subsequent slashes in prepath which currently must
|
||||||
|
be entered the right way - not sure if there is an alternative
|
||||||
|
since the '\' is a valid posix character so we can not switch
|
||||||
|
those safely to '/' if any are found in the middle of the prepath */
|
||||||
|
/* BB test paths to Windows with '/' in the midst of prepath */
|
||||||
|
strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
|
||||||
return full_path;
|
return full_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
||||||
ea_value, buf_size,
|
ea_value, buf_size,
|
||||||
ACL_TYPE_ACCESS);
|
ACL_TYPE_ACCESS);
|
||||||
CIFSSMBClose(xid, pTcon, fid)
|
CIFSSMBClose(xid, pTcon, fid);
|
||||||
}
|
}
|
||||||
} */ /* BB enable after fixing up return data */
|
} */ /* BB enable after fixing up return data */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче