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 <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Jeff Layton 2010-09-29 19:51:11 -04:00 committed by Steve French
parent 7ffec37245
commit 13cfb7334e
9 changed files with 41 additions and 33 deletions

View File

@ -595,7 +595,8 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
((arg == F_WRLCK) && ((arg == F_WRLCK) &&
(CIFS_I(inode)->clientCanCacheAll))) (CIFS_I(inode)->clientCanCacheAll)))
return generic_setlease(file, arg, lease); 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 /* If the server claims to support oplock on this
file, then we still need to check oplock even file, then we still need to check oplock even
if the local_lease mount option is set, but there if the local_lease mount option is set, but there

View File

@ -341,6 +341,12 @@ cifs_put_tlink(struct tcon_link *tlink)
return; return;
} }
static inline struct tcon_link *
cifs_get_tlink(struct tcon_link *tlink)
{
return tlink;
}
/* This function is always expected to succeed */ /* This function is always expected to succeed */
static inline struct cifsTconInfo * static inline struct cifsTconInfo *
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
@ -389,7 +395,7 @@ struct cifsFileInfo {
struct file *pfile; /* needed for writepage */ struct file *pfile; /* needed for writepage */
struct inode *pInode; /* needed for oplock break */ struct inode *pInode; /* needed for oplock break */
struct vfsmount *mnt; struct vfsmount *mnt;
struct cifsTconInfo *tcon; struct tcon_link *tlink;
struct mutex lock_mutex; struct mutex lock_mutex;
struct list_head llist; /* list of byte range locks we have. */ struct list_head llist; /* list of byte range locks we have. */
bool closePend:1; /* file is marked to close */ 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) static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
{ {
if (atomic_dec_and_test(&cifs_file->count)) { if (atomic_dec_and_test(&cifs_file->count)) {
cifs_put_tlink(cifs_file->tlink);
iput(cifs_file->pInode); iput(cifs_file->pInode);
kfree(cifs_file); kfree(cifs_file);
} }

View File

@ -107,7 +107,7 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
__u16 fileHandle, struct file *file, __u16 fileHandle, struct file *file,
struct vfsmount *mnt, struct cifsTconInfo *tcon, struct vfsmount *mnt, struct tcon_link *tlink,
unsigned int oflags, __u32 oplock); unsigned int oflags, __u32 oplock);
extern int cifs_posix_open(char *full_path, struct inode **pinode, extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct super_block *sb, struct super_block *sb,

View File

@ -132,7 +132,7 @@ cifs_bp_rename_retry:
struct cifsFileInfo * struct cifsFileInfo *
cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, 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) unsigned int oflags, __u32 oplock)
{ {
struct cifsFileInfo *pCifsFile; struct cifsFileInfo *pCifsFile;
@ -149,7 +149,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
pCifsFile->pfile = file; pCifsFile->pfile = file;
pCifsFile->invalidHandle = false; pCifsFile->invalidHandle = false;
pCifsFile->closePend = false; pCifsFile->closePend = false;
pCifsFile->tcon = tcon; pCifsFile->tlink = cifs_get_tlink(tlink);
mutex_init(&pCifsFile->fh_mutex); mutex_init(&pCifsFile->fh_mutex);
mutex_init(&pCifsFile->lock_mutex); mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist); 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); INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist, &tcon->openFileList); list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if (pCifsInode) { if (pCifsInode) {
/* if readable file instance put first in list*/ /* if readable file instance put first in list*/
@ -483,7 +483,7 @@ cifs_create_set_dentry:
} }
pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
nd->path.mnt, tcon, oflags, nd->path.mnt, tlink, oflags,
oplock); oplock);
if (pfile_info == NULL) { if (pfile_info == NULL) {
fput(filp); fput(filp);
@ -758,7 +758,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
} }
cfile = cifs_new_fileinfo(newInode, fileHandle, filp, cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
nd->path.mnt, pTcon, nd->path.mnt, tlink,
nd->intent.open.flags, nd->intent.open.flags,
oplock); oplock);
if (cfile == NULL) { if (cfile == NULL) {

View File

@ -283,7 +283,7 @@ int cifs_open(struct inode *inode, struct file *file)
pCifsFile = cifs_new_fileinfo(inode, netfid, file, pCifsFile = cifs_new_fileinfo(inode, netfid, file,
file->f_path.mnt, file->f_path.mnt,
tcon, oflags, oplock); tlink, oflags, oplock);
if (pCifsFile == NULL) { if (pCifsFile == NULL) {
CIFSSMBClose(xid, tcon, netfid); CIFSSMBClose(xid, tcon, netfid);
rc = -ENOMEM; rc = -ENOMEM;
@ -376,7 +376,7 @@ int cifs_open(struct inode *inode, struct file *file)
goto out; goto out;
pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
tcon, file->f_flags, oplock); tlink, file->f_flags, oplock);
if (pCifsFile == NULL) { if (pCifsFile == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
@ -468,7 +468,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
} }
cifs_sb = CIFS_SB(inode->i_sb); 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 /* can not grab rename sem here because various ops, including
those that already have the rename sem can end up causing writepage 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(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = pSMBFile->tcon; pTcon = tlink_tcon(pSMBFile->tlink);
if (pSMBFile) { if (pSMBFile) {
struct cifsLockInfo *li, *tmp; struct cifsLockInfo *li, *tmp;
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
@ -660,7 +660,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
xid = GetXid(); xid = GetXid();
if (pCFileStruct) { if (pCFileStruct) {
struct cifsTconInfo *pTcon = pCFileStruct->tcon; struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink);
cFYI(1, "Freeing private data in close dir"); cFYI(1, "Freeing private data in close dir");
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
@ -684,6 +684,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
else else
cifs_buf_release(ptmp); cifs_buf_release(ptmp);
} }
cifs_put_tlink(pCFileStruct->tlink);
kfree(file->private_data); kfree(file->private_data);
file->private_data = NULL; 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"); cFYI(1, "Unknown type of lock");
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 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) { if (file->private_data == NULL) {
rc = -EBADF; rc = -EBADF;
@ -970,7 +971,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
return -EBADF; return -EBADF;
open_file = file->private_data; open_file = file->private_data;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
rc = generic_write_checks(file, poffset, &write_size, 0); rc = generic_write_checks(file, poffset, &write_size, 0);
if (rc) if (rc)
@ -1071,7 +1072,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (file->private_data == NULL) if (file->private_data == NULL)
return -EBADF; return -EBADF;
open_file = file->private_data; open_file = file->private_data;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
xid = GetXid(); xid = GetXid();
@ -1393,7 +1394,7 @@ static int cifs_writepages(struct address_space *mapping,
return generic_writepages(mapping, wbc); return generic_writepages(mapping, wbc);
} }
tcon = open_file->tcon; tcon = tlink_tcon(open_file->tlink);
if (!experimEnabled && tcon->ses->server->secMode & if (!experimEnabled && tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
cifsFileInfo_put(open_file); cifsFileInfo_put(open_file);
@ -1672,7 +1673,7 @@ int cifs_fsync(struct file *file, int datasync)
if (rc == 0) { if (rc == 0) {
rc = CIFS_I(inode)->write_behind_rc; rc = CIFS_I(inode)->write_behind_rc;
CIFS_I(inode)->write_behind_rc = 0; CIFS_I(inode)->write_behind_rc = 0;
tcon = smbfile->tcon; tcon = tlink_tcon(smbfile->tlink);
if (!rc && tcon && smbfile && if (!rc && tcon && smbfile &&
!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
@ -1764,7 +1765,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
return rc; return rc;
} }
open_file = file->private_data; open_file = file->private_data;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
if ((file->f_flags & O_ACCMODE) == O_WRONLY) if ((file->f_flags & O_ACCMODE) == O_WRONLY)
cFYI(1, "attempting read on write only file instance"); 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; return rc;
} }
open_file = file->private_data; open_file = file->private_data;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
if ((file->f_flags & O_ACCMODE) == O_WRONLY) if ((file->f_flags & O_ACCMODE) == O_WRONLY)
cFYI(1, "attempting read on write only file instance"); 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; open_file = file->private_data;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 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 * 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 * disconnected since oplock already released by the server
*/ */
if (!cfile->closePend && !cfile->oplock_break_cancelled) { if (!cfile->closePend && !cfile->oplock_break_cancelled) {
rc = CIFSSMBLock(0, cfile->tcon, cfile->netfid, 0, 0, 0, 0, rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
LOCKING_ANDX_OPLOCK_RELEASE, false); 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false);
cFYI(1, "Oplock release rc = %d", rc); cFYI(1, "Oplock release rc = %d", rc);
} }

View File

@ -289,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp)
struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsFileInfo *cfile = filp->private_data; struct cifsFileInfo *cfile = filp->private_data;
struct cifsTconInfo *tcon = cfile->tcon; struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
xid = GetXid(); xid = GetXid();
rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); 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 inode *inode = filp->f_path.dentry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsFileInfo *cfile = filp->private_data; struct cifsFileInfo *cfile = filp->private_data;
struct cifsTconInfo *tcon = cfile->tcon; struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
xid = GetXid(); xid = GetXid();
rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); 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) { if (open_file) {
netfid = open_file->netfid; netfid = open_file->netfid;
netpid = open_file->pid; netpid = open_file->pid;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
goto set_via_filehandle; goto set_via_filehandle;
} }
@ -1696,7 +1696,7 @@ int cifs_revalidate_file(struct file *filp)
if (!cifs_inode_needs_reval(inode)) if (!cifs_inode_needs_reval(inode))
goto check_inval; goto check_inval;
if (cfile->tcon->unix_ext) if (tlink_tcon(cfile->tlink)->unix_ext)
rc = cifs_get_file_info_unix(filp); rc = cifs_get_file_info_unix(filp);
else else
rc = cifs_get_file_info(filp); rc = cifs_get_file_info(filp);
@ -1817,7 +1817,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
if (open_file) { if (open_file) {
__u16 nfid = open_file->netfid; __u16 nfid = open_file->netfid;
__u32 npid = open_file->pid; __u32 npid = open_file->pid;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
npid, false); npid, false);
cifsFileInfo_put(open_file); cifsFileInfo_put(open_file);
@ -1982,7 +1982,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (open_file) { if (open_file) {
u16 nfid = open_file->netfid; u16 nfid = open_file->netfid;
u32 npid = open_file->pid; u32 npid = open_file->pid;
pTcon = open_file->tcon; pTcon = tlink_tcon(open_file->tlink);
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
cifsFileInfo_put(open_file); cifsFileInfo_put(open_file);
} else { } else {

View File

@ -38,7 +38,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
struct cifsFileInfo *pSMBFile = filep->private_data; struct cifsFileInfo *pSMBFile = filep->private_data;
struct cifsTconInfo *tcon = pSMBFile->tcon; struct cifsTconInfo *tcon = tlink_tcon(pSMBFile->tlink);
__u64 ExtAttrBits = 0; __u64 ExtAttrBits = 0;
__u64 ExtAttrMask = 0; __u64 ExtAttrMask = 0;
__u64 caps = le64_to_cpu(tcon->fsUnixInfo.Capability); __u64 caps = le64_to_cpu(tcon->fsUnixInfo.Capability);

View File

@ -346,7 +346,6 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
goto cifs_hl_exit; goto cifs_hl_exit;
} }
/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
if (pTcon->unix_ext) if (pTcon->unix_ext)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb->local_nls, cifs_sb->local_nls,

View File

@ -245,7 +245,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile = file->private_data; cifsFile = file->private_data;
cifsFile->invalidHandle = true; cifsFile->invalidHandle = true;
cifsFile->srch_inf.endOfSearch = false; cifsFile->srch_inf.endOfSearch = false;
cifsFile->tcon = pTcon; cifsFile->tlink = cifs_get_tlink(tlink);
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) { if (full_path == NULL) {
@ -838,7 +838,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
CIFSFindClose(xid, pTcon, cifsFile->netfid); CIFSFindClose(xid, pTcon, cifsFile->netfid);
} */ } */
pTcon = cifsFile->tcon; pTcon = tlink_tcon(cifsFile->tlink);
rc = find_cifs_entry(xid, pTcon, file, rc = find_cifs_entry(xid, pTcon, file,
&current_entry, &num_to_fill); &current_entry, &num_to_fill);
if (rc) { if (rc) {