From 1b12b9c15b4371d83b729b8fc18c670e78a1479b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Aug 2010 21:19:56 +0200 Subject: cifs: use Minshall+French symlink functions If configured, Minshall+French Symlinks are used against all servers. If the server supports UNIX Extensions, we still create Minshall+French Symlinks on write, but on read we fallback to UNIX Extension symlinks. Signed-off-by: Stefan Metzmacher Signed-off-by: Steve French --- fs/cifs/inode.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 93f77d438d3c..016975b8e6dd 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -332,6 +332,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, return rc; } + /* check for Minshall+French symlinks */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { + int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); + } + if (*pinode == NULL) { /* get new inode */ cifs_fill_uniqueid(sb, &fattr); @@ -661,6 +668,13 @@ int cifs_get_inode_info(struct inode **pinode, if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); + /* check for Minshall+French symlinks */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { + tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); + } + if (!*pinode) { *pinode = cifs_iget(sb, &fattr); if (!*pinode) -- cgit v1.2.3-58-ga151 From ba00ba64cf0895e4c2ac507e56306363dc125a90 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 20 Sep 2010 16:01:31 -0700 Subject: cifs: make various routines use the cifsFileInfo->tcon pointer ...where it's available and appropriate. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 4 ++-- fs/cifs/file.c | 39 ++++++++++++++++----------------------- fs/cifs/inode.c | 22 ++++++++++++++++------ fs/cifs/ioctl.c | 17 +++-------------- fs/cifs/readdir.c | 19 ++++++++----------- 5 files changed, 45 insertions(+), 56 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index eeb8c67a3f29..7193494efc03 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -589,6 +589,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; @@ -599,8 +600,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 && - !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 60061b9c2f67..84979fc77862 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -461,7 +461,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) } cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb->tcon; + 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 @@ -575,7 +575,7 @@ int cifs_close(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; + pTcon = pSMBFile->tcon; if (pSMBFile) { struct cifsLockInfo *li, *tmp; write_lock(&GlobalSMBSeslock); @@ -653,11 +653,7 @@ int cifs_closedir(struct inode *inode, struct file *file) xid = GetXid(); if (pCFileStruct) { - struct cifsTconInfo *pTcon; - struct cifs_sb_info *cifs_sb = - CIFS_SB(file->f_path.dentry->d_sb); - - pTcon = cifs_sb->tcon; + struct cifsTconInfo *pTcon = pCFileStruct->tcon; cFYI(1, "Freeing private data in close dir"); write_lock(&GlobalSMBSeslock); @@ -767,7 +763,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 = ((struct cifsFileInfo *)file->private_data)->tcon; if (file->private_data == NULL) { rc = -EBADF; @@ -960,14 +956,14 @@ 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; - /* cFYI(1, " write %d 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 = file->private_data; + pTcon = open_file->tcon; rc = generic_write_checks(file, poffset, &write_size, 0); if (rc) @@ -1062,14 +1058,13 @@ 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; - 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 = file->private_data; + pTcon = open_file->tcon; xid = GetXid(); @@ -1284,7 +1279,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; @@ -1293,7 +1287,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; offset += (loff_t)from; write_data = kmap(page); @@ -1352,6 +1345,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; @@ -1501,8 +1495,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, + rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, bytes_to_write, offset, &bytes_written, iov, n_iov, @@ -1520,8 +1515,7 @@ retry: else set_bit(AS_EIO, &mapping->flags); } else { - cifs_stats_bytes_written(cifs_sb->tcon, - bytes_written); + cifs_stats_bytes_written(tcon, bytes_written); } } for (i = 0; i < n_iov; i++) { @@ -1665,7 +1659,7 @@ int cifs_fsync(struct file *file, 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 = smbfile->tcon; if (!rc && tcon && smbfile && !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); @@ -1750,7 +1744,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; if (file->private_data == NULL) { rc = -EBADF; @@ -1758,6 +1751,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, return rc; } open_file = file->private_data; + pTcon = open_file->tcon; if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1831,7 +1825,6 @@ 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; if (file->private_data == NULL) { rc = -EBADF; @@ -1839,6 +1832,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, return rc; } open_file = file->private_data; + pTcon = open_file->tcon; if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1974,7 +1968,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } open_file = file->private_data; cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - pTcon = cifs_sb->tcon; + pTcon = open_file->tcon; /* * Reads as many pages as possible from fscache. Returns -ENOBUFS @@ -2312,7 +2306,6 @@ void cifs_oplock_break(struct work_struct *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)) { @@ -2339,7 +2332,7 @@ void cifs_oplock_break(struct work_struct *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, 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 016975b8e6dd..0fa145596fcf 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -288,8 +288,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; struct cifsFileInfo *cfile = filp->private_data; + struct cifsTconInfo *tcon = cfile->tcon; xid = GetXid(); rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); @@ -522,8 +522,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; struct cifsFileInfo *cfile = filp->private_data; + struct cifsTconInfo *tcon = cfile->tcon; xid = GetXid(); rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); @@ -891,7 +891,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; FILE_BASIC_INFO info_buf; if (attrs == NULL) @@ -934,9 +934,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 = cifs_sb->tcon; + /* * NT4 apparently returns success on this call, but it doesn't * really work. @@ -1611,11 +1614,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(inode->i_sb)->tcon->unix_ext) + if (cfile->tcon->unix_ext) rc = cifs_get_file_info_unix(filp); else rc = cifs_get_file_info(filp); @@ -1720,7 +1724,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 = NULL; /* * To avoid spurious oplock breaks from server, in the case of @@ -1735,6 +1739,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); @@ -1749,6 +1754,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, rc = -EINVAL; if (rc != 0) { + if (pTcon == NULL) + pTcon = cifs_sb->tcon; + /* 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 @@ -1798,7 +1806,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; struct cifs_unix_set_info_args *args = NULL; struct cifsFileInfo *open_file; @@ -1889,9 +1897,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; 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 9d38a71c8e14..cc70a61a47d2 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -37,11 +37,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) int xid; struct cifs_sb_info *cifs_sb; #ifdef CONFIG_CIFS_POSIX + struct cifsFileInfo *pSMBFile = filep->private_data; + struct cifsTconInfo *tcon = pSMBFile->tcon; __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; - __u64 caps; - struct cifsTconInfo *tcon; - struct cifsFileInfo *pSMBFile = filep->private_data; + __u64 caps = le64_to_cpu(tcon->fsUnixInfo.Capability); #endif /* CONFIG_CIFS_POSIX */ xid = GetXid(); @@ -50,17 +50,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; - 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 6a8b417babab..d7784a95134f 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -228,22 +228,21 @@ 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; - - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - if (cifs_sb == NULL) - return -EINVAL; - - pTcon = cifs_sb->tcon; + cifsFile->tcon = cifs_sb->tcon; + pTcon = cifsFile->tcon; if (pTcon == NULL) return -EINVAL; @@ -786,9 +785,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; - if (pTcon == NULL) - return -EINVAL; switch ((int) file->f_pos) { case 0: @@ -838,6 +834,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) { -- cgit v1.2.3-58-ga151 From a6e8a8455c94565c53e1a1756d2ab9d9e3a902b8 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 20 Sep 2010 16:01:33 -0700 Subject: cifs: add function to get a tcon from cifs_sb 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 Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 2 +- fs/cifs/cifsacl.c | 16 ++++++++-------- fs/cifs/cifsfs.c | 11 +++-------- fs/cifs/cifsglob.h | 6 ++++++ fs/cifs/connect.c | 4 ++-- fs/cifs/dir.c | 20 ++++++++++---------- fs/cifs/file.c | 4 ++-- fs/cifs/fscache.c | 7 ++++--- fs/cifs/inode.c | 49 +++++++++++++++++++++++++------------------------ fs/cifs/link.c | 8 ++++---- fs/cifs/misc.c | 2 +- fs/cifs/readdir.c | 8 ++++---- fs/cifs/xattr.c | 8 ++++---- 13 files changed, 74 insertions(+), 71 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index d6ced7aa23cf..f1e13ea45a17 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -316,7 +316,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 85d7cf7ff2c8..32f244909a0d 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -559,7 +559,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); @@ -577,7 +577,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) { @@ -585,10 +585,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; @@ -618,7 +618,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); @@ -634,7 +634,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) { @@ -642,10 +642,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 7193494efc03..b9624abb7261 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -137,9 +137,6 @@ cifs_read_super(struct super_block *sb, void *data, sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; sb->s_bdi = &cifs_sb->bdi; -/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) - sb->s_blocksize = - cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = cifs_root_iget(sb, ROOT_I); @@ -225,7 +222,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; @@ -367,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; + struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); struct sockaddr *srcaddr; srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; @@ -458,9 +455,7 @@ static void cifs_umount_begin(struct super_block *sb) if (cifs_sb == NULL) return; - tcon = cifs_sb->tcon; - if (tcon == NULL) - return; + tcon = cifs_sb_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 6f3968a5fea4..c3510168438e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -413,6 +413,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 230410e0a453..c42d37fb5b7c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3026,8 +3026,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 613589cf5172..f660a15eb14f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -64,8 +64,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++) { @@ -150,7 +150,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, pCifsFile->pfile = file; pCifsFile->invalidHandle = false; pCifsFile->closePend = false; - pCifsFile->tcon = cifs_sb->tcon; + pCifsFile->tcon = cifs_sb_tcon(cifs_sb); mutex_init(&pCifsFile->fh_mutex); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); @@ -158,7 +158,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); 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); @@ -298,7 +298,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) { @@ -373,7 +373,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 (tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, create_options, &fileHandle, &oplock, buf, cifs_sb->local_nls, @@ -504,7 +504,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) { @@ -631,7 +631,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 84979fc77862..6712c2b0a0ae 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -235,7 +235,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); @@ -345,7 +345,7 @@ int cifs_open(struct inode *inode, struct file *file) goto out; } - if (cifs_sb->tcon->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 diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 9f3f5c4be161..ec4318b019cc 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -66,11 +66,11 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) if (cifsi->fscache) return; - cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache, + cifsi->fscache = fscache_acquire_cookie(cifs_sb_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", - cifs_sb->tcon->fscache, cifsi->fscache); + cifs_sb_tcon(cifs_sb)->fscache, cifsi->fscache); } void cifs_fscache_release_inode_cookie(struct inode *inode) @@ -117,7 +117,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode) /* retire the current fscache cache and get a new one */ fscache_relinquish_cookie(cifsi->fscache, 1); - cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache, + cifsi->fscache = fscache_acquire_cookie( + cifs_sb_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 0fa145596fcf..dce2d598927e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -52,7 +52,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 @@ -315,7 +315,8 @@ 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 */ @@ -360,7 +361,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; @@ -449,7 +450,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); @@ -489,8 +490,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); @@ -566,7 +567,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)) { @@ -706,8 +707,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; @@ -716,7 +717,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 */ @@ -841,7 +842,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, @@ -852,10 +853,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) #ifdef CONFIG_CIFS_FSCACHE /* populate tcon->resource_id */ - cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; + cifs_sb_tcon(cifs_sb)->resource_id = CIFS_I(inode)->uniqueid; #endif - 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; @@ -938,7 +939,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, goto set_via_filehandle; } - pTcon = cifs_sb->tcon; + pTcon = cifs_sb_tcon(cifs_sb); /* * NT4 apparently returns success on this call, but it doesn't @@ -1000,7 +1001,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; @@ -1111,7 +1112,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; @@ -1213,7 +1214,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) { @@ -1394,7 +1395,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) { @@ -1435,7 +1436,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; @@ -1486,7 +1487,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, int xid, rc, tmprc; cifs_sb = CIFS_SB(source_dir->i_sb); - tcon = cifs_sb->tcon; + tcon = cifs_sb_tcon(cifs_sb); xid = GetXid(); @@ -1660,7 +1661,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, @@ -1755,7 +1756,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, if (rc != 0) { if (pTcon == NULL) - pTcon = cifs_sb->tcon; + pTcon = cifs_sb_tcon(cifs_sb); /* Set file size by pathname rather than by handle either because no valid, writeable file handle for @@ -1901,7 +1902,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); cifsFileInfo_put(open_file); } else { - pTcon = cifs_sb->tcon; + pTcon = cifs_sb_tcon(cifs_sb); rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -2086,7 +2087,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/link.c b/fs/cifs/link.c index cbf7b112287b..66db2d61fa43 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -249,7 +249,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, int rc; int oplock = 0; __u16 netfid = 0; - struct cifsTconInfo *pTcon = cifs_sb->tcon; + struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); u8 *buf; char *pbuf; unsigned int bytes_read = 0; @@ -321,7 +321,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) */ @@ -390,7 +390,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(); @@ -459,7 +459,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 3ccadc1326d6..c5cbfdb2a58b 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -729,6 +729,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 d7784a95134f..3efc2424964f 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -102,7 +102,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; @@ -171,7 +171,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, @@ -199,7 +199,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, @@ -241,7 +241,7 @@ 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; + cifsFile->tcon = cifs_sb_tcon(cifs_sb); pTcon = cifsFile->tcon; if (pTcon == NULL) return -EINVAL; diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a1509207bfa6..41f95bf67977 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -61,7 +61,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) { @@ -116,7 +116,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) { @@ -224,7 +224,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) { @@ -346,7 +346,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; -- cgit v1.2.3-58-ga151 From 0d424ad0a4b8c08e45928bccfa5b4b240097b01b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 20 Sep 2010 16:01:35 -0700 Subject: cifs: add cifs_sb_master_tcon and convert some callers to use it At mount time, we'll always need to create a tcon that will serve as a template for others that are associated with the mount. This tcon is known as the "master" tcon. In some cases, we'll need to use that tcon regardless of who's accessing the mount. Add an accessor function for the master tcon and go ahead and switch the appropriate places to use it. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 6 +++--- fs/cifs/cifsglob.h | 7 +++++++ fs/cifs/connect.c | 4 ++-- fs/cifs/dir.c | 10 +++++----- fs/cifs/fscache.c | 12 ++++++------ fs/cifs/inode.c | 29 ++++++++++++++++------------- fs/cifs/misc.c | 2 +- fs/cifs/readdir.c | 4 ++-- 8 files changed, 42 insertions(+), 32 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b9624abb7261..898d2a5cfad2 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -222,7 +222,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(cifs_sb); + struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); int rc = -EOPNOTSUPP; int xid; @@ -364,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); struct sockaddr *srcaddr; srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; @@ -455,7 +455,7 @@ static void cifs_umount_begin(struct super_block *sb) if (cifs_sb == NULL) return; - tcon = cifs_sb_tcon(cifs_sb); + 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 cc8300c741b6..c265ebdcd177 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -419,6 +419,13 @@ cifs_sb_tcon(struct cifs_sb_info *cifs_sb) return cifs_sb->ptcon; } +/* This function is always expected to succeed */ +static inline struct cifsTconInfo * +cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) +{ + return cifs_sb->ptcon; +} + 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 b4bacea54626..f6a3091c2874 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3025,9 +3025,9 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) { int rc = 0; char *tmp; + struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); - if (cifs_sb_tcon(cifs_sb)) - cifs_put_tcon(cifs_sb_tcon(cifs_sb)); + cifs_put_tcon(tcon); cifs_sb->ptcon = NULL; tmp = cifs_sb->prepath; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f660a15eb14f..fe02435acb3c 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -54,18 +54,18 @@ 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); 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->Flags & SMB_SHARE_IS_IN_DFS) + dfsplen = strnlen(tcon->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(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++) { diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index ec4318b019cc..a2ad94efcfe6 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -62,15 +62,15 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) { struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); if (cifsi->fscache) return; - cifsi->fscache = fscache_acquire_cookie(cifs_sb_tcon(cifs_sb)->fscache, - &cifs_fscache_inode_object_def, - cifsi); - cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", - cifs_sb_tcon(cifs_sb)->fscache, cifsi->fscache); + cifsi->fscache = fscache_acquire_cookie(tcon->fscache, + &cifs_fscache_inode_object_def, cifsi); + cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, + cifsi->fscache); } void cifs_fscache_release_inode_cookie(struct inode *inode) @@ -118,7 +118,7 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode) fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = fscache_acquire_cookie( - cifs_sb_tcon(cifs_sb)->fscache, + cifs_sb_master_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index dce2d598927e..da716d96dae6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -52,7 +52,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 @@ -476,6 +476,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) @@ -490,8 +492,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); @@ -698,6 +700,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) { @@ -707,8 +710,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; @@ -717,7 +720,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 */ @@ -831,18 +834,18 @@ retry_iget5_locked: 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 inode *inode = NULL; long rc; char *full_path; + struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); - cifs_sb = CIFS_SB(sb); 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, @@ -853,10 +856,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) #ifdef CONFIG_CIFS_FSCACHE /* populate tcon->resource_id */ - cifs_sb_tcon(cifs_sb)->resource_id = CIFS_I(inode)->uniqueid; + tcon->resource_id = CIFS_I(inode)->uniqueid; #endif - 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; @@ -1661,7 +1664,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_tcon(CIFS_SB(sb))->unix_ext) + if (cifs_sb_master_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, @@ -2087,7 +2090,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(cifs_sb); + struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb); if (pTcon->unix_ext) return cifs_setattr_unix(direntry, attrs); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index c5cbfdb2a58b..252f2768db84 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -729,6 +729,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 3efc2424964f..887a7e230376 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -102,7 +102,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; @@ -171,7 +171,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, -- cgit v1.2.3-58-ga151 From 7ffec372458d163492e56e663a1b3a2d7be0a0a2 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 29 Sep 2010 19:51:11 -0400 Subject: cifs: add refcounted and timestamped container for holding tcons Eventually, we'll need to track the use of tcons on a per-sb basis, so that we know when it's ok to tear them down. Begin this conversion by adding a new "tcon_link" struct and accessors that get it. For now, the core data structures are untouched -- cifs_sb still just points to a single tcon and the pointers are just cast to deal with the accessor functions. A later patch will flesh this out. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 21 ++++--- fs/cifs/cifsacl.c | 42 ++++++++++--- fs/cifs/cifsglob.h | 51 ++++++++++++---- fs/cifs/dir.c | 65 ++++++++++++++------ fs/cifs/file.c | 9 ++- fs/cifs/inode.c | 157 ++++++++++++++++++++++++++++++++++++++----------- fs/cifs/link.c | 87 ++++++++++++++++++--------- fs/cifs/readdir.c | 32 +++++----- fs/cifs/xattr.c | 60 ++++++++++++------- 9 files changed, 376 insertions(+), 148 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f1e13ea45a17..f4aab6f01174 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -306,6 +306,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) int xid, i; int rc = 0; struct vfsmount *mnt = ERR_PTR(-ENOENT); + struct tcon_link *tlink; cFYI(1, "in %s", __func__); BUG_ON(IS_ROOT(dentry)); @@ -315,14 +316,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) dput(nd->path.dentry); 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; - goto out_err; - } - /* * The MSDFS spec states that paths in DFS referral requests and * responses must be prefixed by a single '\' character instead of @@ -335,10 +328,20 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) goto out_err; } - rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls, + cifs_sb = CIFS_SB(dentry->d_inode->i_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto out_err; + } + ses = tlink_tcon(tlink)->ses; + + rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, &num_referrals, &referrals, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_put_tlink(tlink); + for (i = 0; i < num_referrals; i++) { int len; dump_referral(referrals+i); diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 32f244909a0d..2647ea410c4c 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -557,11 +557,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, { struct cifs_ntsd *pntsd = NULL; int xid, rc; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + + if (IS_ERR(tlink)) + return NULL; xid = GetXid(); - rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen); + rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); FreeXid(xid); + cifs_put_tlink(tlink); cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); return pntsd; @@ -574,10 +579,16 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, int oplock = 0; int xid, rc; __u16 fid; + struct cifsTconInfo *tcon; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + + if (IS_ERR(tlink)) + return NULL; + tcon = tlink_tcon(tlink); 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) { @@ -585,11 +596,12 @@ 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: + cifs_put_tlink(tlink); FreeXid(xid); return pntsd; } @@ -616,10 +628,15 @@ 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 tcon_link *tlink = cifs_sb_tlink(cifs_sb); + + if (IS_ERR(tlink)) + return PTR_ERR(tlink); xid = GetXid(); - rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen); + rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen); FreeXid(xid); + cifs_put_tlink(tlink); cFYI(DBG2, "SetCIFSACL rc = %d", rc); return rc; @@ -631,10 +648,16 @@ 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; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + + tcon = tlink_tcon(tlink); 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) { @@ -642,12 +665,13 @@ 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); - out: + CIFSSMBClose(xid, tcon, fid); +out: FreeXid(xid); + cifs_put_tlink(tlink); return rc; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c265ebdcd177..cdfd2db4e70d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -310,6 +310,44 @@ struct cifsTconInfo { /* BB add field for back pointer to sb struct(s)? */ }; +/* + * This is a refcounted and timestamped container for a tcon pointer. The + * container holds a tcon reference. It is considered safe to free one of + * these when the tl_count goes to 0. The tl_time is the time of the last + * "get" on the container. + */ +struct tcon_link { + spinlock_t tl_lock; + u32 tl_count; + u64 tl_time; + struct cifsTconInfo *tl_tcon; +}; + +static inline struct tcon_link * +cifs_sb_tlink(struct cifs_sb_info *cifs_sb) +{ + return (struct tcon_link *)cifs_sb->ptcon; +} + +static inline struct cifsTconInfo * +tlink_tcon(struct tcon_link *tlink) +{ + return (struct cifsTconInfo *)tlink; +} + +static inline void +cifs_put_tlink(struct tcon_link *tlink) +{ + return; +} + +/* This function is always expected to succeed */ +static inline struct cifsTconInfo * +cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) +{ + return cifs_sb->ptcon; +} + /* * This info hangs off the cifsFileInfo structure, pointed to by llist. * This is used to track byte stream locks on the file @@ -413,19 +451,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->ptcon; -} - -/* This function is always expected to succeed */ -static inline struct cifsTconInfo * -cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) -{ - return cifs_sb->ptcon; -} - 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/dir.c b/fs/cifs/dir.c index 23ec28a4c11f..bb3ea06ca6f4 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -137,7 +137,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, { 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) @@ -191,7 +190,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, __u32 posix_flags = 0; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_fattr fattr; - struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); + struct tcon_link *tlink; + struct cifsTconInfo *tcon; cFYI(1, "posix open %s", full_path); @@ -226,10 +226,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode, posix_flags |= SMB_O_DIRECT; mode &= ~current_umask(); + + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto posix_open_ret; + } + + tcon = tlink_tcon(tlink); 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); + cifs_put_tlink(tlink); + if (rc) goto posix_open_ret; @@ -290,6 +300,7 @@ 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 tcon_link *tlink; struct cifsTconInfo *tcon; char *full_path = NULL; FILE_ALL_INFO *buf = NULL; @@ -299,13 +310,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb_tcon(cifs_sb); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto cifs_create_out; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + FreeXid(xid); + return PTR_ERR(tlink); } + tcon = tlink_tcon(tlink); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -315,6 +325,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else oflags = FMODE_READ | SMB_O_CREAT; + full_path = build_path_from_dentry(direntry); + if (full_path == NULL) { + rc = -ENOMEM; + goto cifs_create_out; + } + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { @@ -481,6 +497,7 @@ cifs_create_set_dentry: cifs_create_out: kfree(buf); kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return rc; } @@ -491,6 +508,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int rc = -EPERM; int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; @@ -503,10 +521,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, if (!old_valid_dev(device_number)) return -EINVAL; - xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { @@ -606,6 +628,7 @@ mknod_out: kfree(full_path); kfree(buf); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -619,6 +642,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, __u16 fileHandle = 0; bool posix_open = false; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct cifsFileInfo *cfile; struct inode *newInode = NULL; @@ -633,7 +657,12 @@ 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(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + FreeXid(xid); + return (struct dentry *)tlink; + } + pTcon = tlink_tcon(tlink); /* * Don't allow the separator character in a path component. @@ -644,8 +673,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, for (i = 0; i < direntry->d_name.len; i++) if (direntry->d_name.name[i] == '\\') { cFYI(1, "Invalid file name"); - FreeXid(xid); - return ERR_PTR(-EINVAL); + rc = -EINVAL; + goto lookup_out; } } @@ -655,7 +684,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, */ if (nd && (nd->flags & LOOKUP_EXCL)) { d_instantiate(direntry, NULL); - return NULL; + rc = 0; + goto lookup_out; } /* can not grab the rename sem here since it would @@ -663,8 +693,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, in which we already have the sb rename sem */ full_path = build_path_from_dentry(direntry); if (full_path == NULL) { - FreeXid(xid); - return ERR_PTR(-ENOMEM); + rc = -ENOMEM; + goto lookup_out; } if (direntry->d_inode != NULL) { @@ -760,6 +790,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, lookup_out: kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return ERR_PTR(rc); } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index de046e183d12..1e375abc5eb3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -224,6 +224,7 @@ int cifs_open(struct inode *inode, struct file *file) __u32 oplock; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; + struct tcon_link *tlink; struct cifsFileInfo *pCifsFile = NULL; struct cifsInodeInfo *pCifsInode; char *full_path = NULL; @@ -235,7 +236,12 @@ int cifs_open(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + FreeXid(xid); + return PTR_ERR(tlink); + } + tcon = tlink_tcon(tlink); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); @@ -402,6 +408,7 @@ out: kfree(buf); kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index da716d96dae6..aa229692aef1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -313,16 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode, FILE_UNIX_BASIC_INFO find_data; struct cifs_fattr fattr; struct cifsTconInfo *tcon; + struct tcon_link *tlink; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - tcon = cifs_sb_tcon(cifs_sb); - cFYI(1, "Getting info on %s", full_path); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + /* 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 & CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_put_tlink(tlink); if (!rc) { cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); @@ -361,7 +366,8 @@ 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 tcon_link *tlink; + struct cifsTconInfo *tcon; char buf[24]; unsigned int bytes_read; char *pbuf; @@ -380,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, return -EINVAL; /* EOPNOTSUPP? */ } - rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + + rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -388,7 +399,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)) { @@ -430,8 +441,9 @@ 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); } + cifs_put_tlink(tlink); return rc; } @@ -449,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, ssize_t rc; char ea_value[4]; __u32 mode; + struct tcon_link *tlink; + struct cifsTconInfo *tcon; - rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS", + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + + 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); + cifs_put_tlink(tlink); if (rc < 0) return (int)rc; else if (rc > 3) { @@ -564,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode, { int rc = 0, tmprc; struct cifsTconInfo *pTcon; + struct tcon_link *tlink; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *buf = NULL; bool adjustTZ = false; struct cifs_fattr fattr; - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + cFYI(1, "Getting info on %s", full_path); if ((pfindData == NULL) && (*pinode != NULL)) { if (CIFS_I(*pinode)->clientCanCacheRead) { cFYI(1, "No need to revalidate cached inode sizes"); - return rc; + goto cgii_exit; } } /* if file info not passed in then get it from server */ if (pfindData == NULL) { buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; + if (buf == NULL) { + rc = -ENOMEM; + goto cgii_exit; + } pfindData = (FILE_ALL_INFO *)buf; /* could do find first instead but this returns more info */ @@ -688,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode, cgii_exit: kfree(buf); + cifs_put_tlink(tlink); return rc; } @@ -895,6 +923,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 tcon_link *tlink = NULL; struct cifsTconInfo *pTcon; FILE_BASIC_INFO info_buf; @@ -942,7 +971,13 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, goto set_via_filehandle; } - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + tlink = NULL; + goto out; + } + pTcon = tlink_tcon(tlink); /* * NT4 apparently returns success on this call, but it doesn't @@ -987,6 +1022,8 @@ set_via_filehandle: else cifsFileInfo_put(open_file); out: + if (tlink != NULL) + cifs_put_tlink(tlink); return rc; } @@ -1004,10 +1041,16 @@ 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(cifs_sb); + struct tcon_link *tlink; + struct cifsTconInfo *tcon; __u32 dosattr, origattr; FILE_BASIC_INFO *info_buf = NULL; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, @@ -1076,6 +1119,7 @@ out_close: CIFSSMBClose(xid, tcon, netfid); out: kfree(info_buf); + cifs_put_tlink(tlink); return rc; /* @@ -1115,12 +1159,18 @@ 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(cifs_sb); + struct tcon_link *tlink; + struct cifsTconInfo *tcon; struct iattr *attrs = NULL; __u32 dosattr = 0, origattr = 0; cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + xid = GetXid(); /* Unlink can be called from rename so we can not take the @@ -1128,8 +1178,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) full_path = build_path_from_dentry(dentry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto unlink_out; } if ((tcon->ses->capabilities & CAP_UNIX) && @@ -1195,10 +1244,11 @@ out_reval: dir->i_ctime = dir->i_mtime = current_fs_time(sb); cifs_inode = CIFS_I(dir); CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ - +unlink_out: kfree(full_path); kfree(attrs); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -1207,6 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) int rc = 0, tmprc; int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; @@ -1214,16 +1265,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); - xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto mkdir_out; } if ((pTcon->ses->capabilities & CAP_UNIX) && @@ -1381,6 +1434,7 @@ mkdir_get_info: mkdir_out: kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -1389,6 +1443,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) int rc = 0; int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; char *full_path = NULL; struct cifsInodeInfo *cifsInode; @@ -1397,18 +1452,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb_tcon(cifs_sb); - full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto rmdir_exit; + } + + cifs_sb = CIFS_SB(inode->i_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto rmdir_exit; } + pTcon = tlink_tcon(tlink); rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_put_tlink(tlink); if (!rc) { drop_nlink(inode); @@ -1429,6 +1489,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); +rmdir_exit: kfree(full_path); FreeXid(xid); return rc; @@ -1439,10 +1500,16 @@ 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(cifs_sb); + struct tcon_link *tlink; + struct cifsTconInfo *pTcon; __u16 srcfid; int oplock, rc; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + /* try path-based rename first */ rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -1454,11 +1521,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, * rename by filehandle to various Windows servers. */ if (rc == 0 || rc != -ETXTBSY) - return rc; + goto do_rename_exit; /* open-file renames don't work across directories */ if (to_dentry->d_parent != from_dentry->d_parent) - return rc; + goto do_rename_exit; /* open the file to be renamed -- we need DELETE perms */ rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, @@ -1474,7 +1541,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, CIFSSMBClose(xid, pTcon, srcfid); } - +do_rename_exit: + cifs_put_tlink(tlink); return rc; } @@ -1484,13 +1552,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, char *fromName = NULL; char *toName = NULL; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *tcon; FILE_UNIX_BASIC_INFO *info_buf_source = NULL; FILE_UNIX_BASIC_INFO *info_buf_target; int xid, rc, tmprc; cifs_sb = CIFS_SB(source_dir->i_sb); - tcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); xid = GetXid(); @@ -1566,6 +1638,7 @@ cifs_rename_exit: kfree(fromName); kfree(toName); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -1728,6 +1801,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 tcon_link *tlink = NULL; struct cifsTconInfo *pTcon = NULL; /* @@ -1758,8 +1832,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, rc = -EINVAL; if (rc != 0) { - if (pTcon == NULL) - pTcon = cifs_sb_tcon(cifs_sb); + if (pTcon == NULL) { + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + } /* Set file size by pathname rather than by handle either because no valid, writeable file handle for @@ -1790,6 +1868,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, CIFSSMBClose(xid, pTcon, netfid); } } + if (tlink) + cifs_put_tlink(tlink); } if (rc == 0) { @@ -1810,6 +1890,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 tcon_link *tlink; struct cifsTconInfo *pTcon; struct cifs_unix_set_info_args *args = NULL; struct cifsFileInfo *open_file; @@ -1905,11 +1986,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); cifsFileInfo_put(open_file); } else { - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto out; + } + pTcon = tlink_tcon(tlink); rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_put_tlink(tlink); } if (rc) diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 66db2d61fa43..b38fe6704ad2 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -249,7 +249,8 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, int rc; int oplock = 0; __u16 netfid = 0; - struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); + struct tcon_link *tlink; + struct cifsTconInfo *pTcon; u8 *buf; char *pbuf; unsigned int bytes_read = 0; @@ -261,23 +262,30 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, /* it's not a symlink */ return 0; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, CREATE_NOT_DIR, &netfid, &oplock, &file_info, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc != 0) - return rc; + goto out; if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) { CIFSSMBClose(xid, pTcon, netfid); /* it's not a symlink */ - return 0; + goto out; } buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; + if (!buf) { + rc = -ENOMEM; + goto out; + } pbuf = buf; rc = CIFSSMBRead(xid, pTcon, netfid, @@ -287,23 +295,28 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, CIFSSMBClose(xid, pTcon, netfid); if (rc != 0) { kfree(buf); - return rc; + goto out; } rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); kfree(buf); - if (rc == -EINVAL) + if (rc == -EINVAL) { /* it's not a symlink */ - return 0; + rc = 0; + goto out; + } + if (rc != 0) - return rc; + goto out; /* it is a symlink */ fattr->cf_eof = link_len; fattr->cf_mode &= ~S_IFMT; fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; fattr->cf_dtype = DT_LNK; - return 0; +out: + cifs_put_tlink(tlink); + return rc; } int @@ -314,17 +327,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, int xid; char *fromName = NULL; char *toName = NULL; - struct cifs_sb_info *cifs_sb_target; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct cifsInodeInfo *cifsInode; - xid = GetXid(); - - cifs_sb_target = CIFS_SB(inode->i_sb); - pTcon = cifs_sb_tcon(cifs_sb_target); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); -/* 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) */ + xid = GetXid(); fromName = build_path_from_dentry(old_file); toName = build_path_from_dentry(direntry); @@ -336,13 +349,13 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, /* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/ if (pTcon->unix_ext) rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb_target->local_nls, - cifs_sb_target->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); else { rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb_target->local_nls, - cifs_sb_target->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if ((rc == -EIO) || (rc == -EINVAL)) rc = -EOPNOTSUPP; @@ -378,6 +391,7 @@ cifs_hl_exit: kfree(fromName); kfree(toName); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -390,10 +404,19 @@ 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(cifs_sb); + struct tcon_link *tlink = NULL; + struct cifsTconInfo *tcon; xid = GetXid(); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + tlink = NULL; + goto out; + } + tcon = tlink_tcon(tlink); + /* * For now, we just handle symlinks with unix extensions enabled. * Eventually we should handle NTFS reparse points, and MacOS @@ -442,6 +465,8 @@ out: } FreeXid(xid); + if (tlink) + cifs_put_tlink(tlink); nd_set_link(nd, target_path); return NULL; } @@ -451,22 +476,25 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) { int rc = -EOPNOTSUPP; int xid; - struct cifs_sb_info *cifs_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto symlink_exit; + } + pTcon = tlink_tcon(tlink); full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto symlink_exit; } cFYI(1, "Full path: %s", full_path); @@ -504,8 +532,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) d_instantiate(direntry, newinode); } } - +symlink_exit: kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return rc; } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 887a7e230376..170047cf4522 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -223,33 +223,35 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, static int initiate_cifs_search(const int xid, struct file *file) { int rc = 0; - char *full_path; + char *full_path = NULL; struct cifsFileInfo *cifsFile; - struct cifs_sb_info *cifs_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + struct tcon_link *tlink; struct cifsTconInfo *pTcon; - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - if (cifs_sb == NULL) - return -EINVAL; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); if (file->private_data == NULL) file->private_data = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); + if (file->private_data == NULL) { + rc = -ENOMEM; + goto error_exit; + } - 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); - pTcon = cifsFile->tcon; - if (pTcon == NULL) - return -EINVAL; + cifsFile->tcon = pTcon; full_path = build_path_from_dentry(file->f_path.dentry); - - if (full_path == NULL) - return -ENOMEM; + if (full_path == NULL) { + rc = -ENOMEM; + goto error_exit; + } cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); @@ -282,7 +284,9 @@ ffirst_retry: cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; goto ffirst_retry; } +error_exit: kfree(full_path); + cifs_put_tlink(tlink); return rc; } diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 41f95bf67977..a264b744bb41 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -47,9 +47,10 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) #ifdef CONFIG_CIFS_XATTR int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct super_block *sb; - char *full_path; + char *full_path = NULL; if (direntry == NULL) return -EIO; @@ -58,16 +59,19 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) sb = direntry->d_inode->i_sb; if (sb == NULL) return -EIO; - xid = GetXid(); cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto remove_ea_exit; } if (ea_name == NULL) { cFYI(1, "Null xattr names not supported"); @@ -91,6 +95,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) remove_ea_exit: kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); #endif return rc; } @@ -102,6 +107,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, #ifdef CONFIG_CIFS_XATTR int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct super_block *sb; char *full_path; @@ -113,16 +119,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, sb = direntry->d_inode->i_sb; if (sb == NULL) return -EIO; - xid = GetXid(); cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto set_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -132,9 +141,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, returns as xattrs */ if (value_size > MAX_EA_VALUE_SIZE) { cFYI(1, "size of EA value too large"); - kfree(full_path); - FreeXid(xid); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto set_ea_exit; } if (ea_name == NULL) { @@ -198,6 +206,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, set_ea_exit: kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); #endif return rc; } @@ -209,6 +218,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, #ifdef CONFIG_CIFS_XATTR int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct super_block *sb; char *full_path; @@ -221,16 +231,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, if (sb == NULL) return -EIO; - xid = GetXid(); - cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb_tcon(cifs_sb); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto get_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -323,6 +335,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, get_ea_exit: kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); #endif return rc; } @@ -333,6 +346,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) #ifdef CONFIG_CIFS_XATTR int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct super_block *sb; char *full_path; @@ -346,18 +360,20 @@ 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; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { rc = -ENOMEM; - FreeXid(xid); - return rc; + goto list_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -370,8 +386,10 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); +list_ea_exit: kfree(full_path); FreeXid(xid); + cifs_put_tlink(tlink); #endif return rc; } -- cgit v1.2.3-58-ga151 From 13cfb7334eb6fd0fc06da5589aea1e947791f1d6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 29 Sep 2010 19:51:11 -0400 Subject: cifs: have cifsFileInfo hold a reference to a tlink rather than tcon pointer cifsFileInfo needs a pointer to a tcon, but it doesn't currently hold a reference to it. Change it to keep a pointer to a tcon_link instead and hold a reference to it. That will keep the tcon from being freed until the file is closed. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 3 ++- fs/cifs/cifsglob.h | 9 ++++++++- fs/cifs/cifsproto.h | 2 +- fs/cifs/dir.c | 10 +++++----- fs/cifs/file.c | 31 ++++++++++++++++--------------- fs/cifs/inode.c | 12 ++++++------ fs/cifs/ioctl.c | 2 +- fs/cifs/link.c | 1 - fs/cifs/readdir.c | 4 ++-- 9 files changed, 41 insertions(+), 33 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 898d2a5cfad2..b2fd075dc2e6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -595,7 +595,8 @@ 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 (cfile->tcon->local_lease && !CIFS_I(inode)->clientCanCacheRead) + else if (tlink_tcon(cfile->tlink)->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/cifsglob.h b/fs/cifs/cifsglob.h index cdfd2db4e70d..d5324853203b 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -341,6 +341,12 @@ cifs_put_tlink(struct tcon_link *tlink) return; } +static inline struct tcon_link * +cifs_get_tlink(struct tcon_link *tlink) +{ + return tlink; +} + /* This function is always expected to succeed */ static inline struct cifsTconInfo * cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) @@ -389,7 +395,7 @@ struct cifsFileInfo { struct file *pfile; /* needed for writepage */ struct inode *pInode; /* needed for oplock break */ struct vfsmount *mnt; - struct cifsTconInfo *tcon; + struct tcon_link *tlink; struct mutex lock_mutex; struct list_head llist; /* list of byte range locks we have. */ bool closePend:1; /* file is marked to close */ @@ -411,6 +417,7 @@ static inline void cifsFileInfo_get(struct cifsFileInfo *cifs_file) static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file) { if (atomic_dec_and_test(&cifs_file->count)) { + cifs_put_tlink(cifs_file->tlink); iput(cifs_file->pInode); kfree(cifs_file); } diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 610b2263c9f3..7294723d0625 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -107,7 +107,7 @@ 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, struct cifsTconInfo *tcon, + struct vfsmount *mnt, struct tcon_link *tlink, unsigned int oflags, __u32 oplock); extern int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index bb3ea06ca6f4..5adf47f28fed 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -132,7 +132,7 @@ cifs_bp_rename_retry: struct cifsFileInfo * cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, - struct vfsmount *mnt, struct cifsTconInfo *tcon, + struct vfsmount *mnt, struct tcon_link *tlink, unsigned int oflags, __u32 oplock) { struct cifsFileInfo *pCifsFile; @@ -149,7 +149,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, pCifsFile->pfile = file; pCifsFile->invalidHandle = false; pCifsFile->closePend = false; - pCifsFile->tcon = tcon; + pCifsFile->tlink = cifs_get_tlink(tlink); mutex_init(&pCifsFile->fh_mutex); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); @@ -157,7 +157,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist, &tcon->openFileList); + list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); pCifsInode = CIFS_I(newinode); if (pCifsInode) { /* if readable file instance put first in list*/ @@ -483,7 +483,7 @@ cifs_create_set_dentry: } pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, - nd->path.mnt, tcon, oflags, + nd->path.mnt, tlink, oflags, oplock); if (pfile_info == NULL) { fput(filp); @@ -758,7 +758,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } cfile = cifs_new_fileinfo(newInode, fileHandle, filp, - nd->path.mnt, pTcon, + nd->path.mnt, tlink, nd->intent.open.flags, oplock); if (cfile == NULL) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1e375abc5eb3..24332d437150 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -283,7 +283,7 @@ int cifs_open(struct inode *inode, struct file *file) pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, - tcon, oflags, oplock); + tlink, oflags, oplock); if (pCifsFile == NULL) { CIFSSMBClose(xid, tcon, netfid); rc = -ENOMEM; @@ -376,7 +376,7 @@ int cifs_open(struct inode *inode, struct file *file) goto out; pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, - tcon, file->f_flags, oplock); + tlink, file->f_flags, oplock); if (pCifsFile == NULL) { rc = -ENOMEM; goto out; @@ -468,7 +468,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) } cifs_sb = CIFS_SB(inode->i_sb); - tcon = pCifsFile->tcon; + tcon = tlink_tcon(pCifsFile->tlink); /* can not grab rename sem here because various ops, including those that already have the rename sem can end up causing writepage @@ -582,7 +582,7 @@ int cifs_close(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - pTcon = pSMBFile->tcon; + pTcon = tlink_tcon(pSMBFile->tlink); if (pSMBFile) { struct cifsLockInfo *li, *tmp; write_lock(&GlobalSMBSeslock); @@ -660,7 +660,7 @@ int cifs_closedir(struct inode *inode, struct file *file) xid = GetXid(); if (pCFileStruct) { - struct cifsTconInfo *pTcon = pCFileStruct->tcon; + struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink); cFYI(1, "Freeing private data in close dir"); write_lock(&GlobalSMBSeslock); @@ -684,6 +684,7 @@ int cifs_closedir(struct inode *inode, struct file *file) else cifs_buf_release(ptmp); } + cifs_put_tlink(pCFileStruct->tlink); kfree(file->private_data); file->private_data = NULL; } @@ -770,7 +771,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 = ((struct cifsFileInfo *)file->private_data)->tcon; + tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink); if (file->private_data == NULL) { rc = -EBADF; @@ -970,7 +971,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, return -EBADF; open_file = file->private_data; - pTcon = open_file->tcon; + pTcon = tlink_tcon(open_file->tlink); rc = generic_write_checks(file, poffset, &write_size, 0); if (rc) @@ -1071,7 +1072,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, if (file->private_data == NULL) return -EBADF; open_file = file->private_data; - pTcon = open_file->tcon; + pTcon = tlink_tcon(open_file->tlink); xid = GetXid(); @@ -1393,7 +1394,7 @@ static int cifs_writepages(struct address_space *mapping, return generic_writepages(mapping, wbc); } - tcon = open_file->tcon; + tcon = tlink_tcon(open_file->tlink); if (!experimEnabled && tcon->ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { cifsFileInfo_put(open_file); @@ -1672,7 +1673,7 @@ int cifs_fsync(struct file *file, int datasync) if (rc == 0) { rc = CIFS_I(inode)->write_behind_rc; CIFS_I(inode)->write_behind_rc = 0; - tcon = smbfile->tcon; + tcon = tlink_tcon(smbfile->tlink); if (!rc && tcon && smbfile && !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); @@ -1764,7 +1765,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, return rc; } open_file = file->private_data; - pTcon = open_file->tcon; + pTcon = tlink_tcon(open_file->tlink); if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1845,7 +1846,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, return rc; } open_file = file->private_data; - pTcon = open_file->tcon; + pTcon = tlink_tcon(open_file->tlink); if ((file->f_flags & O_ACCMODE) == O_WRONLY) cFYI(1, "attempting read on write only file instance"); @@ -1981,7 +1982,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } open_file = file->private_data; cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - pTcon = open_file->tcon; + pTcon = tlink_tcon(open_file->tlink); /* * Reads as many pages as possible from fscache. Returns -ENOBUFS @@ -2345,8 +2346,8 @@ void cifs_oplock_break(struct work_struct *work) * disconnected since oplock already released by the server */ if (!cfile->closePend && !cfile->oplock_break_cancelled) { - rc = CIFSSMBLock(0, cfile->tcon, cfile->netfid, 0, 0, 0, 0, - LOCKING_ANDX_OPLOCK_RELEASE, false); + rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), 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 aa229692aef1..a39a1c451733 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -289,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp) struct inode *inode = filp->f_path.dentry->d_inode; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsFileInfo *cfile = filp->private_data; - struct cifsTconInfo *tcon = cfile->tcon; + struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); xid = GetXid(); rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); @@ -546,7 +546,7 @@ int cifs_get_file_info(struct file *filp) struct inode *inode = filp->f_path.dentry->d_inode; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsFileInfo *cfile = filp->private_data; - struct cifsTconInfo *tcon = cfile->tcon; + struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink); xid = GetXid(); rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); @@ -967,7 +967,7 @@ 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; + pTcon = tlink_tcon(open_file->tlink); goto set_via_filehandle; } @@ -1696,7 +1696,7 @@ int cifs_revalidate_file(struct file *filp) if (!cifs_inode_needs_reval(inode)) goto check_inval; - if (cfile->tcon->unix_ext) + if (tlink_tcon(cfile->tlink)->unix_ext) rc = cifs_get_file_info_unix(filp); else rc = cifs_get_file_info(filp); @@ -1817,7 +1817,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; + pTcon = tlink_tcon(open_file->tlink); rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, npid, false); cifsFileInfo_put(open_file); @@ -1982,7 +1982,7 @@ 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; + pTcon = tlink_tcon(open_file->tlink); rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); cifsFileInfo_put(open_file); } else { diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index cc70a61a47d2..077bf756f342 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -38,7 +38,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) struct cifs_sb_info *cifs_sb; #ifdef CONFIG_CIFS_POSIX struct cifsFileInfo *pSMBFile = filep->private_data; - struct cifsTconInfo *tcon = pSMBFile->tcon; + struct cifsTconInfo *tcon = tlink_tcon(pSMBFile->tlink); __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; __u64 caps = le64_to_cpu(tcon->fsUnixInfo.Capability); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index b38fe6704ad2..85cdbf831e7b 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -346,7 +346,6 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, goto cifs_hl_exit; } -/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/ if (pTcon->unix_ext) rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, cifs_sb->local_nls, diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 170047cf4522..1f0bd0f972d4 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -245,7 +245,7 @@ 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 = pTcon; + cifsFile->tlink = cifs_get_tlink(tlink); full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { @@ -838,7 +838,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) CIFSFindClose(xid, pTcon, cifsFile->netfid); } */ - pTcon = cifsFile->tcon; + pTcon = tlink_tcon(cifsFile->tlink); rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); if (rc) { -- cgit v1.2.3-58-ga151 From 6508d904e6fb66ce4c34617f72b38d6714c4b9f6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 29 Sep 2010 19:51:11 -0400 Subject: cifs: have find_readable/writable_file filter by fsuid When we implement multiuser mounts, we'll need to filter filehandles by fsuid. Add a flag for multiuser mounts and code to filter by fsuid when it's set. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- 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 | 33 +++++++++++++++++++++++++-------- fs/cifs/inode.c | 6 +++--- 6 files changed, 35 insertions(+), 16 deletions(-) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ba0afd3acff4..e04e6923d354 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -37,6 +37,7 @@ #define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ +#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ struct cifs_sb_info { struct cifsTconInfo *ptcon; /* primary mount */ @@ -48,7 +49,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 2647ea410c4c..c9b4792ae825 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -615,7 +615,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); @@ -685,7 +685,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 7294723d0625..29a2ee8ae51f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -78,9 +78,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 5adf47f28fed..e249b561ce8f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -144,6 +144,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, 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 24332d437150..80856f180711 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1168,9 +1168,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 multiuser mounts */ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) + fsuid_only = false; read_lock(&GlobalSMBSeslock); /* we could simply get the first_list_entry since write-only entries @@ -1179,6 +1185,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) { @@ -1198,9 +1206,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; @@ -1214,13 +1224,19 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) return NULL; } + /* only filter by fsuid on multiuser mounts */ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) + 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))) { @@ -1315,7 +1331,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); @@ -1388,7 +1404,7 @@ static int cifs_writepages(struct address_space *mapping, * but it'll at least handle the return. Maybe it should be * a BUG() instead? */ - open_file = find_writable_file(CIFS_I(mapping->host)); + open_file = find_writable_file(CIFS_I(mapping->host), false); if (!open_file) { kfree(iov); return generic_writepages(mapping, wbc); @@ -1505,7 +1521,8 @@ retry: break; } if (n_iov) { - 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 a39a1c451733..df29a3a3d80c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -963,7 +963,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; @@ -1813,7 +1813,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; @@ -1978,7 +1978,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; -- cgit v1.2.3-58-ga151 From 3aa1c8c2900065a51268430ab48a1b42fdfe5b45 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 7 Oct 2010 14:46:28 -0400 Subject: cifs: on multiuser mount, set ownership to current_fsuid/current_fsgid (try #5) ...when unix extensions aren't enabled. This makes everything on the mount appear to be owned by the current user. This version of the patch differs from previous versions however in that the admin can still force the ownership of all files to appear as a single user via the uid=/gid= options. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'fs/cifs/inode.c') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index df29a3a3d80c..7e5b8c39a07a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1755,11 +1755,21 @@ 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_master_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_MULTIUSER) && + !tcon->unix_ext) { + if (!cifs_sb->mnt_uid) + stat->uid = current_fsuid(); + if (!cifs_sb->mnt_uid) + stat->gid = current_fsgid(); + } } return err; } -- cgit v1.2.3-58-ga151