aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-07-21 17:29:16 -0400
committerMark Fasheh <mfasheh@suse.com>2008-10-13 16:57:57 -0400
commit53da4939f349d4edd283b043219221ca5b78e4d4 (patch)
tree3e0f8e1bd5474822431cffd1e449df9b639e1772
parenta447c0932445f92ce6f4c1bd020f62c5097a7842 (diff)
ocfs2: POSIX file locks support
This is actually pretty easy since fs/dlm already handles the bulk of the work. The Ocfs2 userspace cluster stack module already uses fs/dlm as the underlying lock manager, so I only had to add the right calls. Cluster-aware POSIX locks ("plocks") can be turned off by the same means at UNIX locks - mount with 'noflocks', or create a local-only Ocfs2 volume. Internally, the file system uses two sets of file_operations, depending on whether cluster aware plocks is required. This turns out to be easier than implementing local-only versions of ->lock. Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r--fs/ocfs2/file.c51
-rw-r--r--fs/ocfs2/file.h2
-rw-r--r--fs/ocfs2/inode.c15
-rw-r--r--fs/ocfs2/locks.c15
-rw-r--r--fs/ocfs2/locks.h1
-rw-r--r--fs/ocfs2/stack_user.c33
-rw-r--r--fs/ocfs2/stackglue.c20
-rw-r--r--fs/ocfs2/stackglue.h19
8 files changed, 154 insertions, 2 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ed38796052d2..1015ef16a8bf 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2237,6 +2237,10 @@ const struct inode_operations ocfs2_special_file_iops = {
2237 .permission = ocfs2_permission, 2237 .permission = ocfs2_permission,
2238}; 2238};
2239 2239
2240/*
2241 * Other than ->lock, keep ocfs2_fops and ocfs2_dops in sync with
2242 * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
2243 */
2240const struct file_operations ocfs2_fops = { 2244const struct file_operations ocfs2_fops = {
2241 .llseek = generic_file_llseek, 2245 .llseek = generic_file_llseek,
2242 .read = do_sync_read, 2246 .read = do_sync_read,
@@ -2251,6 +2255,7 @@ const struct file_operations ocfs2_fops = {
2251#ifdef CONFIG_COMPAT 2255#ifdef CONFIG_COMPAT
2252 .compat_ioctl = ocfs2_compat_ioctl, 2256 .compat_ioctl = ocfs2_compat_ioctl,
2253#endif 2257#endif
2258 .lock = ocfs2_lock,
2254 .flock = ocfs2_flock, 2259 .flock = ocfs2_flock,
2255 .splice_read = ocfs2_file_splice_read, 2260 .splice_read = ocfs2_file_splice_read,
2256 .splice_write = ocfs2_file_splice_write, 2261 .splice_write = ocfs2_file_splice_write,
@@ -2267,5 +2272,51 @@ const struct file_operations ocfs2_dops = {
2267#ifdef CONFIG_COMPAT 2272#ifdef CONFIG_COMPAT
2268 .compat_ioctl = ocfs2_compat_ioctl, 2273 .compat_ioctl = ocfs2_compat_ioctl,
2269#endif 2274#endif
2275 .lock = ocfs2_lock,
2276 .flock = ocfs2_flock,
2277};
2278
2279/*
2280 * POSIX-lockless variants of our file_operations.
2281 *
2282 * These will be used if the underlying cluster stack does not support
2283 * posix file locking, if the user passes the "localflocks" mount
2284 * option, or if we have a local-only fs.
2285 *
2286 * ocfs2_flock is in here because all stacks handle UNIX file locks,
2287 * so we still want it in the case of no stack support for
2288 * plocks. Internally, it will do the right thing when asked to ignore
2289 * the cluster.
2290 */
2291const struct file_operations ocfs2_fops_no_plocks = {
2292 .llseek = generic_file_llseek,
2293 .read = do_sync_read,
2294 .write = do_sync_write,
2295 .mmap = ocfs2_mmap,
2296 .fsync = ocfs2_sync_file,
2297 .release = ocfs2_file_release,
2298 .open = ocfs2_file_open,
2299 .aio_read = ocfs2_file_aio_read,
2300 .aio_write = ocfs2_file_aio_write,
2301 .unlocked_ioctl = ocfs2_ioctl,
2302#ifdef CONFIG_COMPAT
2303 .compat_ioctl = ocfs2_compat_ioctl,
2304#endif
2305 .flock = ocfs2_flock,
2306 .splice_read = ocfs2_file_splice_read,
2307 .splice_write = ocfs2_file_splice_write,
2308};
2309
2310const struct file_operations ocfs2_dops_no_plocks = {
2311 .llseek = generic_file_llseek,
2312 .read = generic_read_dir,
2313 .readdir = ocfs2_readdir,
2314 .fsync = ocfs2_sync_file,
2315 .release = ocfs2_dir_release,
2316 .open = ocfs2_dir_open,
2317 .unlocked_ioctl = ocfs2_ioctl,
2318#ifdef CONFIG_COMPAT
2319 .compat_ioctl = ocfs2_compat_ioctl,
2320#endif
2270 .flock = ocfs2_flock, 2321 .flock = ocfs2_flock,
2271}; 2322};
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 1e27b4d017ea..5a6d3e48e4ba 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -28,6 +28,8 @@
28 28
29extern const struct file_operations ocfs2_fops; 29extern const struct file_operations ocfs2_fops;
30extern const struct file_operations ocfs2_dops; 30extern const struct file_operations ocfs2_dops;
31extern const struct file_operations ocfs2_fops_no_plocks;
32extern const struct file_operations ocfs2_dops_no_plocks;
31extern const struct inode_operations ocfs2_file_iops; 33extern const struct inode_operations ocfs2_file_iops;
32extern const struct inode_operations ocfs2_special_file_iops; 34extern const struct inode_operations ocfs2_special_file_iops;
33struct ocfs2_alloc_context; 35struct ocfs2_alloc_context;
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 7e9e4c79aec7..99f012a0f207 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -219,6 +219,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
219 struct super_block *sb; 219 struct super_block *sb;
220 struct ocfs2_super *osb; 220 struct ocfs2_super *osb;
221 int status = -EINVAL; 221 int status = -EINVAL;
222 int use_plocks = 1;
222 223
223 mlog_entry("(0x%p, size:%llu)\n", inode, 224 mlog_entry("(0x%p, size:%llu)\n", inode,
224 (unsigned long long)le64_to_cpu(fe->i_size)); 225 (unsigned long long)le64_to_cpu(fe->i_size));
@@ -226,6 +227,10 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
226 sb = inode->i_sb; 227 sb = inode->i_sb;
227 osb = OCFS2_SB(sb); 228 osb = OCFS2_SB(sb);
228 229
230 if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
231 ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
232 use_plocks = 0;
233
229 /* this means that read_inode cannot create a superblock inode 234 /* this means that read_inode cannot create a superblock inode
230 * today. change if needed. */ 235 * today. change if needed. */
231 if (!OCFS2_IS_VALID_DINODE(fe) || 236 if (!OCFS2_IS_VALID_DINODE(fe) ||
@@ -295,13 +300,19 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
295 300
296 switch (inode->i_mode & S_IFMT) { 301 switch (inode->i_mode & S_IFMT) {
297 case S_IFREG: 302 case S_IFREG:
298 inode->i_fop = &ocfs2_fops; 303 if (use_plocks)
304 inode->i_fop = &ocfs2_fops;
305 else
306 inode->i_fop = &ocfs2_fops_no_plocks;
299 inode->i_op = &ocfs2_file_iops; 307 inode->i_op = &ocfs2_file_iops;
300 i_size_write(inode, le64_to_cpu(fe->i_size)); 308 i_size_write(inode, le64_to_cpu(fe->i_size));
301 break; 309 break;
302 case S_IFDIR: 310 case S_IFDIR:
303 inode->i_op = &ocfs2_dir_iops; 311 inode->i_op = &ocfs2_dir_iops;
304 inode->i_fop = &ocfs2_dops; 312 if (use_plocks)
313 inode->i_fop = &ocfs2_dops;
314 else
315 inode->i_fop = &ocfs2_dops_no_plocks;
305 i_size_write(inode, le64_to_cpu(fe->i_size)); 316 i_size_write(inode, le64_to_cpu(fe->i_size));
306 break; 317 break;
307 case S_IFLNK: 318 case S_IFLNK:
diff --git a/fs/ocfs2/locks.c b/fs/ocfs2/locks.c
index 203f87143877..544ac6245175 100644
--- a/fs/ocfs2/locks.c
+++ b/fs/ocfs2/locks.c
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/fcntl.h>
27 28
28#define MLOG_MASK_PREFIX ML_INODE 29#define MLOG_MASK_PREFIX ML_INODE
29#include <cluster/masklog.h> 30#include <cluster/masklog.h>
@@ -32,6 +33,7 @@
32 33
33#include "dlmglue.h" 34#include "dlmglue.h"
34#include "file.h" 35#include "file.h"
36#include "inode.h"
35#include "locks.h" 37#include "locks.h"
36 38
37static int ocfs2_do_flock(struct file *file, struct inode *inode, 39static int ocfs2_do_flock(struct file *file, struct inode *inode,
@@ -123,3 +125,16 @@ int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl)
123 else 125 else
124 return ocfs2_do_flock(file, inode, cmd, fl); 126 return ocfs2_do_flock(file, inode, cmd, fl);
125} 127}
128
129int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
130{
131 struct inode *inode = file->f_mapping->host;
132 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
133
134 if (!(fl->fl_flags & FL_POSIX))
135 return -ENOLCK;
136 if (__mandatory_lock(inode))
137 return -ENOLCK;
138
139 return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
140}
diff --git a/fs/ocfs2/locks.h b/fs/ocfs2/locks.h
index 9743ef2324ec..496d488b271f 100644
--- a/fs/ocfs2/locks.h
+++ b/fs/ocfs2/locks.h
@@ -27,5 +27,6 @@
27#define OCFS2_LOCKS_H 27#define OCFS2_LOCKS_H
28 28
29int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl); 29int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl);
30int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl);
30 31
31#endif /* OCFS2_LOCKS_H */ 32#endif /* OCFS2_LOCKS_H */
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index 353fc35c6748..faec2d879357 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -28,6 +28,7 @@
28#include "ocfs2.h" /* For struct ocfs2_lock_res */ 28#include "ocfs2.h" /* For struct ocfs2_lock_res */
29#include "stackglue.h" 29#include "stackglue.h"
30 30
31#include <linux/dlm_plock.h>
31 32
32/* 33/*
33 * The control protocol starts with a handshake. Until the handshake 34 * The control protocol starts with a handshake. Until the handshake
@@ -746,6 +747,37 @@ static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
746{ 747{
747} 748}
748 749
750static int user_plock(struct ocfs2_cluster_connection *conn,
751 u64 ino,
752 struct file *file,
753 int cmd,
754 struct file_lock *fl)
755{
756 /*
757 * This more or less just demuxes the plock request into any
758 * one of three dlm calls.
759 *
760 * Internally, fs/dlm will pass these to a misc device, which
761 * a userspace daemon will read and write to.
762 *
763 * For now, cancel requests (which happen internally only),
764 * are turned into unlocks. Most of this function taken from
765 * gfs2_lock.
766 */
767
768 if (cmd == F_CANCELLK) {
769 cmd = F_SETLK;
770 fl->fl_type = F_UNLCK;
771 }
772
773 if (IS_GETLK(cmd))
774 return dlm_posix_get(conn->cc_lockspace, ino, file, fl);
775 else if (fl->fl_type == F_UNLCK)
776 return dlm_posix_unlock(conn->cc_lockspace, ino, file, fl);
777 else
778 return dlm_posix_lock(conn->cc_lockspace, ino, file, cmd, fl);
779}
780
749/* 781/*
750 * Compare a requested locking protocol version against the current one. 782 * Compare a requested locking protocol version against the current one.
751 * 783 *
@@ -839,6 +871,7 @@ static struct ocfs2_stack_operations ocfs2_user_plugin_ops = {
839 .dlm_unlock = user_dlm_unlock, 871 .dlm_unlock = user_dlm_unlock,
840 .lock_status = user_dlm_lock_status, 872 .lock_status = user_dlm_lock_status,
841 .lock_lvb = user_dlm_lvb, 873 .lock_lvb = user_dlm_lvb,
874 .plock = user_plock,
842 .dump_lksb = user_dlm_dump_lksb, 875 .dump_lksb = user_dlm_dump_lksb,
843}; 876};
844 877
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 07f348b8d721..7150f5dce957 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -288,6 +288,26 @@ void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
288} 288}
289EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb); 289EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
290 290
291int ocfs2_stack_supports_plocks(void)
292{
293 return !!(active_stack && active_stack->sp_ops->plock);
294}
295EXPORT_SYMBOL_GPL(ocfs2_stack_supports_plocks);
296
297/*
298 * ocfs2_plock() can only be safely called if
299 * ocfs2_stack_supports_plocks() returned true
300 */
301int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
302 struct file *file, int cmd, struct file_lock *fl)
303{
304 WARN_ON_ONCE(active_stack->sp_ops->plock == NULL);
305 if (active_stack->sp_ops->plock)
306 return active_stack->sp_ops->plock(conn, ino, file, cmd, fl);
307 return -EOPNOTSUPP;
308}
309EXPORT_SYMBOL_GPL(ocfs2_plock);
310
291int ocfs2_cluster_connect(const char *stack_name, 311int ocfs2_cluster_connect(const char *stack_name,
292 const char *group, 312 const char *group,
293 int grouplen, 313 int grouplen,
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
index db56281dd1be..c571af375ef8 100644
--- a/fs/ocfs2/stackglue.h
+++ b/fs/ocfs2/stackglue.h
@@ -28,6 +28,10 @@
28#include "dlm/dlmapi.h" 28#include "dlm/dlmapi.h"
29#include <linux/dlm.h> 29#include <linux/dlm.h>
30 30
31/* Needed for plock-related prototypes */
32struct file;
33struct file_lock;
34
31/* 35/*
32 * dlmconstants.h does not have a LOCAL flag. We hope to remove it 36 * dlmconstants.h does not have a LOCAL flag. We hope to remove it
33 * some day, but right now we need it. Let's fake it. This value is larger 37 * some day, but right now we need it. Let's fake it. This value is larger
@@ -187,6 +191,17 @@ struct ocfs2_stack_operations {
187 void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb); 191 void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
188 192
189 /* 193 /*
194 * Cluster-aware posix locks
195 *
196 * This is NULL for stacks which do not support posix locks.
197 */
198 int (*plock)(struct ocfs2_cluster_connection *conn,
199 u64 ino,
200 struct file *file,
201 int cmd,
202 struct file_lock *fl);
203
204 /*
190 * This is an optoinal debugging hook. If provided, the 205 * This is an optoinal debugging hook. If provided, the
191 * stack can dump debugging information about this lock. 206 * stack can dump debugging information about this lock.
192 */ 207 */
@@ -240,6 +255,10 @@ int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
240void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb); 255void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
241void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb); 256void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
242 257
258int ocfs2_stack_supports_plocks(void);
259int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
260 struct file *file, int cmd, struct file_lock *fl);
261
243void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto); 262void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
244 263
245 264