]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/ocfs2-POSIX-file-locks-support.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / ocfs2-POSIX-file-locks-support.patch
1 From: Mark Fasheh <mfasheh@suse.com>
2 Subject: ocfs2: POSIX file locks support
3 Patch-mainline: 2.6.28?
4 References: FATE110294
5
6 This is actually pretty easy since fs/dlm already handles the bulk of the
7 work. The Ocfs2 userspace cluster stack module already uses fs/dlm as the
8 underlying lock manager, so I only had to add the right calls.
9
10 Cluster-aware POSIX locks ("plocks") can be turned off by the same means at
11 UNIX locks - mount with 'noflocks', or create a local-only Ocfs2 volume.
12 Internally, the file system uses two sets of file_operations, depending on
13 whether cluster aware plocks is required. This turns out to be easier than
14 implementing local-only versions of ->lock.
15
16 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
17 ---
18 fs/ocfs2/file.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
19 fs/ocfs2/file.h | 2 +
20 fs/ocfs2/inode.c | 15 ++++++++++++--
21 fs/ocfs2/locks.c | 15 ++++++++++++++
22 fs/ocfs2/locks.h | 1
23 fs/ocfs2/stack_user.c | 33 ++++++++++++++++++++++++++++++++
24 fs/ocfs2/stackglue.c | 20 +++++++++++++++++++
25 fs/ocfs2/stackglue.h | 19 ++++++++++++++++++
26 8 files changed, 154 insertions(+), 2 deletions(-)
27
28 --- a/fs/ocfs2/file.c
29 +++ b/fs/ocfs2/file.c
30 @@ -2154,6 +2154,10 @@ const struct inode_operations ocfs2_spec
31 .permission = ocfs2_permission,
32 };
33
34 +/*
35 + * Other than ->lock, keep ocfs2_fops and ocfs2_dops in sync with
36 + * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
37 + */
38 const struct file_operations ocfs2_fops = {
39 .llseek = generic_file_llseek,
40 .read = do_sync_read,
41 @@ -2168,6 +2172,7 @@ const struct file_operations ocfs2_fops
42 #ifdef CONFIG_COMPAT
43 .compat_ioctl = ocfs2_compat_ioctl,
44 #endif
45 + .lock = ocfs2_lock,
46 .flock = ocfs2_flock,
47 .splice_read = ocfs2_file_splice_read,
48 .splice_write = ocfs2_file_splice_write,
49 @@ -2177,6 +2182,52 @@ const struct file_operations ocfs2_dops
50 .llseek = generic_file_llseek,
51 .read = generic_read_dir,
52 .readdir = ocfs2_readdir,
53 + .fsync = ocfs2_sync_file,
54 + .release = ocfs2_dir_release,
55 + .open = ocfs2_dir_open,
56 + .unlocked_ioctl = ocfs2_ioctl,
57 +#ifdef CONFIG_COMPAT
58 + .compat_ioctl = ocfs2_compat_ioctl,
59 +#endif
60 + .lock = ocfs2_lock,
61 + .flock = ocfs2_flock,
62 +};
63 +
64 +/*
65 + * POSIX-lockless variants of our file_operations.
66 + *
67 + * These will be used if the underlying cluster stack does not support
68 + * posix file locking, if the user passes the "localflocks" mount
69 + * option, or if we have a local-only fs.
70 + *
71 + * ocfs2_flock is in here because all stacks handle UNIX file locks,
72 + * so we still want it in the case of no stack support for
73 + * plocks. Internally, it will do the right thing when asked to ignore
74 + * the cluster.
75 + */
76 +const struct file_operations ocfs2_fops_no_plocks = {
77 + .llseek = generic_file_llseek,
78 + .read = do_sync_read,
79 + .write = do_sync_write,
80 + .mmap = ocfs2_mmap,
81 + .fsync = ocfs2_sync_file,
82 + .release = ocfs2_file_release,
83 + .open = ocfs2_file_open,
84 + .aio_read = ocfs2_file_aio_read,
85 + .aio_write = ocfs2_file_aio_write,
86 + .unlocked_ioctl = ocfs2_ioctl,
87 +#ifdef CONFIG_COMPAT
88 + .compat_ioctl = ocfs2_compat_ioctl,
89 +#endif
90 + .flock = ocfs2_flock,
91 + .splice_read = ocfs2_file_splice_read,
92 + .splice_write = ocfs2_file_splice_write,
93 +};
94 +
95 +const struct file_operations ocfs2_dops_no_plocks = {
96 + .llseek = generic_file_llseek,
97 + .read = generic_read_dir,
98 + .readdir = ocfs2_readdir,
99 .fsync = ocfs2_sync_file,
100 .release = ocfs2_dir_release,
101 .open = ocfs2_dir_open,
102 --- a/fs/ocfs2/file.h
103 +++ b/fs/ocfs2/file.h
104 @@ -28,6 +28,8 @@
105
106 extern const struct file_operations ocfs2_fops;
107 extern const struct file_operations ocfs2_dops;
108 +extern const struct file_operations ocfs2_fops_no_plocks;
109 +extern const struct file_operations ocfs2_dops_no_plocks;
110 extern const struct inode_operations ocfs2_file_iops;
111 extern const struct inode_operations ocfs2_special_file_iops;
112 struct ocfs2_alloc_context;
113 --- a/fs/ocfs2/inode.c
114 +++ b/fs/ocfs2/inode.c
115 @@ -220,6 +220,7 @@ int ocfs2_populate_inode(struct inode *i
116 struct super_block *sb;
117 struct ocfs2_super *osb;
118 int status = -EINVAL;
119 + int use_plocks = 1;
120
121 mlog_entry("(0x%p, size:%llu)\n", inode,
122 (unsigned long long)le64_to_cpu(fe->i_size));
123 @@ -227,6 +228,10 @@ int ocfs2_populate_inode(struct inode *i
124 sb = inode->i_sb;
125 osb = OCFS2_SB(sb);
126
127 + if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
128 + ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
129 + use_plocks = 0;
130 +
131 /* this means that read_inode cannot create a superblock inode
132 * today. change if needed. */
133 if (!OCFS2_IS_VALID_DINODE(fe) ||
134 @@ -296,13 +301,19 @@ int ocfs2_populate_inode(struct inode *i
135
136 switch (inode->i_mode & S_IFMT) {
137 case S_IFREG:
138 - inode->i_fop = &ocfs2_fops;
139 + if (use_plocks)
140 + inode->i_fop = &ocfs2_fops;
141 + else
142 + inode->i_fop = &ocfs2_fops_no_plocks;
143 inode->i_op = &ocfs2_file_iops;
144 i_size_write(inode, le64_to_cpu(fe->i_size));
145 break;
146 case S_IFDIR:
147 inode->i_op = &ocfs2_dir_iops;
148 - inode->i_fop = &ocfs2_dops;
149 + if (use_plocks)
150 + inode->i_fop = &ocfs2_dops;
151 + else
152 + inode->i_fop = &ocfs2_dops_no_plocks;
153 i_size_write(inode, le64_to_cpu(fe->i_size));
154 break;
155 case S_IFLNK:
156 --- a/fs/ocfs2/locks.c
157 +++ b/fs/ocfs2/locks.c
158 @@ -24,6 +24,7 @@
159 */
160
161 #include <linux/fs.h>
162 +#include <linux/fcntl.h>
163
164 #define MLOG_MASK_PREFIX ML_INODE
165 #include <cluster/masklog.h>
166 @@ -32,6 +33,7 @@
167
168 #include "dlmglue.h"
169 #include "file.h"
170 +#include "inode.h"
171 #include "locks.h"
172
173 static int ocfs2_do_flock(struct file *file, struct inode *inode,
174 @@ -123,3 +125,16 @@ int ocfs2_flock(struct file *file, int c
175 else
176 return ocfs2_do_flock(file, inode, cmd, fl);
177 }
178 +
179 +int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
180 +{
181 + struct inode *inode = file->f_mapping->host;
182 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
183 +
184 + if (!(fl->fl_flags & FL_POSIX))
185 + return -ENOLCK;
186 + if (__mandatory_lock(inode))
187 + return -ENOLCK;
188 +
189 + return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
190 +}
191 --- a/fs/ocfs2/locks.h
192 +++ b/fs/ocfs2/locks.h
193 @@ -27,5 +27,6 @@
194 #define OCFS2_LOCKS_H
195
196 int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl);
197 +int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl);
198
199 #endif /* OCFS2_LOCKS_H */
200 --- a/fs/ocfs2/stack_user.c
201 +++ b/fs/ocfs2/stack_user.c
202 @@ -28,6 +28,7 @@
203 #include "ocfs2.h" /* For struct ocfs2_lock_res */
204 #include "stackglue.h"
205
206 +#include <linux/dlm_plock.h>
207
208 /*
209 * The control protocol starts with a handshake. Until the handshake
210 @@ -746,6 +747,37 @@ static void user_dlm_dump_lksb(union ocf
211 {
212 }
213
214 +static int user_plock(struct ocfs2_cluster_connection *conn,
215 + u64 ino,
216 + struct file *file,
217 + int cmd,
218 + struct file_lock *fl)
219 +{
220 + /*
221 + * This more or less just demuxes the plock request into any
222 + * one of three dlm calls.
223 + *
224 + * Internally, fs/dlm will pass these to a misc device, which
225 + * a userspace daemon will read and write to.
226 + *
227 + * For now, cancel requests (which happen internally only),
228 + * are turned into unlocks. Most of this function taken from
229 + * gfs2_lock.
230 + */
231 +
232 + if (cmd == F_CANCELLK) {
233 + cmd = F_SETLK;
234 + fl->fl_type = F_UNLCK;
235 + }
236 +
237 + if (IS_GETLK(cmd))
238 + return dlm_posix_get(conn->cc_lockspace, ino, file, fl);
239 + else if (fl->fl_type == F_UNLCK)
240 + return dlm_posix_unlock(conn->cc_lockspace, ino, file, fl);
241 + else
242 + return dlm_posix_lock(conn->cc_lockspace, ino, file, cmd, fl);
243 +}
244 +
245 /*
246 * Compare a requested locking protocol version against the current one.
247 *
248 @@ -839,6 +871,7 @@ static struct ocfs2_stack_operations ocf
249 .dlm_unlock = user_dlm_unlock,
250 .lock_status = user_dlm_lock_status,
251 .lock_lvb = user_dlm_lvb,
252 + .plock = user_plock,
253 .dump_lksb = user_dlm_dump_lksb,
254 };
255
256 --- a/fs/ocfs2/stackglue.c
257 +++ b/fs/ocfs2/stackglue.c
258 @@ -288,6 +288,26 @@ void ocfs2_dlm_dump_lksb(union ocfs2_dlm
259 }
260 EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
261
262 +int ocfs2_stack_supports_plocks(void)
263 +{
264 + return !!(active_stack && active_stack->sp_ops->plock);
265 +}
266 +EXPORT_SYMBOL_GPL(ocfs2_stack_supports_plocks);
267 +
268 +/*
269 + * ocfs2_plock() can only be safely called if
270 + * ocfs2_stack_supports_plocks() returned true
271 + */
272 +int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
273 + struct file *file, int cmd, struct file_lock *fl)
274 +{
275 + WARN_ON_ONCE(active_stack->sp_ops->plock == NULL);
276 + if (active_stack->sp_ops->plock)
277 + return active_stack->sp_ops->plock(conn, ino, file, cmd, fl);
278 + return -EOPNOTSUPP;
279 +}
280 +EXPORT_SYMBOL_GPL(ocfs2_plock);
281 +
282 int ocfs2_cluster_connect(const char *stack_name,
283 const char *group,
284 int grouplen,
285 --- a/fs/ocfs2/stackglue.h
286 +++ b/fs/ocfs2/stackglue.h
287 @@ -28,6 +28,10 @@
288 #include "dlm/dlmapi.h"
289 #include <linux/dlm.h>
290
291 +/* Needed for plock-related prototypes */
292 +struct file;
293 +struct file_lock;
294 +
295 /*
296 * dlmconstants.h does not have a LOCAL flag. We hope to remove it
297 * some day, but right now we need it. Let's fake it. This value is larger
298 @@ -187,6 +191,17 @@ struct ocfs2_stack_operations {
299 void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
300
301 /*
302 + * Cluster-aware posix locks
303 + *
304 + * This is NULL for stacks which do not support posix locks.
305 + */
306 + int (*plock)(struct ocfs2_cluster_connection *conn,
307 + u64 ino,
308 + struct file *file,
309 + int cmd,
310 + struct file_lock *fl);
311 +
312 + /*
313 * This is an optoinal debugging hook. If provided, the
314 * stack can dump debugging information about this lock.
315 */
316 @@ -240,6 +255,10 @@ int ocfs2_dlm_lock_status(union ocfs2_dl
317 void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
318 void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
319
320 +int ocfs2_stack_supports_plocks(void);
321 +int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
322 + struct file *file, int cmd, struct file_lock *fl);
323 +
324 void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
325
326