aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-10-11 15:07:19 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-12 14:08:01 -0400
commitd7c86ff8cd00abc730fe5d031f43dc9138b6324e (patch)
treea1f264ce2f33e3ac77a459291b9a5e45a63e3bff /fs
parenta5e18bc36e9e05ce0338d370a2ce4290910e43ea (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifsfs.c18
-rw-r--r--fs/cifs/cifsfs.h6
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/dir.c10
-rw-r--r--fs/cifs/file.c9
7 files changed, 29 insertions, 18 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 586ee3d527d2..525ba59a4105 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -48,6 +48,7 @@ struct cifs_sb_info {
48 struct nls_table *local_nls; 48 struct nls_table *local_nls;
49 unsigned int rsize; 49 unsigned int rsize;
50 unsigned int wsize; 50 unsigned int wsize;
51 atomic_t active;
51 uid_t mnt_uid; 52 uid_t mnt_uid;
52 gid_t mnt_gid; 53 gid_t mnt_gid;
53 mode_t mnt_file_mode; 54 mode_t mnt_file_mode;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 3258c822328b..cbd468c880c4 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -83,6 +83,24 @@ extern mempool_t *cifs_sm_req_poolp;
83extern mempool_t *cifs_req_poolp; 83extern mempool_t *cifs_req_poolp;
84extern mempool_t *cifs_mid_poolp; 84extern mempool_t *cifs_mid_poolp;
85 85
86void
87cifs_sb_active(struct super_block *sb)
88{
89 struct cifs_sb_info *server = CIFS_SB(sb);
90
91 if (atomic_inc_return(&server->active) == 1)
92 atomic_inc(&sb->s_active);
93}
94
95void
96cifs_sb_deactive(struct super_block *sb)
97{
98 struct cifs_sb_info *server = CIFS_SB(sb);
99
100 if (atomic_dec_and_test(&server->active))
101 deactivate_super(sb);
102}
103
86static int 104static int
87cifs_read_super(struct super_block *sb, void *data, 105cifs_read_super(struct super_block *sb, void *data,
88 const char *devname, int silent) 106 const char *devname, int silent)
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 786bdf36aebf..85544bcab517 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -42,10 +42,8 @@ extern const struct address_space_operations cifs_addr_ops;
42extern const struct address_space_operations cifs_addr_ops_smallbuf; 42extern const struct address_space_operations cifs_addr_ops_smallbuf;
43 43
44/* Functions related to super block operations */ 44/* Functions related to super block operations */
45/* extern const struct super_operations cifs_super_ops;*/ 45extern void cifs_sb_active(struct super_block *sb);
46extern void cifs_read_inode(struct inode *); 46extern void cifs_sb_deactive(struct super_block *sb);
47/*extern void cifs_delete_inode(struct inode *);*/ /* BB not needed yet */
48/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
49 47
50/* Functions related to inodes */ 48/* Functions related to inodes */
51extern const struct inode_operations cifs_dir_inode_ops; 49extern const struct inode_operations cifs_dir_inode_ops;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 8289e61937a2..e2b760ef22ff 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -388,7 +388,6 @@ struct cifsFileInfo {
388 /* lock scope id (0 if none) */ 388 /* lock scope id (0 if none) */
389 struct file *pfile; /* needed for writepage */ 389 struct file *pfile; /* needed for writepage */
390 struct dentry *dentry; 390 struct dentry *dentry;
391 struct vfsmount *mnt;
392 struct tcon_link *tlink; 391 struct tcon_link *tlink;
393 struct mutex lock_mutex; 392 struct mutex lock_mutex;
394 struct list_head llist; /* list of byte range locks we have. */ 393 struct list_head llist; /* list of byte range locks we have. */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 29a2ee8ae51f..7f416abd34cf 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,
107 107
108extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, 108extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
109 __u16 fileHandle, struct file *file, 109 __u16 fileHandle, struct file *file,
110 struct vfsmount *mnt, struct tcon_link *tlink, 110 struct tcon_link *tlink,
111 unsigned int oflags, __u32 oplock); 111 unsigned int oflags, __u32 oplock);
112extern int cifs_posix_open(char *full_path, struct inode **pinode, 112extern int cifs_posix_open(char *full_path, struct inode **pinode,
113 struct super_block *sb, 113 struct super_block *sb,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 6887c412c61a..c205ec9293ea 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -132,8 +132,7 @@ cifs_bp_rename_retry:
132 132
133struct cifsFileInfo * 133struct cifsFileInfo *
134cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, 134cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
135 struct vfsmount *mnt, struct tcon_link *tlink, 135 struct tcon_link *tlink, unsigned int oflags, __u32 oplock)
136 unsigned int oflags, __u32 oplock)
137{ 136{
138 struct dentry *dentry = file->f_path.dentry; 137 struct dentry *dentry = file->f_path.dentry;
139 struct cifsFileInfo *pCifsFile; 138 struct cifsFileInfo *pCifsFile;
@@ -147,7 +146,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file,
147 pCifsFile->pid = current->tgid; 146 pCifsFile->pid = current->tgid;
148 pCifsFile->uid = current_fsuid(); 147 pCifsFile->uid = current_fsuid();
149 pCifsFile->dentry = dget(dentry); 148 pCifsFile->dentry = dget(dentry);
150 pCifsFile->mnt = mnt;
151 pCifsFile->pfile = file; 149 pCifsFile->pfile = file;
152 pCifsFile->invalidHandle = false; 150 pCifsFile->invalidHandle = false;
153 pCifsFile->closePend = false; 151 pCifsFile->closePend = false;
@@ -485,8 +483,7 @@ cifs_create_set_dentry:
485 } 483 }
486 484
487 pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, 485 pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
488 nd->path.mnt, tlink, oflags, 486 tlink, oflags, oplock);
489 oplock);
490 if (pfile_info == NULL) { 487 if (pfile_info == NULL) {
491 fput(filp); 488 fput(filp);
492 CIFSSMBClose(xid, tcon, fileHandle); 489 CIFSSMBClose(xid, tcon, fileHandle);
@@ -760,8 +757,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
760 } 757 }
761 758
762 cfile = cifs_new_fileinfo(newInode, fileHandle, filp, 759 cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
763 nd->path.mnt, tlink, 760 tlink, nd->intent.open.flags,
764 nd->intent.open.flags,
765 oplock); 761 oplock);
766 if (cfile == NULL) { 762 if (cfile == NULL) {
767 fput(filp); 763 fput(filp);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c302b9c52644..fd78a355f634 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -282,7 +282,6 @@ int cifs_open(struct inode *inode, struct file *file)
282 } 282 }
283 283
284 pCifsFile = cifs_new_fileinfo(inode, netfid, file, 284 pCifsFile = cifs_new_fileinfo(inode, netfid, file,
285 file->f_path.mnt,
286 tlink, oflags, oplock); 285 tlink, oflags, oplock);
287 if (pCifsFile == NULL) { 286 if (pCifsFile == NULL) {
288 CIFSSMBClose(xid, tcon, netfid); 287 CIFSSMBClose(xid, tcon, netfid);
@@ -375,8 +374,8 @@ int cifs_open(struct inode *inode, struct file *file)
375 if (rc != 0) 374 if (rc != 0)
376 goto out; 375 goto out;
377 376
378 pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, 377 pCifsFile = cifs_new_fileinfo(inode, netfid, file, tlink,
379 tlink, file->f_flags, oplock); 378 file->f_flags, oplock);
380 if (pCifsFile == NULL) { 379 if (pCifsFile == NULL) {
381 rc = -ENOMEM; 380 rc = -ENOMEM;
382 goto out; 381 goto out;
@@ -2381,14 +2380,14 @@ void cifs_oplock_break(struct work_struct *work)
2381 2380
2382void cifs_oplock_break_get(struct cifsFileInfo *cfile) 2381void cifs_oplock_break_get(struct cifsFileInfo *cfile)
2383{ 2382{
2384 mntget(cfile->mnt); 2383 cifs_sb_active(cfile->dentry->d_sb);
2385 cifsFileInfo_get(cfile); 2384 cifsFileInfo_get(cfile);
2386} 2385}
2387 2386
2388void cifs_oplock_break_put(struct cifsFileInfo *cfile) 2387void cifs_oplock_break_put(struct cifsFileInfo *cfile)
2389{ 2388{
2390 mntput(cfile->mnt);
2391 cifsFileInfo_put(cfile); 2389 cifsFileInfo_put(cfile);
2390 cifs_sb_deactive(cfile->dentry->d_sb);
2392} 2391}
2393 2392
2394const struct address_space_operations cifs_addr_ops = { 2393const struct address_space_operations cifs_addr_ops = {