Commit cf4d8d75d8aba537a19b313a9364fd08ddbd5622

Authored by David Teigland
Committed by Mark Fasheh
1 parent d4b95eef4d

ocfs2: add fsdlm to stackglue

Add code to use fs/dlm.

[ Modified to be part of the stack_user module -- Joel ]

Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>

Showing 3 changed files with 243 additions and 6 deletions Side-by-side Diff

fs/ocfs2/stack_user.c
... ... @@ -24,6 +24,7 @@
24 24 #include <linux/reboot.h>
25 25 #include <asm/uaccess.h>
26 26  
  27 +#include "ocfs2.h" /* For struct ocfs2_lock_res */
27 28 #include "stackglue.h"
28 29  
29 30  
... ... @@ -152,6 +153,8 @@
152 153 struct ocfs2_control_message_down u_down;
153 154 };
154 155  
  156 +static struct ocfs2_stack_plugin user_stack;
  157 +
155 158 static atomic_t ocfs2_control_opened;
156 159 static int ocfs2_control_this_node = -1;
157 160 static struct ocfs2_protocol_version running_proto;
... ... @@ -344,6 +347,20 @@
344 347 return rc;
345 348 }
346 349  
  350 +static int ocfs2_control_get_this_node(void)
  351 +{
  352 + int rc;
  353 +
  354 + mutex_lock(&ocfs2_control_lock);
  355 + if (ocfs2_control_this_node < 0)
  356 + rc = -EINVAL;
  357 + else
  358 + rc = ocfs2_control_this_node;
  359 + mutex_unlock(&ocfs2_control_lock);
  360 +
  361 + return rc;
  362 +}
  363 +
