diff options
author | Tejun Heo <tj@kernel.org> | 2010-07-20 16:09:02 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-07-22 16:59:15 -0400 |
commit | 9b646972467fb5fdc677f9e4251875db20bdbb64 (patch) | |
tree | 01d54cf7e0ee110bd8287c3360de0c3997e859ae /fs/cifs/file.c | |
parent | d098adfb7d281258173a43151483e52e21761021 (diff) |
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>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 75541af4b3db..e767bfa7978b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2295,8 +2295,7 @@ out: | |||
2295 | return rc; | 2295 | return rc; |
2296 | } | 2296 | } |
2297 | 2297 | ||
2298 | static void | 2298 | void cifs_oplock_break(struct work_struct *work) |
2299 | cifs_oplock_break(struct slow_work *work) | ||
2300 | { | 2299 | { |
2301 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2300 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
2302 | oplock_break); | 2301 | oplock_break); |
@@ -2333,33 +2332,30 @@ cifs_oplock_break(struct slow_work *work) | |||
2333 | LOCKING_ANDX_OPLOCK_RELEASE, false); | 2332 | LOCKING_ANDX_OPLOCK_RELEASE, false); |
2334 | cFYI(1, "Oplock release rc = %d", rc); | 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 | 2347 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) |
2339 | cifs_oplock_break_get(struct slow_work *work) | ||
2340 | { | 2348 | { |
2341 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2342 | oplock_break); | ||
2343 | mntget(cfile->mnt); | 2349 | mntget(cfile->mnt); |
2344 | cifsFileInfo_get(cfile); | 2350 | cifsFileInfo_get(cfile); |
2345 | return 0; | ||
2346 | } | 2351 | } |
2347 | 2352 | ||
2348 | static void | 2353 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
2349 | cifs_oplock_break_put(struct slow_work *work) | ||
2350 | { | 2354 | { |
2351 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2352 | oplock_break); | ||
2353 | mntput(cfile->mnt); | 2355 | mntput(cfile->mnt); |
2354 | cifsFileInfo_put(cfile); | 2356 | cifsFileInfo_put(cfile); |
2355 | } | 2357 | } |
2356 | 2358 | ||
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 | |||
2363 | const struct address_space_operations cifs_addr_ops = { | 2359 | const struct address_space_operations cifs_addr_ops = { |
2364 | .readpage = cifs_readpage, | 2360 | .readpage = cifs_readpage, |
2365 | .readpages = cifs_readpages, | 2361 | .readpages = cifs_readpages, |