]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/mnt_clone_write.patch
Disable build of xen kernel.
[ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / mnt_clone_write.patch
1 From: Nick Piggin <npiggin@suse.de>
2 Subject: fs: introduce mnt_clone_write
3 References: bnc#436953
4 Patch-upstream: no (could be submitted)
5
6 This patch speeds up lmbench lat_mmap test by about another 2% after the
7 first patch.
8
9 Before:
10 avg = 462.286
11 std = 5.46106
12
13 After:
14 avg = 453.12
15 std = 9.58257
16
17 (50 runs of each, stddev gives a reasonable confidence)
18
19 It does this by introducing mnt_clone_write, which avoids some heavyweight
20 operations of mnt_want_write if called on a vfsmount which we know already
21 has a write count; and mnt_want_write_file, which can call mnt_clone_write
22 if the file is open for write.
23
24 After these two patches, mnt_want_write and mnt_drop_write go from 7% on
25 the profile down to 1.3% (including mnt_clone_write).
26
27 ---
28 fs/file_table.c | 3 +--
29 fs/inode.c | 2 +-
30 fs/namespace.c | 38 ++++++++++++++++++++++++++++++++++++++
31 fs/open.c | 4 ++--
32 fs/xattr.c | 4 ++--
33 include/linux/mount.h | 2 ++
34 6 files changed, 46 insertions(+), 7 deletions(-)
35
36 --- a/fs/file_table.c
37 +++ b/fs/file_table.c
38 @@ -210,8 +210,7 @@ int init_file(struct file *file, struct
39 */
40 if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
41 file_take_write(file);
42 - error = mnt_want_write(mnt);
43 - WARN_ON(error);
44 + mnt_clone_write(mnt);
45 }
46 return error;
47 }
48 --- a/fs/inode.c
49 +++ b/fs/inode.c
50 @@ -1256,7 +1256,7 @@ void file_update_time(struct file *file)
51 if (IS_NOCMTIME(inode))
52 return;
53
54 - err = mnt_want_write(file->f_path.mnt);
55 + err = mnt_want_write_file(file->f_path.mnt, file);
56 if (err)
57 return;
58
59 --- a/fs/namespace.c
60 +++ b/fs/namespace.c
61 @@ -264,6 +264,44 @@ out:
62 EXPORT_SYMBOL_GPL(mnt_want_write);
63
64 /**
65 + * mnt_clone_write - get write access to a mount
66 + * @mnt: the mount on which to take a write
67 + *
68 + * This is effectively like mnt_want_write, except
69 + * it must only be used to take an extra write reference
70 + * on a mountpoint that we already know has a write reference
71 + * on it. This allows some optimisation.
72 + *
73 + * After finished, mnt_drop_write must be called as usual to
74 + * drop the reference.
75 + */
76 +void mnt_clone_write(struct vfsmount *mnt)
77 +{
78 + preempt_disable();
79 + inc_mnt_writers(mnt);
80 + preempt_enable();
81 +}
82 +EXPORT_SYMBOL_GPL(mnt_clone_write);
83 +
84 +/**
85 + * mnt_want_write_file - get write access to a file's mount
86 + * @file: the file who's mount on which to take a write
87 + *
88 + * This is like mnt_want_write, but it takes a file and can
89 + * do some optimisations if the file is open for write already
90 + */
91 +int mnt_want_write_file(struct vfsmount *mnt, struct file *file)
92 +{
93 + if (!(file->f_mode & FMODE_WRITE))
94 + return mnt_want_write(mnt);
95 + else {
96 + mnt_clone_write(mnt);
97 + return 0;
98 + }
99 +}
100 +EXPORT_SYMBOL_GPL(mnt_want_write_file);
101 +
102 +/**
103 * mnt_drop_write - give up write access to a mount
104 * @mnt: the mount on which to give up write access
105 *
106 --- a/fs/open.c
107 +++ b/fs/open.c
108 @@ -616,7 +616,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
109
110 audit_inode(NULL, dentry);
111
112 - err = mnt_want_write(file->f_path.mnt);
113 + err = mnt_want_write_file(file->f_path.mnt, file);
114 if (err)
115 goto out_putf;
116 mutex_lock(&inode->i_mutex);
117 @@ -765,7 +765,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
118 if (!file)
119 goto out;
120
121 - error = mnt_want_write(file->f_path.mnt);
122 + error = mnt_want_write_file(file->f_path.mnt, file);
123 if (error)
124 goto out_fput;
125 dentry = file->f_path.dentry;
126 --- a/fs/xattr.c
127 +++ b/fs/xattr.c
128 @@ -301,7 +301,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
129 return error;
130 dentry = f->f_path.dentry;
131 audit_inode(NULL, dentry);
132 - error = mnt_want_write(f->f_path.mnt);
133 + error = mnt_want_write_file(f->f_path.mnt, f);
134 if (!error) {
135 error = setxattr(dentry, name, value, size, flags);
136 mnt_drop_write(f->f_path.mnt);
137 @@ -528,7 +528,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, c
138 return error;
139 dentry = f->f_path.dentry;
140 audit_inode(NULL, dentry);
141 - error = mnt_want_write(f->f_path.mnt);
142 + error = mnt_want_write_file(f->f_path.mnt, f);
143 if (!error) {
144 error = removexattr(dentry, name);
145 mnt_drop_write(f->f_path.mnt);
146 --- a/include/linux/mount.h
147 +++ b/include/linux/mount.h
148 @@ -99,6 +99,8 @@ static inline struct vfsmount *mntget(st
149 }
150
151 extern int mnt_want_write(struct vfsmount *mnt);
152 +extern int mnt_want_write_file(struct vfsmount *mnt, struct file *file);
153 +extern void mnt_clone_write(struct vfsmount *mnt);
154 extern void mnt_drop_write(struct vfsmount *mnt);
155 extern void mntput_no_expire(struct vfsmount *mnt);
156 extern void mnt_pin(struct vfsmount *mnt);