Commit 9b646972467fb5fdc677f9e4251875db20bdbb64

Authored by Tejun Heo
1 parent d098adfb7d

cifs: use workqueue instead of slow-work

Workqueue can now handle high concurrency.  Use system_nrt_wq
instead of slow-work.

* Updated is_valid_oplock_break() to not call cifs_oplock_break_put()
  as advised by Steve French.  It might cause deadlock.  Instead,
  reference is increased after queueing succeeded and
  cifs_oplock_break() briefly grabs GlobalSMBSeslock before putting
  the cfile to make sure it doesn't put before the matching get is
  finished.

* Anton Blanchard reported that cifs conversion was using now gone
  system_single_wq.  Use system_nrt_wq which provides non-reentrance
  guarantee which is enough and much better.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Steve French <sfrench@samba.org>
Cc: Anton Blanchard <anton@samba.org>

Showing 6 changed files with 31 additions and 35 deletions Side-by-side Diff

... ... @@ -2,7 +2,6 @@
2 2 tristate "CIFS support (advanced network filesystem, SMBFS successor)"
3 3 depends on INET
4 4 select NLS
5   - select SLOW_WORK
6 5 help
7 6 This is the client VFS module for the Common Internet File System
8 7 (CIFS) protocol which is the successor to the Server Message Block
... ... @@ -917,15 +917,10 @@
917 917 if (rc)
918 918 goto out_unregister_key_type;
919 919 #endif
920   - rc = slow_work_register_user(THIS_MODULE);
921   - if (rc)
922   - goto out_unregister_resolver_key;
923 920  
924 921 return 0;
925 922  
926   - out_unregister_resolver_key:
927 923 #ifdef CONFIG_CIFS_DFS_UPCALL
928   - unregister_key_type(&key_type_dns_resolver);
929 924 out_unregister_key_type:
930 925 #endif
931 926 #ifdef CONFIG_CIFS_UPCALL
... ... @@ -19,7 +19,7 @@
19 19 #include <linux/in.h>
20 20 #include <linux/in6.h>
21 21 #include <linux/slab.h>
22   -#include <linux/slow-work.h>
  22 +#include <linux/workqueue.h>
23 23 #include "cifs_fs_sb.h"
24 24 #include "cifsacl.h"
25 25 /*
... ... @@ -363,7 +363,7 @@
363 363 atomic_t count; /* reference count */
364 364 struct mutex fh_mutex; /* prevents reopen race after dead ses*/
365 365 struct cifs_search_info srch_inf;
366   - struct slow_work oplock_break; /* slow_work job for oplock breaks */
  366 + struct work_struct oplock_break; /* work for oplock breaks */
367 367 };
368 368  
369 369 /* Take a reference on the file private data */
... ... @@ -732,5 +732,7 @@
732 732 GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
733 733 GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
734 734  
735   -extern const struct slow_work_ops cifs_oplock_break_ops;
  735 +void cifs_oplock_break(struct work_struct *work);
  736 +void cifs_oplock_break_get(struct cifsFileInfo *cfile);
  737 +void cifs_oplock_break_put(struct cifsFileInfo *cfile);
... ... @@ -162,7 +162,7 @@
162 162 mutex_init(&pCifsFile->lock_mutex);
163 163 INIT_LIST_HEAD(&pCifsFile->llist);
164 164 atomic_set(&pCifsFile->count, 1);
165   - slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
  165 + INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
166 166  
167 167 write_lock(&GlobalSMBSeslock);
168 168 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
... ... @@ -2295,8 +2295,7 @@
2295 2295 return rc;
2296 2296 }
2297 2297  
2298   -static void
2299   -cifs_oplock_break(struct slow_work *work)
  2298 +void cifs_oplock_break(struct work_struct *work)
2300 2299 {
2301 2300 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2302 2301 oplock_break);
2303 2302  
2304 2303  
2305 2304  
2306 2305  
2307 2306  
2308 2307  
... ... @@ -2333,32 +2332,29 @@
2333 2332 LOCKING_ANDX_OPLOCK_RELEASE, false);
2334 2333 cFYI(1, "Oplock release rc = %d", rc);
2335 2334 }
  2335 +
  2336 + /*
  2337 + * We might have kicked in before is_valid_oplock_break()
  2338 + * finished grabbing reference for us. Make sure it's done by
  2339 + * waiting for GlobalSMSSeslock.
  2340 + */
  2341 + write_lock(&GlobalSMBSeslock);
  2342 + write_unlock(&GlobalSMBSeslock);
  2343 +
  2344 + cifs_oplock_break_put(cfile);
2336 2345 }
2337 2346  
2338   -static int
2339   -cifs_oplock_break_get(struct slow_work *work)
  2347 +void cifs_oplock_break_get(struct cifsFileInfo *cfile)
2340 2348 {
2341   - struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2342   - oplock_break);
2343 2349 mntget(cfile->mnt);
2344 2350 cifsFileInfo_get(cfile);
2345   - return 0;
2346 2351 }
2347 2352  
2348   -static void
2349   -cifs_oplock_break_put(struct slow_work *work)
  2353 +void cifs_oplock_break_put(struct cifsFileInfo *cfile)
2350 2354 {
2351   - struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2352   - oplock_break);
2353 2355 mntput(cfile->mnt);
2354 2356 cifsFileInfo_put(cfile);
2355 2357 }
2356   -
2357   -const struct slow_work_ops cifs_oplock_break_ops = {
2358   - .get_ref = cifs_oplock_break_get,
2359   - .put_ref = cifs_oplock_break_put,
2360   - .execute = cifs_oplock_break,
2361   -};
2362 2358  
2363 2359 const struct address_space_operations cifs_addr_ops = {
2364 2360 .readpage = cifs_readpage,
... ... @@ -498,7 +498,6 @@
498 498 struct cifsTconInfo *tcon;
499 499 struct cifsInodeInfo *pCifsInode;
500 500 struct cifsFileInfo *netfile;
501   - int rc;
502 501  
503 502 cFYI(1, "Checking for oplock break or dnotify response");
504 503 if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
... ... @@ -583,13 +582,18 @@
583 582 pCifsInode->clientCanCacheAll = false;
584 583 if (pSMB->OplockLevel == 0)
585 584 pCifsInode->clientCanCacheRead = false;
586   - rc = slow_work_enqueue(&netfile->oplock_break);
587   - if (rc) {
588   - cERROR(1, "failed to enqueue oplock "
589   - "break: %d\n", rc);
590   - } else {
591   - netfile->oplock_break_cancelled = false;
592   - }
  585 +
  586 + /*
  587 + * cifs_oplock_break_put() can't be called
  588 + * from here. Get reference after queueing
  589 + * succeeded. cifs_oplock_break() will
  590 + * synchronize using GlobalSMSSeslock.
  591 + */
  592 + if (queue_work(system_nrt_wq,
  593 + &netfile->oplock_break))
  594 + cifs_oplock_break_get(netfile);
  595 + netfile->oplock_break_cancelled = false;
  596 +
593 597 read_unlock(&GlobalSMBSeslock);
594 598 read_unlock(&cifs_tcp_ses_lock);
595 599 return true;