diff options
author | npiggin@suse.de <npiggin@suse.de> | 2009-04-26 06:25:55 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-11 21:36:02 -0400 |
commit | 96029c4e09ccbd73a6d0ed2b29e80bf2586ad7ef (patch) | |
tree | 032d2ac7024250c18487a2c7122af68fe56567ff /fs/namespace.c | |
parent | d3ef3d7351ccfbef3e5d926efc5ee332136f40d4 (diff) |
fs: introduce mnt_clone_write
This patch speeds up lmbench lat_mmap test by about another 2% after the
first patch.
Before:
avg = 462.286
std = 5.46106
After:
avg = 453.12
std = 9.58257
(50 runs of each, stddev gives a reasonable confidence)
It does this by introducing mnt_clone_write, which avoids some heavyweight
operations of mnt_want_write if called on a vfsmount which we know already
has a write count; and mnt_want_write_file, which can call mnt_clone_write
if the file is open for write.
After these two patches, mnt_want_write and mnt_drop_write go from 7% on
the profile down to 1.3% (including mnt_clone_write).
[AV: mnt_want_write_file() should take file alone and derive mnt from it;
not only all callers have that form, but that's the only mnt about which
we know that it's already held for write if file is opened for write]
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 22ae06ad751d..120b8a6b99ed 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -265,6 +265,46 @@ out: | |||
265 | EXPORT_SYMBOL_GPL(mnt_want_write); | 265 | EXPORT_SYMBOL_GPL(mnt_want_write); |
266 | 266 | ||
267 | /** | 267 | /** |
268 | * mnt_clone_write - get write access to a mount | ||
269 | * @mnt: the mount on which to take a write | ||
270 | * | ||
271 | * This is effectively like mnt_want_write, except | ||
272 | * it must only be used to take an extra write reference | ||
273 | * on a mountpoint that we already know has a write reference | ||
274 | * on it. This allows some optimisation. | ||
275 | * | ||
276 | * After finished, mnt_drop_write must be called as usual to | ||
277 | * drop the reference. | ||
278 | */ | ||
279 | int mnt_clone_write(struct vfsmount *mnt) | ||
280 | { | ||
281 | /* superblock may be r/o */ | ||
282 | if (__mnt_is_readonly(mnt)) | ||
283 | return -EROFS; | ||
284 | preempt_disable(); | ||
285 | inc_mnt_writers(mnt); | ||
286 | preempt_enable(); | ||
287 | return 0; | ||
288 | } | ||
289 | EXPORT_SYMBOL_GPL(mnt_clone_write); | ||
290 | |||
291 | /** | ||
292 | * mnt_want_write_file - get write access to a file's mount | ||
293 | * @file: the file who's mount on which to take a write | ||
294 | * | ||
295 | * This is like mnt_want_write, but it takes a file and can | ||
296 | * do some optimisations if the file is open for write already | ||
297 | */ | ||
298 | int mnt_want_write_file(struct file *file) | ||
299 | { | ||
300 | if (!(file->f_mode & FMODE_WRITE)) | ||
301 | return mnt_want_write(file->f_path.mnt); | ||
302 | else | ||
303 | return mnt_clone_write(file->f_path.mnt); | ||
304 | } | ||
305 | EXPORT_SYMBOL_GPL(mnt_want_write_file); | ||
306 | |||
307 | /** | ||
268 | * mnt_drop_write - give up write access to a mount | 308 | * mnt_drop_write - give up write access to a mount |
269 | * @mnt: the mount on which to give up write access | 309 | * @mnt: the mount on which to give up write access |
270 | * | 310 | * |