347 364 static int ocfs2_control_do_setnode_msg(struct file *file,
348 365 struct ocfs2_control_message_setn *msg)
349 366 {
350 367  
351 368  
... ... @@ -652,13 +669,210 @@
652 669 -rc);
653 670 }
654 671  
  672 +static struct dlm_lksb *fsdlm_astarg_to_lksb(void *astarg)
  673 +{
  674 + struct ocfs2_lock_res *res = astarg;
  675 + return &res->l_lksb.lksb_fsdlm;
  676 +}
  677 +
  678 +static void fsdlm_lock_ast_wrapper(void *astarg)
  679 +{
  680 + struct dlm_lksb *lksb = fsdlm_astarg_to_lksb(astarg);
  681 + int status = lksb->sb_status;
  682 +
  683 + BUG_ON(user_stack.sp_proto == NULL);
  684 +
  685 + /*
  686 + * For now we're punting on the issue of other non-standard errors
  687 + * where we can't tell if the unlock_ast or lock_ast should be called.
  688 + * The main "other error" that's possible is EINVAL which means the
  689 + * function was called with invalid args, which shouldn't be possible
  690 + * since the caller here is under our control. Other non-standard
  691 + * errors probably fall into the same category, or otherwise are fatal
  692 + * which means we can't carry on anyway.
  693 + */
  694 +
  695 + if (status == -DLM_EUNLOCK || status == -DLM_ECANCEL)
  696 + user_stack.sp_proto->lp_unlock_ast(astarg, 0);
  697 + else
  698 + user_stack.sp_proto->lp_lock_ast(astarg);
  699 +}
  700 +
  701 +static void fsdlm_blocking_ast_wrapper(void *astarg, int level)
  702 +{
  703 + BUG_ON(user_stack.sp_proto == NULL);
  704 +
  705 + user_stack.sp_proto->lp_blocking_ast(astarg, level);
  706 +}
  707 +
  708 +static int user_dlm_lock(struct ocfs2_cluster_connection *conn,
  709 + int mode,
  710 + union ocfs2_dlm_lksb *lksb,
  711 + u32 flags,
  712 + void *name,
  713 + unsigned int namelen,
  714 + void *astarg)
  715 +{
  716 + int ret;
  717 +
  718 + if (!lksb->lksb_fsdlm.sb_lvbptr)
  719 + lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
  720 + sizeof(struct dlm_lksb);
  721 +
  722 + ret = dlm_lock(conn->cc_lockspace, mode, &lksb->lksb_fsdlm,
  723 + flags|DLM_LKF_NODLCKWT, name, namelen, 0,
  724 + fsdlm_lock_ast_wrapper, astarg,
  725 + fsdlm_blocking_ast_wrapper);
  726 + return ret;
  727 +}
  728 +
  729 +static int user_dlm_unlock(struct ocfs2_cluster_connection *conn,
  730 + union ocfs2_dlm_lksb *lksb,
  731 + u32 flags,
  732 + void *astarg)
  733 +{
  734 + int ret;
  735 +
  736 + ret = dlm_unlock(conn->cc_lockspace, lksb->lksb_fsdlm.sb_lkid,
  737 + flags, &lksb->lksb_fsdlm, astarg);
  738 + return ret;
  739 +}
  740 +
  741 +static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
  742 +{
  743 + return lksb->lksb_fsdlm.sb_status;
  744 +}
  745 +
  746 +static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
  747 +{
  748 + return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
  749 +}
  750 +
  751 +static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
  752 +{
  753 +}
  754 +
  755 +/*
  756 + * Compare a requested locking protocol version against the current one.
  757 + *
  758 + * If the major numbers are different, they are incompatible.
  759 + * If the current minor is greater than the request, they are incompatible.
  760 + * If the current minor is less than or equal to the request, they are
  761 + * compatible, and the requester should run at the current minor version.
  762 + */
  763 +static int fs_protocol_compare(struct ocfs2_protocol_version *existing,
  764 + struct ocfs2_protocol_version *request)
  765 +{
  766 + if (existing->pv_major != request->pv_major)
  767 + return 1;
  768 +
  769 + if (existing->pv_minor > request->pv_minor)
  770 + return 1;
  771 +
  772 + if (existing->pv_minor < request->pv_minor)
  773 + request->pv_minor = existing->pv_minor;
  774 +
  775 + return 0;
  776 +}
  777 +
  778 +static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
  779 +{
  780 + dlm_lockspace_t *fsdlm;
  781 + struct ocfs2_live_connection *control;
  782 + int rc = 0;
  783 +
  784 + BUG_ON(conn == NULL);
  785 +
  786 + rc = ocfs2_live_connection_new(conn, &control);
  787 + if (rc)
  788 + goto out;
  789 +
  790 + /*
  791 + * running_proto must have been set before we allowed any mounts
  792 + * to proceed.
  793 + */
  794 + if (fs_protocol_compare(&running_proto, &conn->cc_version)) {
  795 + printk(KERN_ERR
  796 + "Unable to mount with fs locking protocol version "
  797 + "%u.%u because the userspace control daemon has "
  798 + "negotiated %u.%u\n",
  799 + conn->cc_version.pv_major, conn->cc_version.pv_minor,
  800 + running_proto.pv_major, running_proto.pv_minor);
  801 + rc = -EPROTO;
  802 + ocfs2_live_connection_drop(control);
  803 + goto out;
  804 + }
  805 +
  806 + rc = dlm_new_lockspace(conn->cc_name, strlen(conn->cc_name),
  807 + &fsdlm, DLM_LSFL_FS, DLM_LVB_LEN);
  808 + if (rc) {
  809 + ocfs2_live_connection_drop(control);
  810 + goto out;
  811 + }
  812 +
  813 + conn->cc_private = control;
  814 + conn->cc_lockspace = fsdlm;
  815 +out:
  816 + return rc;
  817 +}
  818 +
  819 +static int user_cluster_disconnect(struct ocfs2_cluster_connection *conn,
  820 + int hangup_pending)
  821 +{
  822 + dlm_release_lockspace(conn->cc_lockspace, 2);
  823 + conn->cc_lockspace = NULL;
  824 + ocfs2_live_connection_drop(conn->cc_private);
  825 + conn->cc_private = NULL;
  826 + return 0;
  827 +}
  828 +
  829 +static int user_cluster_this_node(unsigned int *this_node)
  830 +{
  831 + int rc;
  832 +
  833 + rc = ocfs2_control_get_this_node();
  834 + if (rc < 0)
  835 + return rc;
  836 +
  837 + *this_node = rc;
  838 + return 0;
  839 +}
  840 +
  841 +static struct ocfs2_stack_operations user_stack_ops = {
  842 + .connect = user_cluster_connect,
  843 + .disconnect = user_cluster_disconnect,
  844 + .this_node = user_cluster_this_node,
  845 + .dlm_lock = user_dlm_lock,
  846 + .dlm_unlock = user_dlm_unlock,
  847 + .lock_status = user_dlm_lock_status,
  848 + .lock_lvb = user_dlm_lvb,
  849 + .dump_lksb = user_dlm_dump_lksb,
  850 +};
  851 +
  852 +static struct ocfs2_stack_plugin user_stack = {
  853 + .sp_name = "user",
  854 + .sp_ops = &user_stack_ops,
  855 + .sp_owner = THIS_MODULE,
  856 +};
  857 +
  858 +
