diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-10-11 15:07:19 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-12 14:08:01 -0400 |
commit | d7c86ff8cd00abc730fe5d031f43dc9138b6324e (patch) | |
tree | a1f264ce2f33e3ac77a459291b9a5e45a63e3bff /fs/cifs/cifsfs.c | |
parent | a5e18bc36e9e05ce0338d370a2ce4290910e43ea (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/cifs/cifsfs.c')
-rw-r--r-- | fs/cifs/cifsfs.c | 18 |
1 files changed, 18 insertions, 0 deletions
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; | |||
83 | extern mempool_t *cifs_req_poolp; | 83 | extern mempool_t *cifs_req_poolp; |
84 | extern mempool_t *cifs_mid_poolp; | 84 | extern mempool_t *cifs_mid_poolp; |
85 | 85 | ||
86 | void | ||
87 | cifs_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 | |||
95 | void | ||
96 | cifs_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 | |||
86 | static int | 104 | static int |
87 | cifs_read_super(struct super_block *sb, void *data, | 105 | cifs_read_super(struct super_block *sb, void *data, |
88 | const char *devname, int silent) | 106 | const char *devname, int silent) |