mirror of https://gitee.com/openkylin/linux.git
cifs: don't use vfsmount to pin superblock for oplock breaks
Filesystems aren't really supposed to do anything with a vfsmount. It's considered a layering violation since vfsmounts are entirely managed at the VFS layer. CIFS currently keeps an active reference to a vfsmount in order to prevent the superblock vanishing before an oplock break has completed. What we really want to do instead is to keep sb->s_active high until the oplock break has completed. This patch borrows the scheme that NFS uses for handling sillyrenames. An atomic_t is added to the cifs_sb_info. When it transitions from 0 to 1, an extra reference to the superblock is taken (by bumping the s_active value). When it transitions from 1 to 0, that reference is dropped and a the superblock teardown may proceed if there are no more references to it. Also, the vfsmount pointer is removed from cifsFileInfo and from cifs_new_fileinfo, and some bogus forward declarations are removed from cifsfs.h. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de> Acked-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
a5e18bc36e
commit
d7c86ff8cd
|
@ -48,6 +48,7 @@ struct cifs_sb_info {
|
||||||
struct nls_table *local_nls;
|
struct nls_table *local_nls;
|
||||||
unsigned int rsize;
|
unsigned int rsize;
|
||||||
unsigned int wsize;
|
unsigned int wsize;
|
||||||
|
atomic_t active;
|
||||||
uid_t mnt_uid;
|
uid_t mnt_uid;
|
||||||
gid_t mnt_gid;
|
gid_t mnt_gid;
|
||||||
mode_t mnt_file_mode;
|
mode_t mnt_file_mode;
|
||||||
|
|
|
@ -83,6 +83,24 @@ extern mempool_t *cifs_sm_req_poolp;
|
||||||
extern mempool_t *cifs_req_poolp;
|
extern mempool_t *cifs_req_poolp;
|
||||||
extern mempool_t *cifs_mid_poolp;
|
extern mempool_t *cifs_mid_poolp;
|
||||||
|
|
||||||
|
void
|
||||||
|
cifs_sb_active(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct cifs_sb_info *server = CIFS_SB(sb);
|
||||||
|
|
||||||
|
if (atomic_inc_return(&server->active) == 1)
|
||||||
|
atomic_inc(&sb->s_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cifs_sb_deactive(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct cifs_sb_info *server = CIFS_SB(sb);
|
||||||
|
|
||||||
|
if (atomic_dec_and_test(&server->active))
|
||||||
|
deactivate_super(sb);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_read_super(struct super_block *sb, void *data,
|
cifs_read_super(struct super_block *sb, void *data,
|
||||||
const char *devname, int silent)
|
const char *devname, int silent)
|
||||||
|
|
|
@ -42,10 +42,8 @@ extern const struct address_space_operations cifs_addr_ops;
|
||||||
extern const struct address_space_operations cifs_addr_ops_smallbuf;
|
extern const struct address_space_operations cifs_addr_ops_smallbuf;
|
||||||
|
|
||||||
/* Functions related to super block operations */
|
/* Functions related to super block operations */
|
||||||
/* extern const struct super_operations cifs_super_ops;*/
|
extern void cifs_sb_active(struct super_block *sb);
|
||||||
extern void cifs_read_inode(struct inode *);
|
extern void cifs_sb_deactive(struct super_block *sb);
|
||||||
/*extern void cifs_delete_inode(struct inode *);*/ /* BB not needed yet */
|
|
||||||
/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
|
|
||||||
|
|
||||||
/* Functions related to inodes */
|
/* Functions related to inodes */
|
||||||
extern const struct inode_operations cifs_dir_inode_ops;
|
extern const struct inode_operations cifs_dir_inode_ops;
|
||||||
|
|
|
@ -388,7 +388,6 @@ struct cifsFileInfo {
|
||||||
/* lock scope id (0 if none) */
|
/* lock scope id (0 if none) */
|
||||||
struct file *pfile; /* needed for writepage */
|
struct file *pfile; /* needed for writepage */
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct vfsmount *mnt;
|
|
||||||
struct tcon_link *tlink;
|
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. */
|
||||||
|
|
|
@ -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 tcon_link *tlink,
|
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,
|
||||||
|
|
|
@ -132,8 +132,7 @@ build_path_from_dentry(struct dentry *direntry)
|
||||||
|
|
||||||
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 tcon_link *tlink,
|
struct tcon_link *tlink, unsigned int oflags, __u32 oplock)
|
||||||
unsigned int oflags, __u32 oplock)
|
|
||||||
{
|
{
|
||||||
struct dentry *dentry = file->f_path.dentry;
|
struct dentry *dentry = file->f_path.dentry;
|
||||||
struct cifsFileInfo *pCifsFile;
|
struct cifsFileInfo *pCifsFile;
|
||||||
|
@ -147,7 +146,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
|
||||||
pCifsFile->pid = current->tgid;
|
pCifsFile->pid = current->tgid;
|
||||||
pCifsFile->uid = current_fsuid();
|
pCifsFile->uid = current_fsuid();
|
||||||
pCifsFile->dentry = dget(dentry);
|
pCifsFile->dentry = dget(dentry);
|
||||||
pCifsFile->mnt = mnt;
|
|
||||||
pCifsFile->pfile = file;
|
pCifsFile->pfile = file;
|
||||||
pCifsFile->invalidHandle = false;
|
pCifsFile->invalidHandle = false;
|
||||||
pCifsFile->closePend = false;
|
pCifsFile->closePend = false;
|
||||||
|
@ -485,8 +483,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
|
pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
|
||||||
nd->path.mnt, tlink, oflags,
|
tlink, oflags, oplock);
|
||||||
oplock);
|
|
||||||
if (pfile_info == NULL) {
|
if (pfile_info == NULL) {
|
||||||
fput(filp);
|
fput(filp);
|
||||||
CIFSSMBClose(xid, tcon, fileHandle);
|
CIFSSMBClose(xid, tcon, fileHandle);
|
||||||
|
@ -760,8 +757,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, tlink,
|
tlink, nd->intent.open.flags,
|
||||||
nd->intent.open.flags,
|
|
||||||
oplock);
|
oplock);
|
||||||
if (cfile == NULL) {
|
if (cfile == NULL) {
|
||||||
fput(filp);
|
fput(filp);
|
||||||
|
|
|
@ -282,7 +282,6 @@ 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,
|
|
||||||
tlink, oflags, oplock);
|
tlink, oflags, oplock);
|
||||||
if (pCifsFile == NULL) {
|
if (pCifsFile == NULL) {
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
CIFSSMBClose(xid, tcon, netfid);
|
||||||
|
@ -375,8 +374,8 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
|
pCifsFile = cifs_new_fileinfo(inode, netfid, file, tlink,
|
||||||
tlink, file->f_flags, oplock);
|
file->f_flags, oplock);
|
||||||
if (pCifsFile == NULL) {
|
if (pCifsFile == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2381,14 +2380,14 @@ void cifs_oplock_break(struct work_struct *work)
|
||||||
|
|
||||||
void cifs_oplock_break_get(struct cifsFileInfo *cfile)
|
void cifs_oplock_break_get(struct cifsFileInfo *cfile)
|
||||||
{
|
{
|
||||||
mntget(cfile->mnt);
|
cifs_sb_active(cfile->dentry->d_sb);
|
||||||
cifsFileInfo_get(cfile);
|
cifsFileInfo_get(cfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cifs_oplock_break_put(struct cifsFileInfo *cfile)
|
void cifs_oplock_break_put(struct cifsFileInfo *cfile)
|
||||||
{
|
{
|
||||||
mntput(cfile->mnt);
|
|
||||||
cifsFileInfo_put(cfile);
|
cifsFileInfo_put(cfile);
|
||||||
|
cifs_sb_deactive(cfile->dentry->d_sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct address_space_operations cifs_addr_ops = {
|
const struct address_space_operations cifs_addr_ops = {
|
||||||
|
|
Loading…
Reference in New Issue