* [PATCH 01/15] cifs: remove unused list_head from cifs_sb_info
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 02/15] cifs: add function to get a tcon from cifs_sb Jeff Layton
` (14 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...nested_tcon_q is unused.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifs_fs_sb.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 4797787..7f5bc7c 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -36,7 +36,6 @@
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
- struct list_head nested_tcon_q;
struct nls_table *local_nls;
unsigned int rsize;
unsigned int wsize;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 02/15] cifs: add function to get a tcon from cifs_sb
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
2010-03-30 19:51 ` [PATCH 01/15] cifs: remove unused list_head from cifs_sb_info Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 03/15] cifs: track local_nls in volume info Jeff Layton
` (13 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
When we convert cifs to do multiple sessions per mount, we'll need more
than one tcon per superblock. At that point "cifs_sb->tcon" will make
no sense. Add a new accessor function that gets a tcon given a cifs_sb.
For now, it just returns cifs_sb->tcon. Later it'll do more.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifs_dfs_ref.c | 2 +-
fs/cifs/cifsacl.c | 16 +++++++-------
fs/cifs/cifsfs.c | 20 ++++++++--------
fs/cifs/cifsglob.h | 6 +++++
fs/cifs/connect.c | 4 +-
fs/cifs/dir.c | 18 ++++++++--------
fs/cifs/file.c | 36 ++++++++++++++++----------------
fs/cifs/inode.c | 54 ++++++++++++++++++++++++------------------------
fs/cifs/ioctl.c | 2 +-
fs/cifs/link.c | 6 ++--
fs/cifs/misc.c | 2 +-
fs/cifs/readdir.c | 10 ++++----
fs/cifs/xattr.c | 8 +++---
13 files changed, 95 insertions(+), 89 deletions(-)
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index b1d61d0..923a9e7 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -322,7 +322,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
nd->path.dentry = dget(dentry);
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
- ses = cifs_sb->tcon->ses;
+ ses = cifs_sb_tcon(cifs_sb)->ses;
if (!ses) {
rc = -EINVAL;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 7dfe084..99e32e4 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -558,7 +558,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
int xid, rc;
xid = GetXid();
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
FreeXid(xid);
@@ -576,7 +576,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
+ rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, READ_CONTROL, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -584,10 +584,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
goto out;
}
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
- CIFSSMBClose(xid, cifs_sb->tcon, fid);
+ CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
out:
FreeXid(xid);
return pntsd;
@@ -617,7 +617,7 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
int xid, rc;
xid = GetXid();
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
FreeXid(xid);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
@@ -633,7 +633,7 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
+ rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, WRITE_DAC, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -641,10 +641,10 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
goto out;
}
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
- CIFSSMBClose(xid, cifs_sb->tcon, fid);
+ CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
out:
FreeXid(xid);
return rc;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ef9ea8a..e7fcd07 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -135,9 +135,9 @@ cifs_read_super(struct super_block *sb, void *data,
sb->s_magic = CIFS_MAGIC_NUMBER;
sb->s_op = &cifs_super_ops;
-/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+/* if (cifs_sb_tcon(cifs_sb)->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize =
- cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
+ cifs_sb_tcon(cifs_sb)->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
#ifdef CONFIG_CIFS_QUOTA
sb->s_qcop = &cifs_quotactl_ops;
#endif
@@ -224,7 +224,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int rc = -EOPNOTSUPP;
int xid;
@@ -359,7 +359,7 @@ static int
cifs_show_options(struct seq_file *s, struct vfsmount *m)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
seq_printf(s, ",unc=%s", tcon->treeName);
if (tcon->ses->userName)
@@ -432,7 +432,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
struct cifsTconInfo *pTcon;
if (cifs_sb)
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
else
return -EIO;
@@ -456,7 +456,7 @@ int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
struct cifsTconInfo *pTcon;
if (cifs_sb)
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
else
return -EIO;
@@ -478,7 +478,7 @@ int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
struct cifsTconInfo *pTcon;
if (cifs_sb)
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
else
return -EIO;
@@ -500,7 +500,7 @@ int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
struct cifsTconInfo *pTcon;
if (cifs_sb)
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
else
return -EIO;
@@ -530,7 +530,7 @@ static void cifs_umount_begin(struct super_block *sb)
if (cifs_sb == NULL)
return;
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
if (tcon == NULL)
return;
@@ -662,7 +662,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
((arg == F_WRLCK) &&
(CIFS_I(inode)->clientCanCacheAll)))
return generic_setlease(file, arg, lease);
- else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
+ else if (cifs_sb_tcon(CIFS_SB(inode->i_sb))->local_lease &&
!CIFS_I(inode)->clientCanCacheRead)
/* If the server claims to support oplock on this
file, then we still need to check oplock even
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 63c89d1..35bd90c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -407,6 +407,12 @@ CIFS_SB(struct super_block *sb)
return sb->s_fs_info;
}
+static inline struct cifsTconInfo *
+cifs_sb_tcon(struct cifs_sb_info *cifs_sb)
+{
+ return cifs_sb->tcon;
+}
+
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 820757b..791fc31 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2820,8 +2820,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
int rc = 0;
char *tmp;
- if (cifs_sb->tcon)
- cifs_put_tcon(cifs_sb->tcon);
+ if (cifs_sb_tcon(cifs_sb))
+ cifs_put_tcon(cifs_sb_tcon(cifs_sb));
cifs_sb->tcon = NULL;
tmp = cifs_sb->prepath;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 6909b60..1b3d384 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -63,8 +63,8 @@ build_path_from_dentry(struct dentry *direntry)
cifs_sb = CIFS_SB(direntry->d_sb);
dirsep = CIFS_DIR_SEP(cifs_sb);
pplen = cifs_sb->prepathlen;
- if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+ if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
+ dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
cifs_bp_rename_retry:
@@ -117,7 +117,7 @@ cifs_bp_rename_retry:
/* BB test paths to Windows with '/' in the midst of prepath */
if (dfsplen) {
- strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+ strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
@@ -160,7 +160,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
+ list_add(&pCifsFile->tlist, &cifs_sb_tcon(cifs_sb)->openFileList);
pCifsInode = CIFS_I(newinode);
if (pCifsInode) {
/* if readable file instance put first in list*/
@@ -225,7 +225,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
posix_flags |= SMB_O_DIRECT;
mode &= ~current_umask();
- rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
+ rc = CIFSPOSIXCreate(xid, cifs_sb_tcon(cifs_sb), posix_flags, mode,
pnetfid, presp_data, poplock, full_path,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -300,7 +300,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -378,7 +378,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY;
- if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+ if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -490,7 +490,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL)
@@ -622,7 +622,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
/* check whether path exists */
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
/*
* Don't allow the separator character in a path component.
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index ec56fdb..d66c79e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -267,7 +267,7 @@ int cifs_open(struct inode *inode, struct file *file)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
pCifsFile = cifs_fill_filedata(file);
@@ -369,7 +369,7 @@ int cifs_open(struct inode *inode, struct file *file)
goto out;
}
- if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+ if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
@@ -483,7 +483,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
}
cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
/* can not grab rename sem here because various ops, including
those that already have the rename sem can end up causing writepage
@@ -598,7 +598,7 @@ int cifs_close(struct inode *inode, struct file *file)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;
write_lock(&GlobalSMBSeslock);
@@ -682,7 +682,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
struct cifs_sb_info *cifs_sb =
CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Freeing private data in close dir"));
write_lock(&GlobalSMBSeslock);
@@ -792,7 +792,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("Unknown type of lock"));
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
if (file->private_data == NULL) {
rc = -EBADF;
@@ -961,7 +961,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
/* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
@@ -1064,7 +1064,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,
*poffset, file->f_path.dentry->d_name.name));
@@ -1295,7 +1295,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
offset += (loff_t)from;
write_data = kmap(page);
@@ -1370,8 +1370,8 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
- if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
- if (cifs_sb->tcon->ses->server->secMode &
+ if ((cifs_sb_tcon(cifs_sb)->ses) && (cifs_sb_tcon(cifs_sb)->ses->server))
+ if (cifs_sb_tcon(cifs_sb)->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if (!experimEnabled)
return generic_writepages(mapping, wbc);
@@ -1504,7 +1504,7 @@ retry:
rc = -EBADF;
} else {
long_op = cifs_write_timeout(cifsi, offset);
- rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
+ rc = CIFSSMBWrite2(xid, cifs_sb_tcon(cifs_sb),
open_file->netfid,
bytes_to_write, offset,
&bytes_written, iov, n_iov,
@@ -1522,7 +1522,7 @@ retry:
else
set_bit(AS_EIO, &mapping->flags);
} else {
- cifs_stats_bytes_written(cifs_sb->tcon,
+ cifs_stats_bytes_written(cifs_sb_tcon(cifs_sb),
bytes_written);
}
}
@@ -1668,7 +1668,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
if (rc == 0) {
rc = CIFS_I(inode)->write_behind_rc;
CIFS_I(inode)->write_behind_rc = 0;
- tcon = CIFS_SB(inode->i_sb)->tcon;
+ tcon = cifs_sb_tcon(CIFS_SB(inode->i_sb));
if (!rc && tcon && smbfile &&
!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
@@ -1753,7 +1753,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (file->private_data == NULL) {
rc = -EBADF;
@@ -1834,7 +1834,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (file->private_data == NULL) {
rc = -EBADF;
@@ -2015,7 +2015,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
pagevec_init(&lru_pvec, 0);
cFYI(DBG2, ("rpages: num pages %d", num_pages));
@@ -2349,7 +2349,7 @@ cifs_oplock_break(struct slow_work *work)
* disconnected since oplock already released by the server
*/
if (!cfile->closePend && !cfile->oplock_break_cancelled) {
- rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
+ rc = CIFSSMBLock(0, cifs_sb_tcon(cifs_sb), cfile->netfid, 0, 0, 0, 0,
LOCKING_ANDX_OPLOCK_RELEASE, false);
cFYI(1, ("Oplock release rc = %d", rc));
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 0cb6c5a..1a2af03 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -50,7 +50,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
/* check if server can support readpages */
- if (cifs_sb->tcon->ses->server->maxBuf <
+ if (cifs_sb_tcon(cifs_sb)->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
@@ -276,7 +276,7 @@ int cifs_get_file_info_unix(struct file *filp)
struct cifs_fattr fattr;
struct inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
xid = GetXid();
@@ -303,7 +303,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
struct cifsTconInfo *tcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
/* could have done a find first instead but this returns more info */
@@ -340,7 +340,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
int rc;
int oplock = 0;
__u16 netfid;
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
char buf[24];
unsigned int bytes_read;
char *pbuf;
@@ -429,7 +429,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
char ea_value[4];
__u32 mode;
- rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
+ rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -469,8 +469,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
if (adjust_tz) {
- fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
- fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
+ fattr->cf_ctime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
+ fattr->cf_mtime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
}
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
@@ -502,7 +502,7 @@ int cifs_get_file_info(struct file *filp)
struct cifs_fattr fattr;
struct inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
xid = GetXid();
@@ -546,7 +546,7 @@ int cifs_get_inode_info(struct inode **pinode,
bool adjustTZ = false;
struct cifs_fattr fattr;
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
if ((pfindData == NULL) && (*pinode != NULL)) {
@@ -678,8 +678,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
}
- if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+ if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
+ dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
@@ -688,7 +688,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
if (dfsplen) {
- strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+ strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
/* switch slash direction in prepath depending on whether
* windows or posix style path names
*/
@@ -768,7 +768,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
return ERR_PTR(-ENOMEM);
xid = GetXid();
- if (cifs_sb->tcon->unix_ext)
+ if (cifs_sb_tcon(cifs_sb)->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
else
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -777,7 +777,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
if (!inode)
return ERR_PTR(-ENOMEM);
- if (rc && cifs_sb->tcon->ipc) {
+ if (rc && cifs_sb_tcon(cifs_sb)->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
@@ -813,7 +813,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
FILE_BASIC_INFO info_buf;
if (attrs == NULL)
@@ -919,7 +919,7 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
struct inode *inode = dentry->d_inode;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
__u32 dosattr, origattr;
FILE_BASIC_INFO *info_buf = NULL;
@@ -1030,7 +1030,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
struct cifsInodeInfo *cifs_inode;
struct super_block *sb = dir->i_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct iattr *attrs = NULL;
__u32 dosattr = 0, origattr = 0;
@@ -1132,7 +1132,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1312,7 +1312,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1353,7 +1353,7 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
struct dentry *to_dentry, const char *toPath)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
__u16 srcfid;
int oplock, rc;
@@ -1402,7 +1402,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
cifs_sb_target = CIFS_SB(target_dir->i_sb);
cifs_sb_source = CIFS_SB(source_dir->i_sb);
- tcon = cifs_sb_source->tcon;
+ tcon = cifs_sb_tcon(cifs_sb_source);
xid = GetXid();
@@ -1410,7 +1410,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
* BB: this might be allowed if same server, but different share.
* Consider adding support for this
*/
- if (tcon != cifs_sb_target->tcon) {
+ if (tcon != cifs_sb_tcon(cifs_sb_target)) {
rc = -EXDEV;
goto cifs_rename_exit;
}
@@ -1538,7 +1538,7 @@ int cifs_revalidate_file(struct file *filp)
if (!cifs_inode_needs_reval(inode))
goto check_inval;
- if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
+ if (cifs_sb_tcon(CIFS_SB(inode->i_sb))->unix_ext)
rc = cifs_get_file_info_unix(filp);
else
rc = cifs_get_file_info(filp);
@@ -1579,7 +1579,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
"jiffies %ld", full_path, inode, inode->i_count.counter,
dentry, dentry->d_time, jiffies));
- if (CIFS_SB(sb)->tcon->unix_ext)
+ if (cifs_sb_tcon(CIFS_SB(sb))->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
else
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -1653,7 +1653,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
/*
* To avoid spurious oplock breaks from server, in the case of
@@ -1731,7 +1731,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
struct inode *inode = direntry->d_inode;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
struct cifs_unix_set_info_args *args = NULL;
struct cifsFileInfo *open_file;
@@ -1997,7 +1997,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
struct inode *inode = direntry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
if (pTcon->unix_ext)
return cifs_setattr_unix(direntry, attrs);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index f946506..c28dc62 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -52,7 +52,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
cifs_sb = CIFS_SB(inode->i_sb);
#ifdef CONFIG_CIFS_POSIX
- tcon = cifs_sb->tcon;
+ tcon = cifs_sb_tcon(cifs_sb);
if (tcon)
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
else {
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index fc1e048..c99e6fc 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -43,7 +43,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
xid = GetXid();
cifs_sb_target = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb_target->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb_target);
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */
@@ -112,7 +112,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
char *full_path = NULL;
char *target_path = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb->tcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
xid = GetXid();
@@ -167,7 +167,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index d147499..80edc23 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -726,6 +726,6 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
"properly. Hardlinks will not be recognized on this "
"mount. Consider mounting with the \"noserverino\" "
"option to silence this message.",
- cifs_sb->tcon->treeName));
+ cifs_sb_tcon(cifs_sb)->treeName));
}
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c343b14..74db1f0 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -101,7 +101,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
return NULL;
}
- if (CIFS_SB(sb)->tcon->nocase)
+ if (cifs_sb_tcon(CIFS_SB(sb))->nocase)
dentry->d_op = &cifs_ci_dentry_ops;
else
dentry->d_op = &cifs_dentry_ops;
@@ -170,7 +170,7 @@ static void
cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
struct cifs_sb_info *cifs_sb)
{
- int offset = cifs_sb->tcon->ses->server->timeAdj;
+ int offset = cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
memset(fattr, 0, sizeof(*fattr));
fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
@@ -198,7 +198,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
int len;
int oplock = 0;
int rc;
- struct cifsTconInfo *ptcon = cifs_sb->tcon;
+ struct cifsTconInfo *ptcon = cifs_sb_tcon(cifs_sb);
char *tmpbuffer;
rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
@@ -242,7 +242,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
if (cifs_sb == NULL)
return -EINVAL;
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (pTcon == NULL)
return -EINVAL;
@@ -777,7 +777,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (pTcon == NULL)
return -EINVAL;
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 3e2ef0d..7efdb5a 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -60,7 +60,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
xid = GetXid();
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -115,7 +115,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
xid = GetXid();
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -223,7 +223,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
xid = GetXid();
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -345,7 +345,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
return -EIO;
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 03/15] cifs: track local_nls in volume info
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
2010-03-30 19:51 ` [PATCH 01/15] cifs: remove unused list_head from cifs_sb_info Jeff Layton
2010-03-30 19:51 ` [PATCH 02/15] cifs: add function to get a tcon from cifs_sb Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 04/15] cifs: move SMB session creation code into separate function Jeff Layton
` (12 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
Add a local_nls field to the smb_vol struct and keep a pointer to the
local_nls in it.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/connect.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 791fc31..5c35923 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -101,6 +101,7 @@ struct smb_vol {
bool sockopt_tcp_nodelay:1;
unsigned short int port;
char *prepath;
+ struct nls_table *local_nls;
};
static int ipv4_connect(struct TCP_Server_Info *server);
@@ -2356,20 +2357,20 @@ try_mount_again:
goto out;
}
-
/* this is needed for ASCII cp to Unicode converts */
if (volume_info->iocharset == NULL) {
- cifs_sb->local_nls = load_nls_default();
- /* load_nls_default can not return null */
+ /* load_nls_default cannot return null */
+ volume_info->local_nls = load_nls_default();
} else {
- cifs_sb->local_nls = load_nls(volume_info->iocharset);
- if (cifs_sb->local_nls == NULL) {
+ volume_info->local_nls = load_nls(volume_info->iocharset);
+ if (volume_info->local_nls == NULL) {
cERROR(1, ("CIFS mount error: iocharset %s not found",
volume_info->iocharset));
rc = -ELIBACC;
goto out;
}
}
+ cifs_sb->local_nls = volume_info->local_nls;
/* get a reference to a tcp session */
srvTcp = cifs_get_tcp_session(volume_info);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 04/15] cifs: move SMB session creation code into separate function
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (2 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 03/15] cifs: track local_nls in volume info Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 05/15] cifs: move tcon find/create " Jeff Layton
` (11 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...it's mostly part of cifs_mount. Break it out into a separate
function.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/connect.c | 158 +++++++++++++++++++++++++++++++----------------------
1 files changed, 93 insertions(+), 65 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5c35923..81b695d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1616,6 +1616,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
int xid;
struct TCP_Server_Info *server = ses->server;
+ cFYI(1, ("%s: ses_count=%d\n", __func__, ses->ses_count));
write_lock(&cifs_tcp_ses_lock);
if (--ses->ses_count > 0) {
write_unlock(&cifs_tcp_ses_lock);
@@ -1634,6 +1635,92 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
cifs_put_tcp_session(server);
}
+static struct cifsSesInfo *
+cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
+{
+ int rc = -ENOMEM, xid;
+ struct cifsSesInfo *ses;
+
+ xid = GetXid();
+
+ ses = cifs_find_smb_ses(server, volume_info->username);
+ if (ses) {
+ cFYI(1, ("Existing smb sess found (status=%d)", ses->status));
+
+ /* existing SMB ses has a server reference already */
+ cifs_put_tcp_session(server);
+
+ mutex_lock(&ses->session_mutex);
+ if (ses->need_reconnect) {
+ cFYI(1, ("Session needs reconnect"));
+ rc = cifs_setup_session(xid, ses,
+ volume_info->local_nls);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ /* problem -- put our reference */
+ cifs_put_smb_ses(ses);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+ }
+ }
+ mutex_unlock(&ses->session_mutex);
+ FreeXid(xid);
+ return ses;
+ }
+
+ cFYI(1, ("Existing smb sess not found"));
+ ses = sesInfoAlloc();
+ if (ses == NULL)
+ goto get_ses_fail;
+
+ /* new SMB session uses our server ref */
+ ses->server = server;
+ if (server->addr.sockAddr6.sin6_family == AF_INET6)
+ sprintf(ses->serverName, "%pI6",
+ &server->addr.sockAddr6.sin6_addr);
+ else
+ sprintf(ses->serverName, "%pI4",
+ &server->addr.sockAddr.sin_addr.s_addr);
+
+ if (volume_info->username)
+ strncpy(ses->userName, volume_info->username,
+ MAX_USERNAME_SIZE);
+
+ /* volume_info->password freed at unmount */
+ if (volume_info->password) {
+ ses->password = kstrdup(volume_info->password, GFP_KERNEL);
+ if (!ses->password)
+ goto get_ses_fail;
+ }
+ if (volume_info->domainname) {
+ int len = strlen(volume_info->domainname);
+ ses->domainName = kmalloc(len + 1, GFP_KERNEL);
+ if (ses->domainName)
+ strcpy(ses->domainName, volume_info->domainname);
+ }
+ ses->linux_uid = volume_info->linux_uid;
+ ses->overrideSecFlg = volume_info->secFlg;
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_setup_session(xid, ses, volume_info->local_nls);
+ mutex_unlock(&ses->session_mutex);
+ if (rc)
+ goto get_ses_fail;
+
+ /* success, put it on the list */
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&ses->smb_ses_list, &server->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ FreeXid(xid);
+ return ses;
+
+get_ses_fail:
+ sesInfoFree(ses);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+}
+
static struct cifsTconInfo *
cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
{
@@ -2379,71 +2466,12 @@ try_mount_again:
goto out;
}
- pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
- if (pSesInfo) {
- cFYI(1, ("Existing smb sess found (status=%d)",
- pSesInfo->status));
- /*
- * The existing SMB session already has a reference to srvTcp,
- * so we can put back the extra one we got before
- */
- cifs_put_tcp_session(srvTcp);
-
- mutex_lock(&pSesInfo->session_mutex);
- if (pSesInfo->need_reconnect) {
- cFYI(1, ("Session needs reconnect"));
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- }
- mutex_unlock(&pSesInfo->session_mutex);
- } else if (!rc) {
- cFYI(1, ("Existing smb sess not found"));
- pSesInfo = sesInfoAlloc();
- if (pSesInfo == NULL) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
-
- /* new SMB session uses our srvTcp ref */
- pSesInfo->server = srvTcp;
- if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
- sprintf(pSesInfo->serverName, "%pI6",
- &srvTcp->addr.sockAddr6.sin6_addr);
- else
- sprintf(pSesInfo->serverName, "%pI4",
- &srvTcp->addr.sockAddr.sin_addr.s_addr);
-
- write_lock(&cifs_tcp_ses_lock);
- list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
- write_unlock(&cifs_tcp_ses_lock);
-
- /* volume_info->password freed at unmount */
- if (volume_info->password) {
- pSesInfo->password = kstrdup(volume_info->password,
- GFP_KERNEL);
- if (!pSesInfo->password) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
- }
- if (volume_info->username)
- strncpy(pSesInfo->userName, volume_info->username,
- MAX_USERNAME_SIZE);
- if (volume_info->domainname) {
- int len = strlen(volume_info->domainname);
- pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
- if (pSesInfo->domainName)
- strcpy(pSesInfo->domainName,
- volume_info->domainname);
- }
- pSesInfo->linux_uid = volume_info->linux_uid;
- pSesInfo->overrideSecFlg = volume_info->secFlg;
- mutex_lock(&pSesInfo->session_mutex);
-
- /* BB FIXME need to pass vol->secFlgs BB */
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- mutex_unlock(&pSesInfo->session_mutex);
+ /* get a reference to a SMB session */
+ pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
+ if (IS_ERR(pSesInfo)) {
+ rc = PTR_ERR(pSesInfo);
+ pSesInfo = NULL;
+ goto mount_fail_check;
}
/* search for existing tcon to this server share */
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 05/15] cifs: move tcon find/create into separate function
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (3 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 04/15] cifs: move SMB session creation code into separate function Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 06/15] cifs: add tcon field to cifsFileInfo struct Jeff Layton
` (10 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...and out of cifs_mount.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/connect.c | 156 +++++++++++++++++++++++++++++------------------------
1 files changed, 86 insertions(+), 70 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 81b695d..9dc817d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1749,6 +1749,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
int xid;
struct cifsSesInfo *ses = tcon->ses;
+ cFYI(1, ("%s: tc_count=%d\n", __func__, tcon->tc_count));
write_lock(&cifs_tcp_ses_lock);
if (--tcon->tc_count > 0) {
write_unlock(&cifs_tcp_ses_lock);
@@ -1766,6 +1767,80 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
cifs_put_smb_ses(ses);
}
+static struct cifsTconInfo *
+cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
+{
+ int rc, xid;
+ struct cifsTconInfo *tcon;
+
+ tcon = cifs_find_tcon(ses, volume_info->UNC);
+ if (tcon) {
+ cFYI(1, ("Found match on UNC path"));
+ /* existing tcon already has a reference */
+ cifs_put_smb_ses(ses);
+ if (tcon->seal != volume_info->seal)
+ cERROR(1, ("transport encryption setting "
+ "conflicts with existing tid"));
+ return tcon;
+ }
+
+ tcon = tconInfoAlloc();
+ if (tcon == NULL) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+
+ tcon->ses = ses;
+ if (volume_info->password) {
+ tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
+ if (!tcon->password) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+ }
+
+ if ((strchr(volume_info->UNC + 3, '\\') == NULL)
+ && (strchr(volume_info->UNC + 3, '/') == NULL)) {
+ cERROR(1, ("Missing share name"));
+ rc = -ENODEV;
+ goto out_fail;
+ }
+
+ /* BB Do we need to wrap session_mutex around
+ * this TCon call and Unix SetFS as
+ * we do on SessSetup and reconnect? */
+ xid = GetXid();
+ rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
+ FreeXid(xid);
+ cFYI(1, ("CIFS Tcon rc = %d", rc));
+ if (rc)
+ goto out_fail;
+
+ if (volume_info->nodfs) {
+ tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
+ cFYI(1, ("DFS disabled (%d)", tcon->Flags));
+ }
+ tcon->seal = volume_info->seal;
+ /* we can have only one retry value for a connection
+ to a share so for resources mounted more than once
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info->retry;
+ tcon->nocase = volume_info->nocase;
+ tcon->local_lease = volume_info->local_lease;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&tcon->tcon_list, &ses->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ return tcon;
+
+out_fail:
+ tconInfoFree(tcon);
+ return ERR_PTR(rc);
+}
+
+
int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -2474,81 +2549,22 @@ try_mount_again:
goto mount_fail_check;
}
- /* search for existing tcon to this server share */
- if (!rc) {
- setup_cifs_sb(volume_info, cifs_sb);
-
- tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
- if (tcon) {
- cFYI(1, ("Found match on UNC path"));
- /* existing tcon already has a reference */
- cifs_put_smb_ses(pSesInfo);
- if (tcon->seal != volume_info->seal)
- cERROR(1, ("transport encryption setting "
- "conflicts with existing tid"));
- } else {
- tcon = tconInfoAlloc();
- if (tcon == NULL) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
-
- tcon->ses = pSesInfo;
- if (volume_info->password) {
- tcon->password = kstrdup(volume_info->password,
- GFP_KERNEL);
- if (!tcon->password) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
- }
-
- if ((strchr(volume_info->UNC + 3, '\\') == NULL)
- && (strchr(volume_info->UNC + 3, '/') == NULL)) {
- cERROR(1, ("Missing share name"));
- rc = -ENODEV;
- goto mount_fail_check;
- } else {
- /* BB Do we need to wrap sesSem around
- * this TCon call and Unix SetFS as
- * we do on SessSetup and reconnect? */
- rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
- tcon, cifs_sb->local_nls);
- cFYI(1, ("CIFS Tcon rc = %d", rc));
- if (volume_info->nodfs) {
- tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
- cFYI(1, ("DFS disabled (%d)",
- tcon->Flags));
- }
- }
- if (rc)
- goto remote_path_check;
- tcon->seal = volume_info->seal;
- write_lock(&cifs_tcp_ses_lock);
- list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
- write_unlock(&cifs_tcp_ses_lock);
- }
-
- /* we can have only one retry value for a connection
- to a share so for resources mounted more than once
- to the same server share the last value passed in
- for the retry flag is used */
- tcon->retry = volume_info->retry;
- tcon->nocase = volume_info->nocase;
- tcon->local_lease = volume_info->local_lease;
- }
- if (pSesInfo) {
- if (pSesInfo->capabilities & CAP_LARGE_FILES)
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- else
- sb->s_maxbytes = MAX_NON_LFS;
- }
+ setup_cifs_sb(volume_info, cifs_sb);
+ if (pSesInfo->capabilities & CAP_LARGE_FILES)
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ else
+ sb->s_maxbytes = MAX_NON_LFS;
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100;
- if (rc)
+ /* search for existing tcon to this server share */
+ tcon = cifs_get_tcon(pSesInfo, volume_info);
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ tcon = NULL;
goto remote_path_check;
+ }
cifs_sb->tcon = tcon;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 06/15] cifs: add tcon field to cifsFileInfo struct
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (4 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 05/15] cifs: move tcon find/create " Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 07/15] cifs: make various routines use the cifsFileInfo->tcon pointer Jeff Layton
` (9 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
With more than one tcon per mount, we need to know which one is
associated with a particular fid.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifsglob.h | 1 +
fs/cifs/dir.c | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 35bd90c..1aa8418 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -349,6 +349,7 @@ struct cifsFileInfo {
struct file *pfile; /* needed for writepage */
struct inode *pInode; /* needed for oplock break */
struct vfsmount *mnt;
+ struct cifsTconInfo *tcon;
struct mutex lock_mutex;
struct list_head llist; /* list of byte range locks we have. */
bool closePend:1; /* file is marked to close */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1b3d384..1ade8e1 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -153,6 +153,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
pCifsFile->pfile = file;
pCifsFile->invalidHandle = false;
pCifsFile->closePend = false;
+ pCifsFile->tcon = cifs_sb_tcon(cifs_sb);
mutex_init(&pCifsFile->fh_mutex);
mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 07/15] cifs: make various routines use the cifsFileInfo->tcon pointer
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (5 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 06/15] cifs: add tcon field to cifsFileInfo struct Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 08/15] cifs: have find_readable/writable_file filter by fsuid Jeff Layton
` (8 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...where it's available and appropriate.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifsfs.c | 4 ++--
fs/cifs/file.c | 40 ++++++++++++++++++----------------------
fs/cifs/inode.c | 22 ++++++++++++++++------
fs/cifs/ioctl.c | 19 ++++---------------
fs/cifs/readdir.c | 18 ++++++++----------
5 files changed, 48 insertions(+), 55 deletions(-)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e7fcd07..e3149c0 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -652,6 +652,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
/* note that this is called by vfs setlease with the BKL held
although I doubt that BKL is needed here in cifs */
struct inode *inode = file->f_path.dentry->d_inode;
+ struct cifsFileInfo *cfile = file->private_data;
if (!(S_ISREG(inode->i_mode)))
return -EINVAL;
@@ -662,8 +663,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
((arg == F_WRLCK) &&
(CIFS_I(inode)->clientCanCacheAll)))
return generic_setlease(file, arg, lease);
- else if (cifs_sb_tcon(CIFS_SB(inode->i_sb))->local_lease &&
- !CIFS_I(inode)->clientCanCacheRead)
+ else if (cfile->tcon->local_lease && !CIFS_I(inode)->clientCanCacheRead)
/* If the server claims to support oplock on this
file, then we still need to check oplock even
if the local_lease mount option is set, but there
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d66c79e..6377cb8 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -483,7 +483,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
}
cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb_tcon(cifs_sb);
+ tcon = pCifsFile->tcon;
/* can not grab rename sem here because various ops, including
those that already have the rename sem can end up causing writepage
@@ -598,7 +598,7 @@ int cifs_close(struct inode *inode, struct file *file)
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
+ pTcon = pSMBFile->tcon;
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;
write_lock(&GlobalSMBSeslock);
@@ -679,10 +679,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (pCFileStruct) {
struct cifsTconInfo *pTcon;
- struct cifs_sb_info *cifs_sb =
- CIFS_SB(file->f_path.dentry->d_sb);
-
- pTcon = cifs_sb_tcon(cifs_sb);
+ pTcon = pCFileStruct->tcon;
cFYI(1, ("Freeing private data in close dir"));
write_lock(&GlobalSMBSeslock);
@@ -792,7 +789,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("Unknown type of lock"));
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- tcon = cifs_sb_tcon(cifs_sb);
+ tcon = ((struct cifsFileInfo *)file->private_data)->tcon;
if (file->private_data == NULL) {
rc = -EBADF;
@@ -961,8 +958,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
-
/* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_path.dentry->d_name.name)); */
@@ -970,6 +965,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
if (file->private_data == NULL)
return -EBADF;
open_file = (struct cifsFileInfo *) file->private_data;
+ pTcon = open_file->tcon;
rc = generic_write_checks(file, poffset, &write_size, 0);
if (rc)
@@ -1064,14 +1060,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
-
cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,
*poffset, file->f_path.dentry->d_name.name));
if (file->private_data == NULL)
return -EBADF;
+
open_file = (struct cifsFileInfo *)file->private_data;
+ pTcon = open_file->tcon;
xid = GetXid();
@@ -1286,7 +1282,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
int rc = -EFAULT;
int bytes_written = 0;
struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
struct inode *inode;
struct cifsFileInfo *open_file;
@@ -1295,7 +1290,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
offset += (loff_t)from;
write_data = kmap(page);
@@ -1354,6 +1348,7 @@ static int cifs_writepages(struct address_space *mapping,
int nr_pages;
__u64 offset = 0;
struct cifsFileInfo *open_file;
+ struct cifsTconInfo *tcon;
struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
struct page *page;
struct pagevec pvec;
@@ -1370,6 +1365,7 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
+ /* WTF? */
if ((cifs_sb_tcon(cifs_sb)->ses) && (cifs_sb_tcon(cifs_sb)->ses->server))
if (cifs_sb_tcon(cifs_sb)->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
@@ -1380,7 +1376,6 @@ static int cifs_writepages(struct address_space *mapping,
if (iov == NULL)
return generic_writepages(mapping, wbc);
-
/*
* BB: Is this meaningful for a non-block-device file system?
* If it is, we should test it again after we do I/O
@@ -1503,8 +1498,9 @@ retry:
cERROR(1, ("No writable handles for inode"));
rc = -EBADF;
} else {
+ tcon = open_file->tcon;
long_op = cifs_write_timeout(cifsi, offset);
- rc = CIFSSMBWrite2(xid, cifs_sb_tcon(cifs_sb),
+ rc = CIFSSMBWrite2(xid, tcon,
open_file->netfid,
bytes_to_write, offset,
&bytes_written, iov, n_iov,
@@ -1522,7 +1518,7 @@ retry:
else
set_bit(AS_EIO, &mapping->flags);
} else {
- cifs_stats_bytes_written(cifs_sb_tcon(cifs_sb),
+ cifs_stats_bytes_written(tcon,
bytes_written);
}
}
@@ -1668,7 +1664,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
if (rc == 0) {
rc = CIFS_I(inode)->write_behind_rc;
CIFS_I(inode)->write_behind_rc = 0;
- tcon = cifs_sb_tcon(CIFS_SB(inode->i_sb));
+ tcon = smbfile->tcon;
if (!rc && tcon && smbfile &&
!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
@@ -1753,7 +1749,6 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
if (file->private_data == NULL) {
rc = -EBADF;
@@ -1761,6 +1756,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
return rc;
}
open_file = (struct cifsFileInfo *)file->private_data;
+ pTcon = open_file->tcon;
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
cFYI(1, ("attempting read on write only file instance"));
@@ -1834,14 +1830,15 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid);
return rc;
}
+
open_file = (struct cifsFileInfo *)file->private_data;
+ pTcon = open_file->tcon;
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
cFYI(1, ("attempting read on write only file instance"));
@@ -2015,7 +2012,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
+ pTcon = open_file->tcon;
pagevec_init(&lru_pvec, 0);
cFYI(DBG2, ("rpages: num pages %d", num_pages));
@@ -2320,7 +2317,6 @@ cifs_oplock_break(struct slow_work *work)
oplock_break);
struct inode *inode = cfile->pInode;
struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb);
int rc, waitrc = 0;
if (inode && S_ISREG(inode->i_mode)) {
@@ -2349,7 +2345,7 @@ cifs_oplock_break(struct slow_work *work)
* disconnected since oplock already released by the server
*/
if (!cfile->closePend && !cfile->oplock_break_cancelled) {
- rc = CIFSSMBLock(0, cifs_sb_tcon(cifs_sb), cfile->netfid, 0, 0, 0, 0,
+ rc = CIFSSMBLock(0, cfile->tcon, cfile->netfid, 0, 0, 0, 0,
LOCKING_ANDX_OPLOCK_RELEASE, false);
cFYI(1, ("Oplock release rc = %d", rc));
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 1a2af03..8c912e1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -276,8 +276,8 @@ int cifs_get_file_info_unix(struct file *filp)
struct cifs_fattr fattr;
struct inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
+ struct cifsTconInfo *tcon = cfile->tcon;
xid = GetXid();
rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -502,8 +502,8 @@ int cifs_get_file_info(struct file *filp)
struct cifs_fattr fattr;
struct inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
+ struct cifsTconInfo *tcon = cfile->tcon;
xid = GetXid();
rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -813,7 +813,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *pTcon;
FILE_BASIC_INFO info_buf;
if (attrs == NULL)
@@ -856,9 +856,12 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
if (open_file) {
netfid = open_file->netfid;
netpid = open_file->pid;
+ pTcon = open_file->tcon;
goto set_via_filehandle;
}
+ pTcon = open_file->tcon;
+
/*
* NT4 apparently returns success on this call, but it doesn't
* really work.
@@ -1534,11 +1537,12 @@ int cifs_revalidate_file(struct file *filp)
{
int rc = 0;
struct inode *inode = filp->f_path.dentry->d_inode;
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
if (!cifs_inode_needs_reval(inode))
goto check_inval;
- if (cifs_sb_tcon(CIFS_SB(inode->i_sb))->unix_ext)
+ if (cfile->tcon->unix_ext)
rc = cifs_get_file_info_unix(filp);
else
rc = cifs_get_file_info(filp);
@@ -1653,7 +1657,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *pTcon = NULL;
/*
* To avoid spurious oplock breaks from server, in the case of
@@ -1668,6 +1672,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
if (open_file) {
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
+ pTcon = open_file->tcon;
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
npid, false);
cifsFileInfo_put(open_file);
@@ -1682,6 +1687,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
rc = -EINVAL;
if (rc != 0) {
+ if (pTcon == NULL)
+ pTcon = cifs_sb_tcon(cifs_sb);
+
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
@@ -1731,7 +1739,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
struct inode *inode = direntry->d_inode;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *pTcon;
struct cifs_unix_set_info_args *args = NULL;
struct cifsFileInfo *open_file;
@@ -1824,9 +1832,11 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (open_file) {
u16 nfid = open_file->netfid;
u32 npid = open_file->pid;
+ pTcon = open_file->tcon;
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
cifsFileInfo_put(open_file);
} else {
+ pTcon = cifs_sb_tcon(cifs_sb);
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index c28dc62..a2c7ed4 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -37,12 +37,12 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
int xid;
struct cifs_sb_info *cifs_sb;
#ifdef CONFIG_CIFS_POSIX
- __u64 ExtAttrBits = 0;
- __u64 ExtAttrMask = 0;
- __u64 caps;
- struct cifsTconInfo *tcon;
struct cifsFileInfo *pSMBFile =
(struct cifsFileInfo *)filep->private_data;
+ struct cifsTconInfo *tcon = pSMBFile->tcon;
+ __u64 ExtAttrBits = 0;
+ __u64 ExtAttrMask = 0;
+ __u64 caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
#endif /* CONFIG_CIFS_POSIX */
xid = GetXid();
@@ -51,17 +51,6 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
cifs_sb = CIFS_SB(inode->i_sb);
-#ifdef CONFIG_CIFS_POSIX
- tcon = cifs_sb_tcon(cifs_sb);
- if (tcon)
- caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
- else {
- rc = -EIO;
- FreeXid(xid);
- return -EIO;
- }
-#endif /* CONFIG_CIFS_POSIX */
-
switch (command) {
case CIFS_IOC_CHECKUMOUNT:
cFYI(1, ("User unmount attempted"));
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 74db1f0..491745f 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -227,22 +227,22 @@ static int initiate_cifs_search(const int xid, struct file *file)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
- if (file->private_data == NULL) {
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ if (cifs_sb == NULL)
+ return -EINVAL;
+
+ if (file->private_data == NULL)
file->private_data =
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
- }
if (file->private_data == NULL)
return -ENOMEM;
cifsFile = file->private_data;
cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false;
+ cifsFile->tcon = cifs_sb_tcon(cifs_sb);
- cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- if (cifs_sb == NULL)
- return -EINVAL;
-
- pTcon = cifs_sb_tcon(cifs_sb);
+ pTcon = cifsFile->tcon;
if (pTcon == NULL)
return -EINVAL;
@@ -777,9 +777,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
- if (pTcon == NULL)
- return -EINVAL;
switch ((int) file->f_pos) {
case 0:
@@ -829,6 +826,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
CIFSFindClose(xid, pTcon, cifsFile->netfid);
} */
+ pTcon = cifsFile->tcon;
rc = find_cifs_entry(xid, pTcon, file,
¤t_entry, &num_to_fill);
if (rc) {
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 08/15] cifs: have find_readable/writable_file filter by fsuid
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (6 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 07/15] cifs: make various routines use the cifsFileInfo->tcon pointer Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 09/15] cifs: fix cifs_show_options to show "username=" or "multises" Jeff Layton
` (7 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
When we implement multisession mounts, we'll need to filter filehandles
by fsuid. Add a flag for multisession mounts and code to filter by
fsuid when it's set.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifs_fs_sb.h | 3 ++-
fs/cifs/cifsacl.c | 4 ++--
fs/cifs/cifsproto.h | 4 ++--
fs/cifs/dir.c | 1 +
fs/cifs/file.c | 31 ++++++++++++++++++++++++-------
fs/cifs/inode.c | 6 +++---
6 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 7f5bc7c..037dbab 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -33,6 +33,7 @@
#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
+#define CIFS_MOUNT_MULTISES 0x8000 /* multisession mount */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
@@ -43,7 +44,7 @@ struct cifs_sb_info {
gid_t mnt_gid;
mode_t mnt_file_mode;
mode_t mnt_dir_mode;
- int mnt_cifs_flags;
+ unsigned int mnt_cifs_flags;
int prepathlen;
char *prepath; /* relative path under the share to mount to */
#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 99e32e4..5e4ea43 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -602,7 +602,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct cifsFileInfo *open_file = NULL;
if (inode)
- open_file = find_readable_file(CIFS_I(inode));
+ open_file = find_readable_file(CIFS_I(inode), true);
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
@@ -660,7 +660,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
- open_file = find_readable_file(CIFS_I(inode));
+ open_file = find_readable_file(CIFS_I(inode), true);
if (!open_file)
return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index bf18970..4b048f1 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -66,9 +66,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern bool is_valid_oplock_break(struct smb_hdr *smb,
struct TCP_Server_Info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
#ifdef CONFIG_CIFS_EXPERIMENTAL
-extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
#endif
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1ade8e1..dbc6b97 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -148,6 +148,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid;
+ pCifsFile->uid = current_fsuid();
pCifsFile->pInode = igrab(newinode);
pCifsFile->mnt = mnt;
pCifsFile->pfile = file;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 6377cb8..8285d14 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1163,9 +1163,15 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
-struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
+ bool fsuid_only)
{
struct cifsFileInfo *open_file = NULL;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
+
+ /* only filter by fsuid on multisession mounts */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTISES))
+ fsuid_only = false;
read_lock(&GlobalSMBSeslock);
/* we could simply get the first_list_entry since write-only entries
@@ -1174,6 +1180,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
continue;
+ if (fsuid_only && open_file->uid != current_fsuid())
+ continue;
if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_RDONLY))) {
if (!open_file->invalidHandle) {
@@ -1193,9 +1201,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
}
#endif
-struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
+ bool fsuid_only)
{
struct cifsFileInfo *open_file;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
bool any_available = false;
int rc;
@@ -1209,13 +1219,19 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
return NULL;
}
+ /* only filter by fsuid on multisession mounts */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTISES))
+ fsuid_only = false;
+
read_lock(&GlobalSMBSeslock);
refind_writable:
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
- if (open_file->closePend ||
- (!any_available && open_file->pid != current->tgid))
+ if (open_file->closePend)
+ continue;
+ if (!any_available && open_file->pid != current->tgid)
+ continue;
+ if (fsuid_only && open_file->uid != current_fsuid())
continue;
-
if (open_file->pfile &&
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
@@ -1310,7 +1326,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
if (mapping->host->i_size - offset < (loff_t)to)
to = (unsigned)(mapping->host->i_size - offset);
- open_file = find_writable_file(CIFS_I(mapping->host));
+ open_file = find_writable_file(CIFS_I(mapping->host), false);
if (open_file) {
bytes_written = cifs_write(open_file->pfile, write_data,
to-from, &offset);
@@ -1493,7 +1509,8 @@ retry:
* CIFSSMBWrite2. We can't rely on the last handle
* we used to still be valid
*/
- open_file = find_writable_file(CIFS_I(mapping->host));
+ open_file = find_writable_file(CIFS_I(mapping->host),
+ false);
if (!open_file) {
cERROR(1, ("No writable handles for inode"));
rc = -EBADF;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8c912e1..e09bf9f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -852,7 +852,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
/*
* If the file is already open for write, just use that fileid
*/
- open_file = find_writable_file(cifsInode);
+ open_file = find_writable_file(cifsInode, true);
if (open_file) {
netfid = open_file->netfid;
netpid = open_file->pid;
@@ -1668,7 +1668,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
* writebehind data than the SMB timeout for the SetPathInfo
* request would allow
*/
- open_file = find_writable_file(cifsInode);
+ open_file = find_writable_file(cifsInode, true);
if (open_file) {
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
@@ -1828,7 +1828,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
args->ctime = NO_CHANGE_64;
args->device = 0;
- open_file = find_writable_file(cifsInode);
+ open_file = find_writable_file(cifsInode, true);
if (open_file) {
u16 nfid = open_file->netfid;
u32 npid = open_file->pid;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 09/15] cifs: fix cifs_show_options to show "username=" or "multises"
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (7 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 08/15] cifs: have find_readable/writable_file filter by fsuid Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 10/15] cifs: move secType to the SMB session Jeff Layton
` (6 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...based on CIFS_MOUNT_MULTISES flag.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifsfs.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e3149c0..53ecc94 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -362,8 +362,12 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
seq_printf(s, ",unc=%s", tcon->treeName);
- if (tcon->ses->userName)
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTISES)
+ seq_printf(s, ",multises");
+ else if (tcon->ses->userName)
seq_printf(s, ",username=%s", tcon->ses->userName);
+
if (tcon->ses->domainName)
seq_printf(s, ",domain=%s", tcon->ses->domainName);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 10/15] cifs: move secType to the SMB session
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (8 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 09/15] cifs: fix cifs_show_options to show "username=" or "multises" Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 11/15] cifs: have cifs_new_fileinfo take a tcon arg Jeff Layton
` (5 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
There's no reason we need to use the same secType for every session on
a socket. Move the secType field from the server info struct to the
SMB session.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifs_spnego.c | 4 ++--
fs/cifs/cifsglob.h | 2 +-
fs/cifs/cifssmb.c | 20 ++++++++++----------
fs/cifs/connect.c | 2 +-
fs/cifs/sess.c | 2 +-
5 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 8ec7736..2f6bb5b 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -132,9 +132,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
dp = description + strlen(description);
/* for now, only sec=krb5 and sec=mskrb5 are valid */
- if (server->secType == Kerberos)
+ if (sesInfo->secType == Kerberos)
sprintf(dp, ";sec=krb5");
- else if (server->secType == MSKerberos)
+ else if (sesInfo->secType == MSKerberos)
sprintf(dp, ";sec=mskrb5");
else
goto out;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1aa8418..b47a66b 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -160,7 +160,6 @@ struct TCP_Server_Info {
struct task_struct *tsk;
char server_GUID[16];
char secMode;
- enum securityEnum secType;
unsigned int maxReq; /* Clients should submit no more */
/* than maxReq distinct unanswered SMBs to the server when using */
/* multiplexed reads or writes */
@@ -212,6 +211,7 @@ struct cifsSesInfo {
struct TCP_Server_Info *server; /* pointer to server info */
int ses_count; /* reference counter */
enum statusEnum status;
+ enum securityEnum secType;
unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u16 ipc_tid; /* special tid for connection to IPC share */
__u16 flags;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2c6de17..227be2c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -425,7 +425,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
if ((secFlags & CIFSSEC_MAY_LANMAN) ||
(secFlags & CIFSSEC_MAY_PLNTXT))
- server->secType = LANMAN;
+ ses->secType = LANMAN;
else {
cERROR(1, ("mount failed weak security disabled"
" in /proc/fs/cifs/SecurityFlags"));
@@ -521,20 +521,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
" but client support disabled"));
if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
- server->secType = NTLMv2;
+ ses->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_NTLM)
- server->secType = NTLM;
+ ses->secType = NTLM;
else if (secFlags & CIFSSEC_MAY_NTLMV2)
- server->secType = NTLMv2;
+ ses->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_KRB5)
- server->secType = Kerberos;
+ ses->secType = Kerberos;
else if (secFlags & CIFSSEC_MAY_NTLMSSP)
- server->secType = RawNTLMSSP;
+ ses->secType = RawNTLMSSP;
else if (secFlags & CIFSSEC_MAY_LANMAN)
- server->secType = LANMAN;
+ ses->secType = LANMAN;
/* #ifdef CONFIG_CIFS_EXPERIMENTAL
else if (secFlags & CIFSSEC_MAY_PLNTXT)
- server->secType = ??
+ ses->secType = ??
#endif */
else {
rc = -EOPNOTSUPP;
@@ -593,12 +593,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
}
if (count == 16) {
- server->secType = RawNTLMSSP;
+ ses->secType = RawNTLMSSP;
} else {
rc = decode_negTokenInit(pSMBr->u.extended_response.
SecurityBlob,
count - 16,
- &server->secType);
+ &ses->secType);
if (rc == 1)
rc = 0;
else
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9dc817d..3e1efc6 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2752,7 +2752,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
NTLMv2 password here) */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
if ((extended_security & CIFSSEC_MAY_LANMAN) &&
- (ses->server->secType == LANMAN))
+ (ses->secType == LANMAN))
calc_lanman_hash(tcon->password, ses->server->cryptKey,
ses->server->secMode &
SECMODE_PW_ENCRYPT ? true : false,
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index aaa9c1c..63da915 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -580,7 +580,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
if (ses == NULL)
return -EINVAL;
- type = ses->server->secType;
+ type = ses->secType;
cFYI(1, ("sess setup type %d", type));
ssetup_ntlmssp_authenticate:
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 11/15] cifs: have cifs_new_fileinfo take a tcon arg
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (9 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 10/15] cifs: move secType to the SMB session Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 12/15] cifs: build sessions and tcons on the fly Jeff Layton
` (4 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
To minimize calls to cifs_sb_tcon and to allow for a clear error path if
a tcon can't be acquired.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/dir.c | 26 ++++++++++++++++++--------
fs/cifs/file.c | 6 +++++-
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index dbc6b97..3467626 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -131,8 +131,9 @@ cifs_bp_rename_retry:
}
struct cifsFileInfo *
-cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
- struct file *file, struct vfsmount *mnt, unsigned int oflags)
+cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
+ struct vfsmount *mnt, struct cifsTconInfo *tcon,
+ unsigned int oflags)
{
int oplock = 0;
struct cifsFileInfo *pCifsFile;
@@ -154,7 +155,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
pCifsFile->pfile = file;
pCifsFile->invalidHandle = false;
pCifsFile->closePend = false;
- pCifsFile->tcon = cifs_sb_tcon(cifs_sb);
+ pCifsFile->tcon = tcon;
mutex_init(&pCifsFile->fh_mutex);
mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist);
@@ -193,6 +194,10 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
struct cifs_fattr fattr;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
cFYI(1, ("posix open %s", full_path));
@@ -227,9 +232,9 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
posix_flags |= SMB_O_DIRECT;
mode &= ~current_umask();
- rc = CIFSPOSIXCreate(xid, cifs_sb_tcon(cifs_sb), posix_flags, mode,
- pnetfid, presp_data, poplock, full_path,
- cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+ rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
+ poplock, full_path, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc)
goto posix_open_ret;
@@ -253,7 +258,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
cifs_fattr_to_inode(*pinode, &fattr);
}
- cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
+ cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, tcon, oflags);
posix_open_ret:
kfree(presp_data);
@@ -304,6 +309,11 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon)) {
+ FreeXid(xid);
+ return PTR_ERR(tcon);
+ }
+
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
rc = -ENOMEM;
@@ -467,7 +477,7 @@ cifs_create_set_dentry:
CIFSSMBClose(xid, tcon, fileHandle);
} else if (!(posix_create) && (newinode)) {
cifs_new_fileinfo(newinode, fileHandle, NULL,
- nd->path.mnt, oflags);
+ nd->path.mnt, tcon, oflags);
}
cifs_create_out:
kfree(buf);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8285d14..308520e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -268,6 +268,10 @@ int cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon)) {
+ FreeXid(xid);
+ return PTR_ERR(tcon);
+ }
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
pCifsFile = cifs_fill_filedata(file);
@@ -390,7 +394,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
- file->f_flags);
+ tcon, file->f_flags);
file->private_data = pCifsFile;
if (file->private_data == NULL) {
rc = -ENOMEM;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 12/15] cifs: build sessions and tcons on the fly
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (10 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 11/15] cifs: have cifs_new_fileinfo take a tcon arg Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 13/15] cifs: on multises mount, set ownership to current_fsuid/current_fsgid Jeff Layton
` (3 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
This patch is rather large, but it's a bit difficult to do piecemeal...
First, callers of cifs_sb_tcon will need to expect the possibility
of a IS_ERR() return from that function. The bulk of this patch is
fixing the callers to do so.
Turn the tcon pointer in the cifs_sb into a radix tree that uses the
fsuid of the process as a key. The value is a new "tcon_link" struct
that contains info about a tcon that's under construction.
When a new process needs a tcon, it'll call cifs_sb_tcon. That will
then look up the tcon_link in the radix tree. If it exists and is
valid, it's returned.
If it doesn't exist, then we stuff a new tcon_link into the tree and
mark it as pending and then go and try to build the session/tcon.
If that works, the tcon pointer in the tcon_link is updated and the
pending flag is cleared.
If the construction fails, then we set the tcon pointer to an ERR_PTR
and clear the pending flag.
If the radix tree is searched and the tcon_link is marked pending
then we go to sleep and wait for the pending flag to be cleared.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/cifs_dfs_ref.c | 10 ++-
fs/cifs/cifs_fs_sb.h | 7 ++-
fs/cifs/cifsacl.c | 32 ++++++--
fs/cifs/cifsfs.c | 69 ++++++----------
fs/cifs/cifsglob.h | 7 +--
fs/cifs/cifsproto.h | 5 +-
fs/cifs/connect.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++--
fs/cifs/dir.c | 47 ++++++-----
fs/cifs/file.c | 16 ++--
fs/cifs/inode.c | 120 ++++++++++++++++++++++------
fs/cifs/link.c | 13 +++-
fs/cifs/misc.c | 2 +-
fs/cifs/readdir.c | 12 ++-
fs/cifs/xattr.c | 23 +++++-
14 files changed, 437 insertions(+), 134 deletions(-)
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 923a9e7..e2d22ff 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -307,6 +307,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals = 0;
struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *tcon;
struct cifsSesInfo *ses;
char *full_path = NULL;
int xid, i;
@@ -322,13 +323,14 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
nd->path.dentry = dget(dentry);
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
- ses = cifs_sb_tcon(cifs_sb)->ses;
-
- if (!ses) {
- rc = -EINVAL;
+ tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
goto out_err;
}
+ ses = tcon->ses;
+
/*
* The MSDFS spec states that paths in DFS referral requests and
* responses must be prefixed by a single '\' character instead of
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 037dbab..27fc7d9 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -15,6 +15,8 @@
* the GNU Lesser General Public License for more details.
*
*/
+#include <linux/radix-tree.h>
+
#ifndef _CIFS_FS_SB_H
#define _CIFS_FS_SB_H
@@ -36,7 +38,10 @@
#define CIFS_MOUNT_MULTISES 0x8000 /* multisession mount */
struct cifs_sb_info {
- struct cifsTconInfo *tcon; /* primary mount */
+ struct radix_tree_root tcon_tree;
+#define CIFS_TCON_MASTER_TAG 0 /* tcon is "master" (mount) tcon */
+#define CIFS_TCON_PENDING_TAG 1 /* tcon is under construction */
+ spinlock_t tcon_tree_lock;
struct nls_table *local_nls;
unsigned int rsize;
unsigned int wsize;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 5e4ea43..1497ea5 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -555,10 +555,14 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
__u16 fid, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int xid, rc;
+ if (IS_ERR(tcon))
+ return (struct cifs_ntsd *) tcon;
+
xid = GetXid();
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
FreeXid(xid);
@@ -570,13 +574,17 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
const char *path, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int oplock = 0;
int xid, rc;
__u16 fid;
+ if (IS_ERR(tcon))
+ return (struct cifs_ntsd *) tcon;
+
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, READ_CONTROL, 0,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -584,10 +592,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
goto out;
}
- rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen);
+ rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
- CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
+ CIFSSMBClose(xid, tcon, fid);
out:
FreeXid(xid);
return pntsd;
@@ -615,9 +623,13 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
struct cifs_ntsd *pnntsd, u32 acllen)
{
int xid, rc;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
FreeXid(xid);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
@@ -630,10 +642,14 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
int oplock = 0;
int xid, rc;
__u16 fid;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, WRITE_DAC, 0,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
@@ -641,10 +657,10 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
goto out;
}
- rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen);
+ rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
- CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid);
+ CIFSSMBClose(xid, tcon, fid);
out:
FreeXid(xid);
return rc;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 53ecc94..84755d5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -102,6 +102,8 @@ cifs_read_super(struct super_block *sb, void *data,
cifs_sb = CIFS_SB(sb);
if (cifs_sb == NULL)
return -ENOMEM;
+ INIT_RADIX_TREE(&cifs_sb->tcon_tree, GFP_KERNEL);
+ spin_lock_init(&cifs_sb->tcon_tree_lock);
#ifdef CONFIG_CIFS_DFS_UPCALL
/* copy mount params to sb for use in submounts */
@@ -228,6 +230,9 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
int rc = -EOPNOTSUPP;
int xid;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
xid = GetXid();
buf->f_type = CIFS_MAGIC_NUMBER;
@@ -359,7 +364,7 @@ static int
cifs_show_options(struct seq_file *s, struct vfsmount *m)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
- struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
seq_printf(s, ",unc=%s", tcon->treeName);
@@ -433,20 +438,13 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
+ cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
FreeXid(xid);
return rc;
}
@@ -457,19 +455,13 @@ int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
+ cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
FreeXid(xid);
return rc;
}
@@ -479,19 +471,13 @@ int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
- } else
- rc = -EIO;
-
+ cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
FreeXid(xid);
return rc;
}
@@ -501,19 +487,13 @@ int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
int xid;
int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- if (cifs_sb)
- pTcon = cifs_sb_tcon(cifs_sb);
- else
- return -EIO;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
xid = GetXid();
- if (pTcon) {
- cFYI(1, ("pqstats %p", qstats));
- } else
- rc = -EIO;
-
+ cFYI(1, ("pqstats %p", qstats));
FreeXid(xid);
return rc;
}
@@ -534,9 +514,8 @@ static void cifs_umount_begin(struct super_block *sb)
if (cifs_sb == NULL)
return;
- tcon = cifs_sb_tcon(cifs_sb);
- if (tcon == NULL)
- return;
+ /* FIXME: handle multisession case properly */
+ tcon = cifs_sb_master_tcon(cifs_sb);
read_lock(&cifs_tcp_ses_lock);
if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b47a66b..49c08e0 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -221,6 +221,7 @@ struct cifsSesInfo {
char *serverDomain; /* security realm of server */
int Suid; /* remote smb uid */
uid_t linux_uid; /* local Linux uid */
+ uid_t linux_fsuid; /* fsuid of owner */
int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
@@ -408,12 +409,6 @@ CIFS_SB(struct super_block *sb)
return sb->s_fs_info;
}
-static inline struct cifsTconInfo *
-cifs_sb_tcon(struct cifs_sb_info *cifs_sb)
-{
- return cifs_sb->tcon;
-}
-
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 4b048f1..d8d7fa8 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -93,7 +93,8 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
__u16 fileHandle, struct file *file,
- struct vfsmount *mnt, unsigned int oflags);
+ struct vfsmount *mnt, struct cifsTconInfo *tcon,
+ unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt, int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid);
@@ -118,6 +119,8 @@ extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
const char *path, const __u16 *pfid);
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
+extern struct cifsTconInfo *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
+extern struct cifsTconInfo *cifs_sb_tcon(struct cifs_sb_info *cifs_sb);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3e1efc6..b213a9b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -104,6 +104,15 @@ struct smb_vol {
struct nls_table *local_nls;
};
+#define TLINK_ERROR_EXPIRE (1 * HZ)
+
+#define TCON_LINK_PENDING 1
+struct tcon_link {
+ unsigned long flags;
+ unsigned long time;
+ struct cifsTconInfo *tcon;
+};
+
static int ipv4_connect(struct TCP_Server_Info *server);
static int ipv6_connect(struct TCP_Server_Info *server);
@@ -1699,6 +1708,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
strcpy(ses->domainName, volume_info->domainname);
}
ses->linux_uid = volume_info->linux_uid;
+ ses->linux_fsuid = current_fsuid();
ses->overrideSecFlg = volume_info->secFlg;
mutex_lock(&ses->session_mutex);
@@ -2480,6 +2490,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
struct TCP_Server_Info *srvTcp;
char *full_path;
char *mount_data = mount_data_global;
+ struct tcon_link *tlink;
#ifdef CONFIG_CIFS_DFS_UPCALL
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals = 0;
@@ -2491,6 +2502,7 @@ try_mount_again:
pSesInfo = NULL;
srvTcp = NULL;
full_path = NULL;
+ tlink = NULL;
xid = GetXid();
@@ -2566,8 +2578,6 @@ try_mount_again:
goto remote_path_check;
}
- cifs_sb->tcon = tcon;
-
/* do not care if following two calls succeed - informational */
if (!tcon->ipc) {
CIFSSMBQFSDeviceInfo(xid, tcon);
@@ -2676,6 +2686,29 @@ remote_path_check:
#endif
}
+ /* now, hang the tcon off of the superblock */
+ tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
+ if (tlink == NULL) {
+ rc = -ENOMEM;
+ goto mount_fail_check;
+ }
+
+ tlink->tcon = tcon;
+ tlink->time = jiffies;
+
+ rc = radix_tree_preload(GFP_KERNEL);
+ if (rc == -ENOMEM) {
+ kfree(tlink);
+ goto mount_fail_check;
+ }
+
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ radix_tree_insert(&cifs_sb->tcon_tree, pSesInfo->linux_fsuid, tlink);
+ radix_tree_tag_set(&cifs_sb->tcon_tree, pSesInfo->linux_fsuid,
+ CIFS_TCON_MASTER_TAG);
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+ radix_tree_preload_end();
+
mount_fail_check:
/* on error free sesinfo and tcon struct if needed */
if (rc) {
@@ -2862,19 +2895,35 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
int
cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
{
- int rc = 0;
+ int i, ret;
char *tmp;
+ struct tcon_link *tlink[8];
+ unsigned long index = 0;
+
+ while (1) {
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ ret = radix_tree_gang_lookup(&cifs_sb->tcon_tree,
+ (void **)tlink, index,
+ ARRAY_SIZE(tlink));
+ for (i = 0; i < ret; i++) {
+ index = (unsigned long)tlink[i]->tcon->ses->linux_fsuid;
+ radix_tree_delete(&cifs_sb->tcon_tree, index);
+ }
+ spin_unlock(&cifs_sb->tcon_tree_lock);
- if (cifs_sb_tcon(cifs_sb))
- cifs_put_tcon(cifs_sb_tcon(cifs_sb));
+ for (i = 0; i < ret; i++)
+ cifs_put_tcon(tlink[i]->tcon);
+
+ if (!ret)
+ break;
+ }
- cifs_sb->tcon = NULL;
tmp = cifs_sb->prepath;
cifs_sb->prepathlen = 0;
cifs_sb->prepath = NULL;
kfree(tmp);
- return rc;
+ return 0;
}
int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
@@ -2931,3 +2980,148 @@ ss_err_exit:
return rc;
}
+struct cifsTconInfo *
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
+{
+ struct cifsTconInfo *master_tcon = cifs_sb_master_tcon(cifs_sb);
+ struct cifsSesInfo *ses;
+ struct cifsTconInfo *tcon = NULL;
+ struct TCP_Server_Info *server = master_tcon->ses->server;
+ struct smb_vol *vol_info;
+
+ vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
+ if (vol_info == NULL) {
+ tcon = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ vol_info->username = kzalloc(MAX_USERNAME_SIZE + 1, GFP_KERNEL);
+ if (vol_info->username == NULL) {
+ tcon = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ snprintf(vol_info->username, MAX_USERNAME_SIZE, "krb5user:0x%x", fsuid);
+ vol_info->local_nls = cifs_sb->local_nls;
+ vol_info->linux_uid = current_uid();
+
+ /* for multisession mounts, force krb5 for now */
+ vol_info->secFlg = server->secMode &
+ (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+ vol_info->secFlg |= (CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_KRB5);
+
+ vol_info->UNC = master_tcon->treeName;
+ vol_info->retry = master_tcon->retry;
+ vol_info->nocase = master_tcon->nocase;
+ vol_info->local_lease = master_tcon->local_lease;
+ vol_info->no_linux_ext = !master_tcon->unix_ext;
+
+ ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
+ if (IS_ERR(ses)) {
+ tcon = (struct cifsTconInfo *) ses;
+ goto out;
+ }
+
+ tcon = cifs_get_tcon(ses, vol_info);
+ if (IS_ERR(tcon)) {
+ cifs_put_smb_ses(ses);
+ goto out;
+ }
+
+ if (ses->capabilities & CAP_UNIX)
+ reset_cifs_unix_caps(0, tcon, NULL, vol_info);
+out:
+ kfree(vol_info->username);
+ kfree(vol_info);
+
+ return tcon;
+}
+
+struct cifsTconInfo *
+cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
+{
+ struct tcon_link *tlink;
+ unsigned int ret;
+
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ ret = radix_tree_gang_lookup_tag(&cifs_sb->tcon_tree, (void **) &tlink,
+ 0, 1, CIFS_TCON_MASTER_TAG);
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+
+ /* the master tcon should always be present */
+ if (ret == 0)
+ BUG();
+
+ return tlink->tcon;
+}
+
+static int
+cifs_sb_tcon_pending_wait(void *unused)
+{
+ schedule();
+ return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+struct cifsTconInfo *
+cifs_sb_tcon(struct cifs_sb_info *cifs_sb)
+{
+ int ret;
+ unsigned long fsuid = (unsigned long) current_fsuid();
+ struct tcon_link *tlink, *newtlink;
+
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTISES))
+ return cifs_sb_master_tcon(cifs_sb);
+
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ tlink = radix_tree_lookup(&cifs_sb->tcon_tree, fsuid);
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+
+ if (tlink == NULL) {
+ newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
+ if (newtlink == NULL)
+ return ERR_PTR(-ENOMEM);
+ newtlink->time = jiffies;
+ newtlink->tcon = ERR_PTR(-EACCES);
+ set_bit(TCON_LINK_PENDING, &newtlink->flags);
+
+ ret = radix_tree_preload(GFP_KERNEL);
+ if (ret != 0) {
+ kfree(newtlink);
+ return ERR_PTR(ret);
+ }
+
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ tlink = radix_tree_lookup(&cifs_sb->tcon_tree, fsuid);
+ if (!tlink) {
+ tlink = newtlink;
+ newtlink = NULL;
+ ret = radix_tree_insert(&cifs_sb->tcon_tree, fsuid,
+ tlink);
+ }
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+ radix_tree_preload_end();
+ kfree(newtlink);
+ if (ret)
+ return ERR_PTR(ret);
+ } else {
+ ret = wait_on_bit(&tlink->flags, TCON_LINK_PENDING,
+ cifs_sb_tcon_pending_wait,
+ TASK_INTERRUPTIBLE);
+ if (ret)
+ return ERR_PTR(ret);
+
+ spin_lock(&cifs_sb->tcon_tree_lock);
+ if (!IS_ERR(tlink->tcon) ||
+ time_before(jiffies, tlink->time + TLINK_ERROR_EXPIRE)) {
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+ return tlink->tcon;
+ }
+ set_bit(TCON_LINK_PENDING, &tlink->flags);
+ spin_unlock(&cifs_sb->tcon_tree_lock);
+ }
+
+ tlink->tcon = cifs_construct_tcon(cifs_sb, fsuid);
+ clear_bit(TCON_LINK_PENDING, &tlink->flags);
+ wake_up_bit(&tlink->flags, TCON_LINK_PENDING);
+ return tlink->tcon;
+}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3467626..680c87a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -53,18 +53,19 @@ build_path_from_dentry(struct dentry *direntry)
int dfsplen;
char *full_path;
char dirsep;
- struct cifs_sb_info *cifs_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+ /* FIXME: this is racy -- need to take proper references */
if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
- cifs_sb = CIFS_SB(direntry->d_sb);
dirsep = CIFS_DIR_SEP(cifs_sb);
pplen = cifs_sb->prepathlen;
- if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
+ if (tcon && (tcon->Flags & SMB_SHARE_IS_IN_DFS))
+ dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
cifs_bp_rename_retry:
@@ -117,7 +118,7 @@ cifs_bp_rename_retry:
/* BB test paths to Windows with '/' in the midst of prepath */
if (dfsplen) {
- strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
+ strncpy(full_path, tcon->treeName, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
@@ -126,7 +127,7 @@ cifs_bp_rename_retry:
}
}
}
- strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
+ strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
return full_path;
}
@@ -138,7 +139,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
int oplock = 0;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
- struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL)
@@ -163,7 +163,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &cifs_sb_tcon(cifs_sb)->openFileList);
+ list_add(&pCifsFile->tlist, &tcon->openFileList);
pCifsInode = CIFS_I(newinode);
if (pCifsInode) {
/* if readable file instance put first in list*/
@@ -193,14 +193,17 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
- struct cifs_fattr fattr;
struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+ struct cifs_fattr fattr;
if (IS_ERR(tcon))
return PTR_ERR(tcon);
cFYI(1, ("posix open %s", full_path));
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (presp_data == NULL)
return -ENOMEM;
@@ -297,17 +300,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
*/
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
__u16 fileHandle;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *tcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
int disposition = FILE_OVERWRITE_IF;
- xid = GetXid();
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
- cifs_sb = CIFS_SB(inode->i_sb);
- tcon = cifs_sb_tcon(cifs_sb);
+ xid = GetXid();
if (IS_ERR(tcon)) {
FreeXid(xid);
@@ -390,7 +393,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY;
- if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
+ if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -491,18 +494,18 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
{
int rc = -EPERM;
int xid;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
char *full_path = NULL;
struct inode *newinode = NULL;
if (!old_valid_dev(device_number))
return -EINVAL;
- xid = GetXid();
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
- cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb_tcon(cifs_sb);
+ xid = GetXid();
full_path = build_path_from_dentry(direntry);
if (full_path == NULL)
@@ -635,6 +638,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ FreeXid(xid);
+ return (struct dentry *) pTcon;
+ }
/*
* Don't allow the separator character in a path component.
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 308520e..4078e95 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -264,9 +264,9 @@ int cifs_open(struct inode *inode, struct file *file)
__u16 netfid;
FILE_ALL_INFO *buf = NULL;
- xid = GetXid();
-
cifs_sb = CIFS_SB(inode->i_sb);
+
+ xid = GetXid();
tcon = cifs_sb_tcon(cifs_sb);
if (IS_ERR(tcon)) {
FreeXid(xid);
@@ -373,7 +373,7 @@ int cifs_open(struct inode *inode, struct file *file)
goto out;
}
- if (cifs_sb_tcon(cifs_sb)->ses->capabilities & CAP_NT_SMBS)
+ if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
@@ -1377,6 +1377,7 @@ static int cifs_writepages(struct address_space *mapping,
int xid, long_op;
cifs_sb = CIFS_SB(mapping->host->i_sb);
+ tcon = cifs_sb_master_tcon(cifs_sb);
/*
* If wsize is smaller that the page cache size, default to writing
@@ -1386,11 +1387,10 @@ static int cifs_writepages(struct address_space *mapping,
return generic_writepages(mapping, wbc);
/* WTF? */
- if ((cifs_sb_tcon(cifs_sb)->ses) && (cifs_sb_tcon(cifs_sb)->ses->server))
- if (cifs_sb_tcon(cifs_sb)->ses->server->secMode &
- (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- if (!experimEnabled)
- return generic_writepages(mapping, wbc);
+ if (tcon->ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ if (!experimEnabled)
+ return generic_writepages(mapping, wbc);
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
if (iov == NULL)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e09bf9f..e8cb95d 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -50,7 +50,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
/* check if server can support readpages */
- if (cifs_sb_tcon(cifs_sb)->ses->server->maxBuf <
+ if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
@@ -300,12 +300,14 @@ int cifs_get_inode_info_unix(struct inode **pinode,
int rc;
FILE_UNIX_BASIC_INFO find_data;
struct cifs_fattr fattr;
- struct cifsTconInfo *tcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
- tcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
/* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -340,11 +342,14 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
int rc;
int oplock = 0;
__u16 netfid;
- struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
char buf[24];
unsigned int bytes_read;
char *pbuf;
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
+
pbuf = buf;
fattr->cf_mode &= ~S_IFMT;
@@ -359,7 +364,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
return -EINVAL; /* EOPNOTSUPP? */
}
- rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+ rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -367,7 +372,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
if (rc == 0) {
int buf_type = CIFS_NO_BUFFER;
/* Read header */
- rc = CIFSSMBRead(xid, pTcon, netfid,
+ rc = CIFSSMBRead(xid, tcon, netfid,
24 /* length */, 0 /* offset */,
&bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) {
@@ -409,7 +414,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
fattr->cf_dtype = DT_REG;
rc = -EOPNOTSUPP; /* or some unknown SFU type */
}
- CIFSSMBClose(xid, pTcon, netfid);
+ CIFSSMBClose(xid, tcon, netfid);
}
return rc;
}
@@ -428,8 +433,12 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
ssize_t rc;
char ea_value[4];
__u32 mode;
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
+
+ if (IS_ERR(tcon))
+ return PTR_ERR(tcon);
- rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS",
+ rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -455,6 +464,8 @@ static void
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
struct cifs_sb_info *cifs_sb, bool adjust_tz)
{
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+
memset(fattr, 0, sizeof(*fattr));
fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
if (info->DeletePending)
@@ -469,8 +480,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
if (adjust_tz) {
- fattr->cf_ctime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
- fattr->cf_mtime.tv_sec += cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
+ fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+ fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
}
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
@@ -540,15 +551,17 @@ int cifs_get_inode_info(struct inode **pinode,
struct super_block *sb, int xid, const __u16 *pfid)
{
int rc = 0, tmprc;
- struct cifsTconInfo *pTcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
char *buf = NULL;
bool adjustTZ = false;
struct cifs_fattr fattr;
- pTcon = cifs_sb_tcon(cifs_sb);
cFYI(1, ("Getting info on %s", full_path));
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1, ("No need to revalidate cached inode sizes"));
@@ -669,6 +682,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
int pplen = cifs_sb->prepathlen;
int dfsplen;
char *full_path = NULL;
+ struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
/* if no prefix path, simply set path to the root of share to "" */
if (pplen == 0) {
@@ -678,8 +692,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
}
- if (cifs_sb_tcon(cifs_sb) && (cifs_sb_tcon(cifs_sb)->Flags & SMB_SHARE_IS_IN_DFS))
- dfsplen = strnlen(cifs_sb_tcon(cifs_sb)->treeName, MAX_TREE_SIZE + 1);
+ if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+ dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
@@ -688,7 +702,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
return full_path;
if (dfsplen) {
- strncpy(full_path, cifs_sb_tcon(cifs_sb)->treeName, dfsplen);
+ strncpy(full_path, tcon->treeName, dfsplen);
/* switch slash direction in prepath depending on whether
* windows or posix style path names
*/
@@ -757,18 +771,21 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
{
int xid;
- struct cifs_sb_info *cifs_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
struct inode *inode = NULL;
long rc;
char *full_path;
- cifs_sb = CIFS_SB(sb);
+ if (IS_ERR(tcon))
+ return (struct inode *) tcon;
+
full_path = cifs_build_path_to_root(cifs_sb);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);
xid = GetXid();
- if (cifs_sb_tcon(cifs_sb)->unix_ext)
+ if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
else
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -777,7 +794,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
if (!inode)
return ERR_PTR(-ENOMEM);
- if (rc && cifs_sb_tcon(cifs_sb)->ipc) {
+ if (rc && tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
@@ -860,7 +877,11 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
goto set_via_filehandle;
}
- pTcon = open_file->tcon;
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ goto out;
+ }
/*
* NT4 apparently returns success on this call, but it doesn't
@@ -926,6 +947,11 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
__u32 dosattr, origattr;
FILE_BASIC_INFO *info_buf = NULL;
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto out;
+ }
+
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
&netfid, &oplock, NULL, cifs_sb->local_nls,
@@ -1040,6 +1066,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
xid = GetXid();
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ FreeXid(xid);
+ return rc;
+ }
/* Unlink can be called from rename so we can not take the
* sb->s_vfs_rename_mutex here */
@@ -1136,6 +1167,11 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1316,6 +1352,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -1360,6 +1401,9 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
__u16 srcfid;
int oplock, rc;
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
/* try path-based rename first */
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -1398,14 +1442,21 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
char *toName = NULL;
struct cifs_sb_info *cifs_sb_source;
struct cifs_sb_info *cifs_sb_target;
- struct cifsTconInfo *tcon;
+ struct cifsTconInfo *source_tcon, *target_tcon;
FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
FILE_UNIX_BASIC_INFO *info_buf_target;
int xid, rc, tmprc;
cifs_sb_target = CIFS_SB(target_dir->i_sb);
cifs_sb_source = CIFS_SB(source_dir->i_sb);
- tcon = cifs_sb_tcon(cifs_sb_source);
+ source_tcon = cifs_sb_tcon(cifs_sb_source);
+ target_tcon = cifs_sb_tcon(cifs_sb_target);
+
+ if (IS_ERR(source_tcon))
+ return PTR_ERR(source_tcon);
+
+ if (IS_ERR(target_tcon))
+ return PTR_ERR(target_tcon);
xid = GetXid();
@@ -1413,7 +1464,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
* BB: this might be allowed if same server, but different share.
* Consider adding support for this
*/
- if (tcon != cifs_sb_tcon(cifs_sb_target)) {
+ if (source_tcon != target_tcon) {
rc = -EXDEV;
goto cifs_rename_exit;
}
@@ -1437,7 +1488,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
rc = cifs_do_rename(xid, source_dentry, fromName,
target_dentry, toName);
- if (rc == -EEXIST && tcon->unix_ext) {
+ if (rc == -EEXIST && source_tcon->unix_ext) {
/*
* Are src and dst hardlinks of same inode? We can
* only tell with unix extensions enabled
@@ -1451,7 +1502,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
}
info_buf_target = info_buf_source + 1;
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
+ tmprc = CIFSSMBUnixQPathInfo(xid, source_tcon, fromName,
info_buf_source,
cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags &
@@ -1459,7 +1510,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
if (tmprc != 0)
goto unlink_target;
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
+ tmprc = CIFSSMBUnixQPathInfo(xid, source_tcon,
toName, info_buf_target,
cifs_sb_target->local_nls,
/* remap based on source sb */
@@ -1562,12 +1613,19 @@ int cifs_revalidate_dentry(struct dentry *dentry)
char *full_path = NULL;
struct inode *inode = dentry->d_inode;
struct super_block *sb = dentry->d_sb;
+ struct cifsTconInfo *tcon;
if (inode == NULL)
return -ENOENT;
xid = GetXid();
+ tcon = cifs_sb_tcon(CIFS_SB(sb));
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto check_inval;
+ }
+
if (!cifs_inode_needs_reval(inode))
goto check_inval;
@@ -1690,6 +1748,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
if (pTcon == NULL)
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
@@ -1837,6 +1898,10 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
cifsFileInfo_put(open_file);
} else {
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ goto out;
+ }
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -2009,6 +2074,9 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if (pTcon->unix_ext)
return cifs_setattr_unix(direntry, attrs);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index c99e6fc..e6227a3 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -44,6 +44,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifs_sb_target = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb_target);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */
@@ -116,6 +118,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ goto out;
+ }
+
/*
* For now, we just handle symlinks with unix extensions enabled.
* Eventually we should handle NTFS reparse points, and MacOS
@@ -168,9 +175,13 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
-
if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 80edc23..51ca940 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -726,6 +726,6 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
"properly. Hardlinks will not be recognized on this "
"mount. Consider mounting with the \"noserverino\" "
"option to silence this message.",
- cifs_sb_tcon(cifs_sb)->treeName));
+ cifs_sb_master_tcon(cifs_sb)->treeName));
}
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 491745f..e26504b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -101,7 +101,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
return NULL;
}
- if (cifs_sb_tcon(CIFS_SB(sb))->nocase)
+ if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase)
dentry->d_op = &cifs_ci_dentry_ops;
else
dentry->d_op = &cifs_dentry_ops;
@@ -170,7 +170,7 @@ static void
cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
struct cifs_sb_info *cifs_sb)
{
- int offset = cifs_sb_tcon(cifs_sb)->ses->server->timeAdj;
+ int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
memset(fattr, 0, sizeof(*fattr));
fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
@@ -231,6 +231,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
if (cifs_sb == NULL)
return -EINVAL;
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon))
+ return PTR_ERR(pTcon);
+
if (file->private_data == NULL)
file->private_data =
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
@@ -240,11 +244,9 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile = file->private_data;
cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false;
- cifsFile->tcon = cifs_sb_tcon(cifs_sb);
+ cifsFile->tcon = pTcon;
pTcon = cifsFile->tcon;
- if (pTcon == NULL)
- return -EINVAL;
full_path = build_path_from_dentry(file->f_path.dentry);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 7efdb5a..d37dcdc 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -61,6 +61,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -116,6 +121,11 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -224,6 +234,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
@@ -345,13 +360,19 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
return -EIO;
cifs_sb = CIFS_SB(sb);
- pTcon = cifs_sb_tcon(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP;
xid = GetXid();
+ pTcon = cifs_sb_tcon(cifs_sb);
+ if (IS_ERR(pTcon)) {
+ rc = PTR_ERR(pTcon);
+ FreeXid(xid);
+ return rc;
+ }
+
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
rc = -ENOMEM;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 13/15] cifs: on multises mount, set ownership to current_fsuid/current_fsgid
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (11 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 12/15] cifs: build sessions and tcons on the fly Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 14/15] cifs: add "multises" mount option Jeff Layton
` (2 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...when unix extensions aren't enabled. This makes everything on
the mount appear to be owned by the current user.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/inode.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e8cb95d..4a0e5e7 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1659,11 +1659,19 @@ check_inval:
int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
+ struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb);
int err = cifs_revalidate_dentry(dentry);
+
if (!err) {
generic_fillattr(dentry->d_inode, stat);
stat->blksize = CIFS_MAX_MSGSIZE;
stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTISES &&
+ !tcon->unix_ext) {
+ stat->uid = current_fsuid();
+ stat->gid = current_fsgid();
+ }
}
return err;
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 14/15] cifs: add "multises" mount option
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (12 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 13/15] cifs: on multises mount, set ownership to current_fsuid/current_fsgid Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-30 19:51 ` [PATCH 15/15] cifs: temporary hack -- set secType to Kerberos Jeff Layton
2010-03-31 12:18 ` [PATCH 00/15] cifs: implement multisession mounts (RFC) Jamie Lokier
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
This allows someone to declare a mount as multisession mount.
Multisession mounts also imply "noperm" since we want to allow
the server to handle permission checking. It also (for now)
requires Kerberos authentication. Eventually, we could expand
this to other authtypes, but that requires a scheme to allow
per-user credential stashing in some form.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/connect.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index b213a9b..9bf590d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -96,6 +96,7 @@ struct smb_vol {
bool noblocksnd:1;
bool noautotune:1;
bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
+ bool multises:1;
unsigned int rsize;
unsigned int wsize;
bool sockopt_tcp_nodelay:1;
@@ -1339,6 +1340,9 @@ cifs_parse_mount_options(char *options, const char *devname,
printk(KERN_WARNING "CIFS: Mount option noac not "
"supported. Instead set "
"/proc/fs/cifs/LookupCacheEnabled to 0\n");
+ } else if (strnicmp(data, "multises", 8) == 0) {
+ vol->multises = 1;
+ vol->secFlg |= CIFSSEC_MAY_KRB5;
} else
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
data);
@@ -2400,6 +2404,9 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
if (pvolume_info->dynperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+ if (pvolume_info->multises)
+ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTISES |
+ CIFS_MOUNT_NO_PERM);
if (pvolume_info->direct_io) {
cFYI(1, ("mounting share using direct i/o"));
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 15/15] cifs: temporary hack -- set secType to Kerberos
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (13 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 14/15] cifs: add "multises" mount option Jeff Layton
@ 2010-03-30 19:51 ` Jeff Layton
2010-03-31 12:18 ` [PATCH 00/15] cifs: implement multisession mounts (RFC) Jamie Lokier
15 siblings, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-30 19:51 UTC (permalink / raw)
To: linux-cifs-client; +Cc: linux-fsdevel
From: Jeff Layton <jlayton@redhat.com>
...fixing this the right way requires an overhaul of how authentication is
handled. Note that this breaks multiple mounts to the same server that use
non-krb5 auth. For the first mount to the server, CIFSMBNegotiate will clobber
this setting. Subsequent mounts that use the same TCP_Server_Info though will
bypass that call and will end up using krb5.
The right way to fix this is to change how the secType gets set in the
first place such that it's decided on a per-session basis rather than in
CIFSSMBNegotiate.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/cifs/connect.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9bf590d..4b0c924 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1714,6 +1714,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
ses->linux_uid = volume_info->linux_uid;
ses->linux_fsuid = current_fsuid();
ses->overrideSecFlg = volume_info->secFlg;
+ ses->secType = Kerberos;
mutex_lock(&ses->session_mutex);
rc = cifs_setup_session(xid, ses, volume_info->local_nls);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 00/15] cifs: implement multisession mounts (RFC)
2010-03-30 19:51 [PATCH 00/15] cifs: implement multisession mounts (RFC) Jeff Layton
` (14 preceding siblings ...)
2010-03-30 19:51 ` [PATCH 15/15] cifs: temporary hack -- set secType to Kerberos Jeff Layton
@ 2010-03-31 12:18 ` Jamie Lokier
2010-03-31 13:42 ` Jeff Layton
2010-03-31 16:43 ` Jeremy Allison
15 siblings, 2 replies; 19+ messages in thread
From: Jamie Lokier @ 2010-03-31 12:18 UTC (permalink / raw)
To: Jeff Layton; +Cc: linux-cifs-client, linux-fsdevel
Jeff Layton wrote:
> To be honest, I have doubts anyway about whether we should take this
> patch into what seems to be considered a legacy codebase these days.
> It's rather difficult to bolt this functionality onto the existing CIFS
> codebase. It's probably more suited to putting into the newer SMB2
> codebase. That said, it'll probably be just as difficult to do this
> there since most of that code was copied from CIFS.
Legacy?
Maybe only in environments where everyone is running only Windows
servers, all of them less than 2 years old :-) (I've yet to see such
an environment, btw).
The stable version of Samba (3.x) supports only SMB1.
Samba 4, which does support SMB2, is "not yet in a state where it can
replace existing production deployments"; the Ubuntu package
description says "experimental, should not be used in production".
In fact when I wanted to deploy an SMB2 service from Linux recently
(to get better file link semantics on a Windows client), I gave up on
it, it was too disruptive to replace Samba 3 with Samba 4.
This per-user patchset you've produced sounds quite useful, thank you.
Please don't think you are targetting only a few horribly outdated
environments with it :-)
-- Jamie
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 00/15] cifs: implement multisession mounts (RFC)
2010-03-31 12:18 ` [PATCH 00/15] cifs: implement multisession mounts (RFC) Jamie Lokier
@ 2010-03-31 13:42 ` Jeff Layton
2010-03-31 16:43 ` Jeremy Allison
1 sibling, 0 replies; 19+ messages in thread
From: Jeff Layton @ 2010-03-31 13:42 UTC (permalink / raw)
To: Jamie Lokier; +Cc: linux-fsdevel, linux-cifs-client
On Wed, 31 Mar 2010 13:18:54 +0100
Jamie Lokier <jamie@shareable.org> wrote:
> Jeff Layton wrote:
> > To be honest, I have doubts anyway about whether we should take this
> > patch into what seems to be considered a legacy codebase these days.
> > It's rather difficult to bolt this functionality onto the existing CIFS
> > codebase. It's probably more suited to putting into the newer SMB2
> > codebase. That said, it'll probably be just as difficult to do this
> > there since most of that code was copied from CIFS.
>
> Legacy?
>
> Maybe only in environments where everyone is running only Windows
> servers, all of them less than 2 years old :-) (I've yet to see such
> an environment, btw).
>
> The stable version of Samba (3.x) supports only SMB1.
>
> Samba 4, which does support SMB2, is "not yet in a state where it can
> replace existing production deployments"; the Ubuntu package
> description says "experimental, should not be used in production".
>
> In fact when I wanted to deploy an SMB2 service from Linux recently
> (to get better file link semantics on a Windows client), I gave up on
> it, it was too disruptive to replace Samba 3 with Samba 4.
>
> This per-user patchset you've produced sounds quite useful, thank you.
> Please don't think you are targetting only a few horribly outdated
> environments with it :-)
>
Ok...legacy is probably too strong a word... :)
The main problem still stands though. This is a very disruptive patch
set and CIFS really wasn't designed with this in mind.
Part of that paragraph comes from my frustration with the direction
taken by the direction of SMB2 development. Rather than building on the
existing CIFS codebase and abstracting it out where needed, it was
deemed less disruptive to copy large swaths of CIFS wholesale
and build an entirely new SMB2 fs from that.
That of course means that any improvements or bugfixes to CIFS have to
essentially be "ported" to the SMB2 code, which is a tremendous
disincentive to do anything large scale on either code base.
In any case, I plan to keep working on this, but I'm starting to wonder
whether my time would be better spent starting an entirely new SMB
filesystem that's multiuser from the get-go and that could handle
either SMB version.
Thanks,
--
Jeff Layton <jlayton@samba.org>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 00/15] cifs: implement multisession mounts (RFC)
2010-03-31 12:18 ` [PATCH 00/15] cifs: implement multisession mounts (RFC) Jamie Lokier
2010-03-31 13:42 ` Jeff Layton
@ 2010-03-31 16:43 ` Jeremy Allison
1 sibling, 0 replies; 19+ messages in thread
From: Jeremy Allison @ 2010-03-31 16:43 UTC (permalink / raw)
To: Jamie Lokier; +Cc: Jeff Layton, linux-cifs-client, linux-fsdevel
On Wed, Mar 31, 2010 at 01:18:54PM +0100, Jamie Lokier wrote:
> Jeff Layton wrote:
> > To be honest, I have doubts anyway about whether we should take this
> > patch into what seems to be considered a legacy codebase these days.
> > It's rather difficult to bolt this functionality onto the existing CIFS
> > codebase. It's probably more suited to putting into the newer SMB2
> > codebase. That said, it'll probably be just as difficult to do this
> > there since most of that code was copied from CIFS.
>
> Legacy?
>
> Maybe only in environments where everyone is running only Windows
> servers, all of them less than 2 years old :-) (I've yet to see such
> an environment, btw).
>
> The stable version of Samba (3.x) supports only SMB1.
FYI. There's experimental SMB2 support
in Samba 3.5.x, which we're fixing up as bugs get
reported. Look for it to become "stable" sometime
later in the 3.x code stream.
Jeremy.
^ permalink raw reply [flat|nested] 19+ messages in thread