655 859 static int __init user_stack_init(void)
656 860 {
657   - return ocfs2_control_init();
  861 + int rc;
  862 +
  863 + rc = ocfs2_control_init();
  864 + if (!rc) {
  865 + rc = ocfs2_stack_glue_register(&user_stack);
  866 + if (rc)
  867 + ocfs2_control_exit();
  868 + }
  869 +
  870 + return rc;
658 871 }
659 872  
660 873 static void __exit user_stack_exit(void)
661 874 {
  875 + ocfs2_stack_glue_unregister(&user_stack);
662 876 ocfs2_control_exit();
663 877 }
664 878  
fs/ocfs2/stackglue.c
... ... @@ -228,13 +228,20 @@
228 228 EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
229 229  
230 230  
  231 +/*
  232 + * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take
  233 + * "struct ocfs2_lock_res *astarg" instead of "void *astarg" because the
  234 + * underlying stack plugins need to pilfer the lksb off of the lock_res.
  235 + * If some other structure needs to be passed as an astarg, the plugins
  236 + * will need to be given a different avenue to the lksb.
  237 + */
231 238 int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
232 239 int mode,
233 240 union ocfs2_dlm_lksb *lksb,
234 241 u32 flags,
235 242 void *name,
236 243 unsigned int namelen,
237   - void *astarg)
  244 + struct ocfs2_lock_res *astarg)
238 245 {
239 246 BUG_ON(lproto == NULL);
240 247  
... ... @@ -246,7 +253,7 @@
246 253 int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
247 254 union ocfs2_dlm_lksb *lksb,
248 255 u32 flags,
249   - void *astarg)
  256 + struct ocfs2_lock_res *astarg)
250 257 {
251 258 BUG_ON(lproto == NULL);
252 259  
... ... @@ -360,7 +367,8 @@
360 367 BUG_ON(group == NULL);
361 368 BUG_ON(group[grouplen] != '\0');
362 369  
363   - active_stack->sp_ops->hangup(group, grouplen);
  370 + if (active_stack->sp_ops->hangup)
  371 + active_stack->sp_ops->hangup(group, grouplen);
364 372  
365 373 /* cluster_disconnect() was called with hangup_pending==1 */
366 374 ocfs2_stack_driver_put();
fs/ocfs2/stackglue.h
... ... @@ -26,6 +26,7 @@
26 26 #include <linux/dlmconstants.h>
27 27  
28 28 #include "dlm/dlmapi.h"
  29 +#include <linux/dlm.h>
29 30  
30 31 /*
31 32 * dlmconstants.h does not have a LOCAL flag. We hope to remove it
32 33  
33 34  
... ... @@ -60,13 +61,26 @@
60 61 void (*lp_unlock_ast)(void *astarg, int error);
61 62 };
62 63  
  64 +
63 65 /*
  66 + * The dlm_lockstatus struct includes lvb space, but the dlm_lksb struct only
  67 + * has a pointer to separately allocated lvb space. This struct exists only to
  68 + * include in the lksb union to make space for a combined dlm_lksb and lvb.
  69 + */
  70 +struct fsdlm_lksb_plus_lvb {
  71 + struct dlm_lksb lksb;
  72 + char lvb[DLM_LVB_LEN];
  73 +};
  74 +
  75 +/*
64 76 * A union of all lock status structures. We define it here so that the
65 77 * size of the union is known. Lock status structures are embedded in
66 78 * ocfs2 inodes.
67 79 */
68 80 union ocfs2_dlm_lksb {
69 81 struct dlm_lockstatus lksb_o2dlm;
  82 + struct dlm_lksb lksb_fsdlm;
  83 + struct fsdlm_lksb_plus_lvb padding;
70 84 };
71 85  
72 86 /*
73 87  
74 88  
... ... @@ -221,17 +235,18 @@
221 235 void ocfs2_cluster_hangup(const char *group, int grouplen);
222 236 int ocfs2_cluster_this_node(unsigned int *node);
223 237  
  238 +struct ocfs2_lock_res;
224 239 int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
225 240 int mode,
226 241 union ocfs2_dlm_lksb *lksb,
227 242 u32 flags,
228 243 void *name,
229 244 unsigned int namelen,
230   - void *astarg);
  245 + struct ocfs2_lock_res *astarg);
231 246 int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
232 247 union ocfs2_dlm_lksb *lksb,
233 248 u32 flags,
234   - void *astarg);
  249 + struct ocfs2_lock_res *astarg);
235 250  
236 251 int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
237 252 void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);