Commit cf4d8d75d8aba537a19b313a9364fd08ddbd5622
Committed by
Mark Fasheh
1 parent
d4b95eef4d
Exists in
master
and in
7 other branches
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); |