Commit 3eeab61a authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] statfs for cifs unix extensions no longer experimental
  [CIFS] New POSIX locking code not setting rc properly to zero on successful
  [CIFS] Support deep tree mounts (e.g. mounts to //server/share/path)
parents 6585b572 b8c06a2a
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, ...@@ -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 { ...@@ -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 */
...@@ -189,7 +189,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -189,7 +189,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_files = 0; /* undefined */ buf->f_files = 0; /* undefined */
buf->f_ffree = 0; /* unlimited */ buf->f_ffree = 0; /* unlimited */
#ifdef CONFIG_CIFS_EXPERIMENTAL
/* BB we could add a second check for a QFS Unix capability bit */ /* BB we could add a second check for a QFS Unix capability bit */
/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
...@@ -199,7 +198,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -199,7 +198,6 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
/* Only need to call the old QFSInfo if failed /* Only need to call the old QFSInfo if failed
on newer one */ on newer one */
if(rc) if(rc)
#endif /* CIFS_EXPERIMENTAL */
rc = CIFSSMBQFSInfo(xid, pTcon, buf); rc = CIFSSMBQFSInfo(xid, pTcon, buf);
/* Old Windows servers do not support level 103, retry with level /* Old Windows servers do not support level 103, retry with level
......
...@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 * ...@@ -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) ...@@ -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 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -70,7 +73,6 @@ build_path_from_dentry(struct dentry *direntry)
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 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -79,7 +81,7 @@ build_path_from_dentry(struct dentry *direntry)
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 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -88,18 +90,23 @@ build_path_from_dentry(struct dentry *direntry)
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;
} }
......
...@@ -752,6 +752,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -752,6 +752,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
int stored_rc = 0; int stored_rc = 0;
struct cifsLockInfo *li, *tmp; struct cifsLockInfo *li, *tmp;
rc = 0;
down(&fid->lock_sem); down(&fid->lock_sem);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) { list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset && if (pfLock->fl_start <= li->offset &&
...@@ -766,7 +767,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -766,7 +767,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
kfree(li); kfree(li);
} }
} }
up(&fid->lock_sem); up(&fid->lock_sem);
} }
} }
......
...@@ -269,7 +269,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ...@@ -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 */
......
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