aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-07-26 12:20:17 -0400
committerSteve French <sfrench@us.ibm.com>2011-07-31 17:21:20 -0400
commitad635942c869ad8fc9af270d4998c42b4e978b32 (patch)
treeb199a039df4aacd26224302b7c29193171e4d444 /fs/cifs/file.c
parent5980fc966bb347801f3fcc39a2ef2a1e14fbf8cb (diff)
cifs: simplify refcounting for oplock breaks
Currently, we take a sb->s_active reference and a cifsFileInfo reference when an oplock break workqueue job is queued. This is unnecessary and more complicated than it needs to be. Also as Al points out, deactivate_super has non-trivial locking implications so it's best to avoid that if we can. Instead, just cancel any pending oplock breaks for this filehandle synchronously in cifsFileInfo_put after taking it off the lists. That should ensure that this job doesn't outlive the structures it depends on. Reported-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c27
1 files changed, 2 insertions, 25 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 378acdafa356..9f41a10523a1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -314,6 +314,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
314 } 314 }
315 spin_unlock(&cifs_file_list_lock); 315 spin_unlock(&cifs_file_list_lock);
316 316
317 cancel_work_sync(&cifs_file->oplock_break);
318
317 if (!tcon->need_reconnect && !cifs_file->invalidHandle) { 319 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
318 int xid, rc; 320 int xid, rc;
319 321
@@ -2418,31 +2420,6 @@ void cifs_oplock_break(struct work_struct *work)
2418 cinode->clientCanCacheRead ? 1 : 0); 2420 cinode->clientCanCacheRead ? 1 : 0);
2419 cFYI(1, "Oplock release rc = %d", rc); 2421 cFYI(1, "Oplock release rc = %d", rc);
2420 } 2422 }
2421
2422 /*
2423 * We might have kicked in before is_valid_oplock_break()
2424 * finished grabbing reference for us. Make sure it's done by
2425 * waiting for cifs_file_list_lock.
2426 */
2427 spin_lock(&cifs_file_list_lock);
2428 spin_unlock(&cifs_file_list_lock);
2429
2430 cifs_oplock_break_put(cfile);
2431}
2432
2433/* must be called while holding cifs_file_list_lock */
2434void cifs_oplock_break_get(struct cifsFileInfo *cfile)
2435{
2436 cifs_sb_active(cfile->dentry->d_sb);
2437 cifsFileInfo_get(cfile);
2438}
2439
2440void cifs_oplock_break_put(struct cifsFileInfo *cfile)
2441{
2442 struct super_block *sb = cfile->dentry->d_sb;
2443
2444 cifsFileInfo_put(cfile);
2445 cifs_sb_deactive(sb);
2446} 2423}
2447 2424
2448const struct address_space_operations cifs_addr_ops = { 2425const struct address_space_operations cifs_addr_ops = {