aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-09-21 03:02:52 -0400
committerSteve French <sfrench@us.ibm.com>2006-09-21 03:02:52 -0400
commit2fe87f02a04ad6e7075023a87fe38eb458a4bb9d (patch)
treeec095fecdccad724faa6560cf7a81a9494a5a093
parentb835bebe95608c81270636a78b70333afb011925 (diff)
[CIFS] Support deep tree mounts (e.g. mounts to //server/share/path)
Samba bugzilla #4040 Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/cifs_fs_sb.h2
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifspdu.h2
-rw-r--r--fs/cifs/connect.c47
-rw-r--r--fs/cifs/dir.c23
-rw-r--r--fs/cifs/xattr.c2
7 files changed, 74 insertions, 11 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 0feb3bd49cb8..1eb9a2ec0a3b 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,7 @@
1Version 1.46
2------------
3Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps.
4
1Version 1.45 5Version 1.45
2------------ 6------------
3Do not time out lockw calls when using posix extensions. Do not 7Do not time out lockw calls when using posix extensions. Do not
@@ -6,7 +10,8 @@ on requests on other threads. Improve POSIX locking emulation,
6(lock cancel now works, and unlock of merged range works even 10(lock cancel now works, and unlock of merged range works even
7to Windows servers now). Fix oops on mount to lanman servers 11to Windows servers now). Fix oops on mount to lanman servers
8(win9x, os/2 etc.) when null password. Do not send listxattr 12(win9x, os/2 etc.) when null password. Do not send listxattr
9(SMB to query all EAs) if nouser_xattr specified. 13(SMB to query all EAs) if nouser_xattr specified. Fix SE Linux
14problem (instantiate inodes/dentries in right order for readdir).
10 15
11Version 1.44 16Version 1.44
12------------ 17------------
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ad58eb0c4d6d..fd1e52ebcee6 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -40,5 +40,7 @@ struct cifs_sb_info {
40 mode_t mnt_file_mode; 40 mode_t mnt_file_mode;
41 mode_t mnt_dir_mode; 41 mode_t mnt_dir_mode;
42 int mnt_cifs_flags; 42 int mnt_cifs_flags;
43 int prepathlen;
44 char * prepath;
43}; 45};
44#endif /* _CIFS_FS_SB_H */ 46#endif /* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 39ee8ef3bdeb..bea875d9a46a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
101extern int cifs_ioctl (struct inode * inode, struct file * filep, 101extern int cifs_ioctl (struct inode * inode, struct file * filep,
102 unsigned int command, unsigned long arg); 102 unsigned int command, unsigned long arg);
103#define CIFS_VERSION "1.45" 103#define CIFS_VERSION "1.46"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 86239023545b..81df2bf8e75a 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1344,6 +1344,7 @@ struct smb_t2_rsp {
1344#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ 1344#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1345#define SMB_QUERY_POSIX_PERMISSION 0x207 1345#define SMB_QUERY_POSIX_PERMISSION 0x207
1346#define SMB_QUERY_POSIX_LOCK 0x208 1346#define SMB_QUERY_POSIX_LOCK 0x208
1347/* #define SMB_POSIX_OPEN 0x209 */
1347#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee 1348#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1348#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 1349#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1349#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ 1350#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1363,6 +1364,7 @@ struct smb_t2_rsp {
1363#define SMB_SET_XATTR 0x205 1364#define SMB_SET_XATTR 0x205
1364#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ 1365#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1365#define SMB_SET_POSIX_LOCK 0x208 1366#define SMB_SET_POSIX_LOCK 0x208
1367#define SMB_POSIX_OPEN 0x209
1366#define SMB_SET_FILE_BASIC_INFO2 0x3ec 1368#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1367#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ 1369#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
1368#define SMB_FILE_ALL_INFO2 0x3fa 1370#define SMB_FILE_ALL_INFO2 0x3fa
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5d394c726860..0e9ba0b9d71e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -89,6 +89,7 @@ struct smb_vol {
89 unsigned int wsize; 89 unsigned int wsize;
90 unsigned int sockopt; 90 unsigned int sockopt;
91 unsigned short int port; 91 unsigned short int port;
92 char * prepath;
92}; 93};
93 94
94static int ipv4_connect(struct sockaddr_in *psin_server, 95static 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)
993 printk(KERN_WARNING "CIFS: domain name too long\n"); 994 printk(KERN_WARNING "CIFS: domain name too long\n");
994 return 1; 995 return 1;
995 } 996 }
997 } else if (strnicmp(data, "prefixpath", 10) == 0) {
998 if (!value || !*value) {
999 printk(KERN_WARNING
1000 "CIFS: invalid path prefix\n");
1001 return 1; /* needs_arg; */
1002 }
1003 if ((temp_len = strnlen(value, 1024)) < 1024) {
1004 if(value[0] != '/')
1005 temp_len++; /* missing leading slash */
1006 vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
1007 if(vol->prepath == NULL)
1008 return 1;
1009 if(value[0] != '/') {
1010 vol->prepath[0] = '/';
1011 strcpy(vol->prepath+1,value);
1012 } else
1013 strcpy(vol->prepath,value);
1014 cFYI(1,("prefix path %s",vol->prepath));
1015 } else {
1016 printk(KERN_WARNING "CIFS: prefix too long\n");
1017 return 1;
1018 }
996 } else if (strnicmp(data, "iocharset", 9) == 0) { 1019 } else if (strnicmp(data, "iocharset", 9) == 0) {
997 if (!value || !*value) { 1020 if (!value || !*value) {
998 printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); 1021 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
@@ -1605,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1605 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { 1628 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1606 kfree(volume_info.UNC); 1629 kfree(volume_info.UNC);
1607 kfree(volume_info.password); 1630 kfree(volume_info.password);
1631 kfree(volume_info.prepath);
1608 FreeXid(xid); 1632 FreeXid(xid);
1609 return -EINVAL; 1633 return -EINVAL;
1610 } 1634 }
@@ -1619,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1619 locations such as env variables and files on disk */ 1643 locations such as env variables and files on disk */
1620 kfree(volume_info.UNC); 1644 kfree(volume_info.UNC);
1621 kfree(volume_info.password); 1645 kfree(volume_info.password);
1646 kfree(volume_info.prepath);
1622 FreeXid(xid); 1647 FreeXid(xid);
1623 return -EINVAL; 1648 return -EINVAL;
1624 } 1649 }
@@ -1639,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1639 /* we failed translating address */ 1664 /* we failed translating address */
1640 kfree(volume_info.UNC); 1665 kfree(volume_info.UNC);
1641 kfree(volume_info.password); 1666 kfree(volume_info.password);
1667 kfree(volume_info.prepath);
1642 FreeXid(xid); 1668 FreeXid(xid);
1643 return -EINVAL; 1669 return -EINVAL;
1644 } 1670 }
@@ -1651,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1651 cERROR(1,("Connecting to DFS root not implemented yet")); 1677 cERROR(1,("Connecting to DFS root not implemented yet"));
1652 kfree(volume_info.UNC); 1678 kfree(volume_info.UNC);
1653 kfree(volume_info.password); 1679 kfree(volume_info.password);
1680 kfree(volume_info.prepath);
1654 FreeXid(xid); 1681 FreeXid(xid);
1655 return -EINVAL; 1682 return -EINVAL;
1656 } else /* which servers DFS root would we conect to */ { 1683 } 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,
1658 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); 1685 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1659 kfree(volume_info.UNC); 1686 kfree(volume_info.UNC);
1660 kfree(volume_info.password); 1687 kfree(volume_info.password);
1688 kfree(volume_info.prepath);
1661 FreeXid(xid); 1689 FreeXid(xid);
1662 return -EINVAL; 1690 return -EINVAL;
1663 } 1691 }
@@ -1672,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1672 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); 1700 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1673 kfree(volume_info.UNC); 1701 kfree(volume_info.UNC);
1674 kfree(volume_info.password); 1702 kfree(volume_info.password);
1703 kfree(volume_info.prepath);
1675 FreeXid(xid); 1704 FreeXid(xid);
1676 return -ELIBACC; 1705 return -ELIBACC;
1677 } 1706 }
@@ -1688,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1688 else { 1717 else {
1689 kfree(volume_info.UNC); 1718 kfree(volume_info.UNC);
1690 kfree(volume_info.password); 1719 kfree(volume_info.password);
1720 kfree(volume_info.prepath);
1691 FreeXid(xid); 1721 FreeXid(xid);
1692 return -EINVAL; 1722 return -EINVAL;
1693 } 1723 }
@@ -1710,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1710 sock_release(csocket); 1740 sock_release(csocket);
1711 kfree(volume_info.UNC); 1741 kfree(volume_info.UNC);
1712 kfree(volume_info.password); 1742 kfree(volume_info.password);
1743 kfree(volume_info.prepath);
1713 FreeXid(xid); 1744 FreeXid(xid);
1714 return rc; 1745 return rc;
1715 } 1746 }
@@ -1720,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1720 sock_release(csocket); 1751 sock_release(csocket);
1721 kfree(volume_info.UNC); 1752 kfree(volume_info.UNC);
1722 kfree(volume_info.password); 1753 kfree(volume_info.password);
1754 kfree(volume_info.prepath);
1723 FreeXid(xid); 1755 FreeXid(xid);
1724 return rc; 1756 return rc;
1725 } else { 1757 } else {
@@ -1744,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1744 sock_release(csocket); 1776 sock_release(csocket);
1745 kfree(volume_info.UNC); 1777 kfree(volume_info.UNC);
1746 kfree(volume_info.password); 1778 kfree(volume_info.password);
1779 kfree(volume_info.prepath);
1747 FreeXid(xid); 1780 FreeXid(xid);
1748 return rc; 1781 return rc;
1749 } 1782 }
@@ -1831,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1831 /* Windows ME may prefer this */ 1864 /* Windows ME may prefer this */
1832 cFYI(1,("readsize set to minimum 2048")); 1865 cFYI(1,("readsize set to minimum 2048"));
1833 } 1866 }
1867 /* calculate prepath */
1868 cifs_sb->prepath = volume_info.prepath;
1869 if(cifs_sb->prepath) {
1870 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1871 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
1872 volume_info.prepath = NULL;
1873 } else
1874 cifs_sb->prepathlen = 0;
1834 cifs_sb->mnt_uid = volume_info.linux_uid; 1875 cifs_sb->mnt_uid = volume_info.linux_uid;
1835 cifs_sb->mnt_gid = volume_info.linux_gid; 1876 cifs_sb->mnt_gid = volume_info.linux_gid;
1836 cifs_sb->mnt_file_mode = volume_info.file_mode; 1877 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,
2008 the password ptr is put in the new session structure (in which case the 2049 the password ptr is put in the new session structure (in which case the
2009 password will be freed at unmount time) */ 2050 password will be freed at unmount time) */
2010 kfree(volume_info.UNC); 2051 kfree(volume_info.UNC);
2052 kfree(volume_info.prepath);
2011 FreeXid(xid); 2053 FreeXid(xid);
2012 return rc; 2054 return rc;
2013} 2055}
@@ -3195,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3195 int xid; 3237 int xid;
3196 struct cifsSesInfo *ses = NULL; 3238 struct cifsSesInfo *ses = NULL;
3197 struct task_struct *cifsd_task; 3239 struct task_struct *cifsd_task;
3240 char * tmp;
3198 3241
3199 xid = GetXid(); 3242 xid = GetXid();
3200 3243
@@ -3228,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3228 } 3271 }
3229 3272
3230 cifs_sb->tcon = NULL; 3273 cifs_sb->tcon = NULL;
3274 tmp = cifs_sb->prepath;
3275 cifs_sb->prepathlen = 0;
3276 cifs_sb->prepath = NULL;
3277 kfree(tmp);
3231 if (ses) 3278 if (ses)
3232 schedule_timeout_interruptible(msecs_to_jiffies(500)); 3279 schedule_timeout_interruptible(msecs_to_jiffies(500));
3233 if (ses) 3280 if (ses)
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 914239d53634..66b825ade3e1 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -46,7 +46,8 @@ char *
46build_path_from_dentry(struct dentry *direntry) 46build_path_from_dentry(struct dentry *direntry)
47{ 47{
48 struct dentry *temp; 48 struct dentry *temp;
49 int namelen = 0; 49 int namelen;
50 int pplen;
50 char *full_path; 51 char *full_path;
51 char dirsep; 52 char dirsep;
52 53
@@ -56,7 +57,9 @@ build_path_from_dentry(struct dentry *direntry)
56 when the server crashed */ 57 when the server crashed */
57 58
58 dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); 59 dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
60 pplen = CIFS_SB(direntry->d_sb)->prepathlen;
59cifs_bp_rename_retry: 61cifs_bp_rename_retry:
62 namelen = pplen;
60 for (temp = direntry; !IS_ROOT(temp);) { 63 for (temp = direntry; !IS_ROOT(temp);) {
61 namelen += (1 + temp->d_name.len); 64 namelen += (1 + temp->d_name.len);
62 temp = temp->d_parent; 65 temp = temp->d_parent;
@@ -70,7 +73,6 @@ cifs_bp_rename_retry:
70 if(full_path == NULL) 73 if(full_path == NULL)
71 return full_path; 74 return full_path;
72 full_path[namelen] = 0; /* trailing null */ 75 full_path[namelen] = 0; /* trailing null */
73
74 for (temp = direntry; !IS_ROOT(temp);) { 76 for (temp = direntry; !IS_ROOT(temp);) {
75 namelen -= 1 + temp->d_name.len; 77 namelen -= 1 + temp->d_name.len;
76 if (namelen < 0) { 78 if (namelen < 0) {
@@ -79,7 +81,7 @@ cifs_bp_rename_retry:
79 full_path[namelen] = dirsep; 81 full_path[namelen] = dirsep;
80 strncpy(full_path + namelen + 1, temp->d_name.name, 82 strncpy(full_path + namelen + 1, temp->d_name.name,
81 temp->d_name.len); 83 temp->d_name.len);
82 cFYI(0, (" name: %s ", full_path + namelen)); 84 cFYI(0, ("name: %s", full_path + namelen));
83 } 85 }
84 temp = temp->d_parent; 86 temp = temp->d_parent;
85 if(temp == NULL) { 87 if(temp == NULL) {
@@ -88,18 +90,23 @@ cifs_bp_rename_retry:
88 return NULL; 90 return NULL;
89 } 91 }
90 } 92 }
91 if (namelen != 0) { 93 if (namelen != pplen) {
92 cERROR(1, 94 cERROR(1,
93 ("We did not end path lookup where we expected namelen is %d", 95 ("did not end path lookup where expected namelen is %d",
94 namelen)); 96 namelen));
95 /* presumably this is only possible if we were racing with a rename 97 /* presumably this is only possible if racing with a rename
96 of one of the parent directories (we can not lock the dentries 98 of one of the parent directories (we can not lock the dentries
97 above us to prevent this, but retrying should be harmless) */ 99 above us to prevent this, but retrying should be harmless) */
98 kfree(full_path); 100 kfree(full_path);
99 namelen = 0;
100 goto cifs_bp_rename_retry; 101 goto cifs_bp_rename_retry;
101 } 102 }
102 103 /* DIR_SEP already set for byte 0 / vs \ but not for
104 subsequent slashes in prepath which currently must
105 be entered the right way - not sure if there is an alternative
106 since the '\' is a valid posix character so we can not switch
107 those safely to '/' if any are found in the middle of the prepath */
108 /* BB test paths to Windows with '/' in the midst of prepath */
109 strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
103 return full_path; 110 return full_path;
104} 111}
105 112
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 067648b7179b..18fcec190f8b 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -269,7 +269,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
269 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, 269 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
270 ea_value, buf_size, 270 ea_value, buf_size,
271 ACL_TYPE_ACCESS); 271 ACL_TYPE_ACCESS);
272 CIFSSMBClose(xid, pTcon, fid) 272 CIFSSMBClose(xid, pTcon, fid);
273 } 273 }
274 } */ /* BB enable after fixing up return data */ 274 } */ /* BB enable after fixing up return data */
275 275