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/file.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/file.c')
-rw-r--r-- | fs/cifs/file.c | 9 |
1 files changed, 4 insertions, 5 deletions
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 | ||
2382 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) | 2381 | void 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 | ||
2388 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) | 2387 | void 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 | ||
2394 | const struct address_space_operations cifs_addr_ops = { | 2393 | const struct address_space_operations cifs_addr_ops = { |