aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/stack_user.c216
-rw-r--r--fs/ocfs2/stackglue.c14
-rw-r--r--fs/ocfs2/stackglue.h19
3 files changed, 243 insertions, 6 deletions
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index de982c11e69b..7428663f9cbb 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -24,6 +24,7 @@
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <asm/uaccess.h> 25#include <asm/uaccess.h>
26 26
27#include "ocfs2.h" /* For struct ocfs2_lock_res */
27#include "stackglue.h" 28#include "stackglue.h"
28 29
29 30
@@ -152,6 +153,8 @@ union ocfs2_control_message {
152 struct ocfs2_control_message_down u_down; 153 struct ocfs2_control_message_down u_down;
153}; 154};
154 155
156static struct ocfs2_stack_plugin user_stack;
157
155static atomic_t ocfs2_control_opened; 158static atomic_t ocfs2_control_opened;
156static int ocfs2_control_this_node = -1; 159static int ocfs2_control_this_node = -1;
157static struct ocfs2_protocol_version running_proto; 160static struct ocfs2_protocol_version running_proto;
@@ -344,6 +347,20 @@ out_unlock:
344 return rc; 347 return rc;
345} 348}
346 349
350static 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
347static int ocfs2_control_do_setnode_msg(struct file *file, 364static int ocfs2_control_do_setnode_msg(struct file *file,
348 struct ocfs2_control_message_setn *msg) 365 struct ocfs2_control_message_setn *msg)
349{ 366{
@@ -652,13 +669,210 @@ static void ocfs2_control_exit(void)
652 -rc); 669 -rc);
653} 670}
654 671
672static 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
678static 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
701static 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
708static 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
729static 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
741static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
742{
743 return lksb->lksb_fsdlm.sb_status;
744}
745
746static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
747{
748 return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
749}
750
751static 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 */
763static 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
778static 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;
815out:
816 return rc;
817}
818
819static 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
829static 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
841static 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
852static struct ocfs2_stack_plugin user_stack = {
853 .sp_name = "user",
854 .sp_ops = &user_stack_ops,
855 .sp_owner = THIS_MODULE,
856};
857
858
655static int __init user_stack_init(void) 859static 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
660static void __exit user_stack_exit(void) 873static void __exit user_stack_exit(void)
661{ 874{
875 ocfs2_stack_glue_unregister(&user_stack);
662 ocfs2_control_exit(); 876 ocfs2_control_exit();
663} 877}
664 878
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index bf45d9bff8a7..119f60cea9cc 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -228,13 +228,20 @@ void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
228EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol); 228EXPORT_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 */
231int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, 238int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
232 int mode, 239 int mode,
233 union ocfs2_dlm_lksb *lksb, 240 union ocfs2_dlm_lksb *lksb,
234 u32 flags, 241 u32 flags,
235 void *name, 242 void *name,
236 unsigned int namelen, 243 unsigned int namelen,
237 void *astarg) 244 struct ocfs2_lock_res *astarg)
238{ 245{
239 BUG_ON(lproto == NULL); 246 BUG_ON(lproto == NULL);
240 247
@@ -246,7 +253,7 @@ EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
246int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, 253int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
247 union ocfs2_dlm_lksb *lksb, 254 union ocfs2_dlm_lksb *lksb,
248 u32 flags, 255 u32 flags,
249 void *astarg) 256 struct ocfs2_lock_res *astarg)
250{ 257{
251 BUG_ON(lproto == NULL); 258 BUG_ON(lproto == NULL);
252 259
@@ -360,7 +367,8 @@ void ocfs2_cluster_hangup(const char *group, int grouplen)
360 BUG_ON(group == NULL); 367 BUG_ON(group == NULL);
361 BUG_ON(group[grouplen] != '\0'); 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 /* cluster_disconnect() was called with hangup_pending==1 */ 373 /* cluster_disconnect() was called with hangup_pending==1 */
366 ocfs2_stack_driver_put(); 374 ocfs2_stack_driver_put();
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
index d88bc655644b..005e4f170e0f 100644
--- a/fs/ocfs2/stackglue.h
+++ b/fs/ocfs2/stackglue.h
@@ -26,6 +26,7 @@
26#include <linux/dlmconstants.h> 26#include <linux/dlmconstants.h>
27 27
28#include "dlm/dlmapi.h" 28#include "dlm/dlmapi.h"
29#include <linux/dlm.h>
29 30
30/* 31/*
31 * dlmconstants.h does not have a LOCAL flag. We hope to remove it 32 * dlmconstants.h does not have a LOCAL flag. We hope to remove it
@@ -60,6 +61,17 @@ struct ocfs2_locking_protocol {
60 void (*lp_unlock_ast)(void *astarg, int error); 61 void (*lp_unlock_ast)(void *astarg, int error);
61}; 62};
62 63
64
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 */
70struct fsdlm_lksb_plus_lvb {
71 struct dlm_lksb lksb;
72 char lvb[DLM_LVB_LEN];
73};
74
63/* 75/*
64 * A union of all lock status structures. We define it here so that the 76 * A union of all lock status structures. We define it here so that the
65 * size of the union is known. Lock status structures are embedded in 77 * size of the union is known. Lock status structures are embedded in
@@ -67,6 +79,8 @@ struct ocfs2_locking_protocol {
67 */ 79 */
68union ocfs2_dlm_lksb { 80union ocfs2_dlm_lksb {
69 struct dlm_lockstatus lksb_o2dlm; 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/*
@@ -221,17 +235,18 @@ int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
221void ocfs2_cluster_hangup(const char *group, int grouplen); 235void ocfs2_cluster_hangup(const char *group, int grouplen);
222int ocfs2_cluster_this_node(unsigned int *node); 236int ocfs2_cluster_this_node(unsigned int *node);
223 237
238struct ocfs2_lock_res;
224int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, 239int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
225 int mode, 240 int mode,
226 union ocfs2_dlm_lksb *lksb, 241 union ocfs2_dlm_lksb *lksb,
227 u32 flags, 242 u32 flags,
228 void *name, 243 void *name,
229 unsigned int namelen, 244 unsigned int namelen,
230 void *astarg); 245 struct ocfs2_lock_res *astarg);
231int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, 246int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
232 union ocfs2_dlm_lksb *lksb, 247 union ocfs2_dlm_lksb *lksb,
233 u32 flags, 248 u32 flags,
234 void *astarg); 249 struct ocfs2_lock_res *astarg);
235 250
236int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb); 251int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
237void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb); 252void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);