Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b646972 authored by Tejun Heo's avatar Tejun Heo
Browse files

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: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarSteve French <sfrench@samba.org>
Cc: Anton Blanchard <anton@samba.org>
parent d098adfb
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -2,7 +2,6 @@ config CIFS
	tristate "CIFS support (advanced network filesystem, SMBFS successor)"
	depends on INET
	select NLS
	select SLOW_WORK
	help
	  This is the client VFS module for the Common Internet File System
	  (CIFS) protocol which is the successor to the Server Message Block
+0 −5
Original line number Diff line number Diff line
@@ -917,15 +917,10 @@ init_cifs(void)
	if (rc)
		goto out_unregister_key_type;
#endif
	rc = slow_work_register_user(THIS_MODULE);
	if (rc)
		goto out_unregister_resolver_key;

	return 0;

 out_unregister_resolver_key:
#ifdef CONFIG_CIFS_DFS_UPCALL
	unregister_key_type(&key_type_dns_resolver);
 out_unregister_key_type:
#endif
#ifdef CONFIG_CIFS_UPCALL
+5 −3
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/slab.h>
#include <linux/slow-work.h>
#include <linux/workqueue.h>
#include "cifs_fs_sb.h"
#include "cifsacl.h"
/*
@@ -363,7 +363,7 @@ struct cifsFileInfo {
	atomic_t count;		/* reference count */
	struct mutex fh_mutex; /* prevents reopen race after dead ses*/
	struct cifs_search_info srch_inf;
	struct slow_work oplock_break; /* slow_work job for oplock breaks */
	struct work_struct oplock_break; /* work for oplock breaks */
};

/* Take a reference on the file private data */
@@ -732,4 +732,6 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
GLOBAL_EXTERN unsigned int cifs_min_small;  /* min size of small buf pool */
GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/

extern const struct slow_work_ops cifs_oplock_break_ops;
void cifs_oplock_break(struct work_struct *work);
void cifs_oplock_break_get(struct cifsFileInfo *cfile);
void cifs_oplock_break_put(struct cifsFileInfo *cfile);
+1 −1
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
	mutex_init(&pCifsFile->lock_mutex);
	INIT_LIST_HEAD(&pCifsFile->llist);
	atomic_set(&pCifsFile->count, 1);
	slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);

	write_lock(&GlobalSMBSeslock);
	list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
+13 −17
Original line number Diff line number Diff line
@@ -2295,8 +2295,7 @@ out:
	return rc;
}

static void
cifs_oplock_break(struct slow_work *work)
void cifs_oplock_break(struct work_struct *work)
{
	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
						  oplock_break);
@@ -2333,33 +2332,30 @@ cifs_oplock_break(struct slow_work *work)
				 LOCKING_ANDX_OPLOCK_RELEASE, false);
		cFYI(1, "Oplock release rc = %d", rc);
	}

	/*
	 * We might have kicked in before is_valid_oplock_break()
	 * finished grabbing reference for us.  Make sure it's done by
	 * waiting for GlobalSMSSeslock.
	 */
	write_lock(&GlobalSMBSeslock);
	write_unlock(&GlobalSMBSeslock);

	cifs_oplock_break_put(cfile);
}

static int
cifs_oplock_break_get(struct slow_work *work)
void cifs_oplock_break_get(struct cifsFileInfo *cfile)
{
	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
						  oplock_break);
	mntget(cfile->mnt);
	cifsFileInfo_get(cfile);
	return 0;
}

static void
cifs_oplock_break_put(struct slow_work *work)
void cifs_oplock_break_put(struct cifsFileInfo *cfile)
{
	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
						  oplock_break);
	mntput(cfile->mnt);
	cifsFileInfo_put(cfile);
}

const struct slow_work_ops cifs_oplock_break_ops = {
	.get_ref	= cifs_oplock_break_get,
	.put_ref	= cifs_oplock_break_put,
	.execute	= cifs_oplock_break,
};

const struct address_space_operations cifs_addr_ops = {
	.readpage = cifs_readpage,
	.readpages = cifs_readpages,
Loading