diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-02-12 17:56:25 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2008-03-10 18:13:54 -0400 |
commit | 0f71b7b40f55de909e40fa5ab217a5da3439c7d8 (patch) | |
tree | 3afad178b200b0a16e10ccaca2b05da1197034d4 /fs | |
parent | 2af37ce82d199d1d8cd6286f42f37d321627a807 (diff) |
ocfs2: Fix endian bug in o2dlm protocol negotiation.
struct dlm_query_join_packet is made up of four one-byte fields. They
are effectively in big-endian order already. However, little-endian
machines swap them before putting the packet on the wire (because
query_join's response is a status, and that status is treated as a u32
on the wire). Thus, a big-endian and little-endian machines will
treat this structure differently.
The solution is to have little-endian machines swap the structure when
converting from the structure to the u32 representation.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/dlm/dlmcommon.h | 20 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 101 |
2 files changed, 76 insertions, 45 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 9843ee17ea27..1f939631ab74 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h | |||
@@ -602,17 +602,19 @@ enum dlm_query_join_response_code { | |||
602 | JOIN_PROTOCOL_MISMATCH, | 602 | JOIN_PROTOCOL_MISMATCH, |
603 | }; | 603 | }; |
604 | 604 | ||
605 | struct dlm_query_join_packet { | ||
606 | u8 code; /* Response code. dlm_minor and fs_minor | ||
607 | are only valid if this is JOIN_OK */ | ||
608 | u8 dlm_minor; /* The minor version of the protocol the | ||
609 | dlm is speaking. */ | ||
610 | u8 fs_minor; /* The minor version of the protocol the | ||
611 | filesystem is speaking. */ | ||
612 | u8 reserved; | ||
613 | }; | ||
614 | |||
605 | union dlm_query_join_response { | 615 | union dlm_query_join_response { |
606 | u32 intval; | 616 | u32 intval; |
607 | struct { | 617 | struct dlm_query_join_packet packet; |
608 | u8 code; /* Response code. dlm_minor and fs_minor | ||
609 | are only valid if this is JOIN_OK */ | ||
610 | u8 dlm_minor; /* The minor version of the protocol the | ||
611 | dlm is speaking. */ | ||
612 | u8 fs_minor; /* The minor version of the protocol the | ||
613 | filesystem is speaking. */ | ||
614 | u8 reserved; | ||
615 | } packet; | ||
616 | }; | 618 | }; |
617 | 619 | ||
618 | struct dlm_lock_request | 620 | struct dlm_lock_request |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 906974cfbf18..0879d86113e3 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -713,14 +713,46 @@ static int dlm_query_join_proto_check(char *proto_type, int node, | |||
713 | return rc; | 713 | return rc; |
714 | } | 714 | } |
715 | 715 | ||
716 | /* | ||
717 | * struct dlm_query_join_packet is made up of four one-byte fields. They | ||
718 | * are effectively in big-endian order already. However, little-endian | ||
719 | * machines swap them before putting the packet on the wire (because | ||
720 | * query_join's response is a status, and that status is treated as a u32 | ||
721 | * on the wire). Thus, a big-endian and little-endian machines will treat | ||
722 | * this structure differently. | ||
723 | * | ||
724 | * The solution is to have little-endian machines swap the structure when | ||
725 | * converting from the structure to the u32 representation. This will | ||
726 | * result in the structure having the correct format on the wire no matter | ||
727 | * the host endian format. | ||
728 | */ | ||
729 | static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet, | ||
730 | u32 *wire) | ||
731 | { | ||
732 | union dlm_query_join_response response; | ||
733 | |||
734 | response.packet = *packet; | ||
735 | *wire = cpu_to_be32(response.intval); | ||
736 | } | ||
737 | |||
738 | static void dlm_query_join_wire_to_packet(u32 wire, | ||
739 | struct dlm_query_join_packet *packet) | ||
740 | { | ||
741 | union dlm_query_join_response response; | ||
742 | |||
743 | response.intval = cpu_to_be32(wire); | ||
744 | *packet = response.packet; | ||
745 | } | ||
746 | |||
716 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | 747 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, |
717 | void **ret_data) | 748 | void **ret_data) |
718 | { | 749 | { |
719 | struct dlm_query_join_request *query; | 750 | struct dlm_query_join_request *query; |
720 | union dlm_query_join_response response = { | 751 | struct dlm_query_join_packet packet = { |
721 | .packet.code = JOIN_DISALLOW, | 752 | .code = JOIN_DISALLOW, |
722 | }; | 753 | }; |
723 | struct dlm_ctxt *dlm = NULL; | 754 | struct dlm_ctxt *dlm = NULL; |
755 | u32 response; | ||
724 | u8 nodenum; | 756 | u8 nodenum; |
725 | 757 | ||
726 | query = (struct dlm_query_join_request *) msg->buf; | 758 | query = (struct dlm_query_join_request *) msg->buf; |
@@ -737,11 +769,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
737 | mlog(0, "node %u is not in our live map yet\n", | 769 | mlog(0, "node %u is not in our live map yet\n", |
738 | query->node_idx); | 770 | query->node_idx); |
739 | 771 | ||
740 | response.packet.code = JOIN_DISALLOW; | 772 | packet.code = JOIN_DISALLOW; |
741 | goto respond; | 773 | goto respond; |
742 | } | 774 | } |
743 | 775 | ||
744 | response.packet.code = JOIN_OK_NO_MAP; | 776 | packet.code = JOIN_OK_NO_MAP; |
745 | 777 | ||
746 | spin_lock(&dlm_domain_lock); | 778 | spin_lock(&dlm_domain_lock); |
747 | dlm = __dlm_lookup_domain_full(query->domain, query->name_len); | 779 | dlm = __dlm_lookup_domain_full(query->domain, query->name_len); |
@@ -760,7 +792,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
760 | mlog(0, "disallow join as node %u does not " | 792 | mlog(0, "disallow join as node %u does not " |
761 | "have node %u in its nodemap\n", | 793 | "have node %u in its nodemap\n", |
762 | query->node_idx, nodenum); | 794 | query->node_idx, nodenum); |
763 | response.packet.code = JOIN_DISALLOW; | 795 | packet.code = JOIN_DISALLOW; |
764 | goto unlock_respond; | 796 | goto unlock_respond; |
765 | } | 797 | } |
766 | } | 798 | } |
@@ -780,23 +812,23 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
780 | /*If this is a brand new context and we | 812 | /*If this is a brand new context and we |
781 | * haven't started our join process yet, then | 813 | * haven't started our join process yet, then |
782 | * the other node won the race. */ | 814 | * the other node won the race. */ |
783 | response.packet.code = JOIN_OK_NO_MAP; | 815 | packet.code = JOIN_OK_NO_MAP; |
784 | } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { | 816 | } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { |
785 | /* Disallow parallel joins. */ | 817 | /* Disallow parallel joins. */ |
786 | response.packet.code = JOIN_DISALLOW; | 818 | packet.code = JOIN_DISALLOW; |
787 | } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { | 819 | } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { |
788 | mlog(0, "node %u trying to join, but recovery " | 820 | mlog(0, "node %u trying to join, but recovery " |
789 | "is ongoing.\n", bit); | 821 | "is ongoing.\n", bit); |
790 | response.packet.code = JOIN_DISALLOW; | 822 | packet.code = JOIN_DISALLOW; |
791 | } else if (test_bit(bit, dlm->recovery_map)) { | 823 | } else if (test_bit(bit, dlm->recovery_map)) { |
792 | mlog(0, "node %u trying to join, but it " | 824 | mlog(0, "node %u trying to join, but it " |
793 | "still needs recovery.\n", bit); | 825 | "still needs recovery.\n", bit); |
794 | response.packet.code = JOIN_DISALLOW; | 826 | packet.code = JOIN_DISALLOW; |
795 | } else if (test_bit(bit, dlm->domain_map)) { | 827 | } else if (test_bit(bit, dlm->domain_map)) { |
796 | mlog(0, "node %u trying to join, but it " | 828 | mlog(0, "node %u trying to join, but it " |
797 | "is still in the domain! needs recovery?\n", | 829 | "is still in the domain! needs recovery?\n", |
798 | bit); | 830 | bit); |
799 | response.packet.code = JOIN_DISALLOW; | 831 | packet.code = JOIN_DISALLOW; |
800 | } else { | 832 | } else { |
801 | /* Alright we're fully a part of this domain | 833 | /* Alright we're fully a part of this domain |
802 | * so we keep some state as to who's joining | 834 | * so we keep some state as to who's joining |
@@ -807,19 +839,15 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
807 | if (dlm_query_join_proto_check("DLM", bit, | 839 | if (dlm_query_join_proto_check("DLM", bit, |
808 | &dlm->dlm_locking_proto, | 840 | &dlm->dlm_locking_proto, |
809 | &query->dlm_proto)) { | 841 | &query->dlm_proto)) { |
810 | response.packet.code = | 842 | packet.code = JOIN_PROTOCOL_MISMATCH; |
811 | JOIN_PROTOCOL_MISMATCH; | ||
812 | } else if (dlm_query_join_proto_check("fs", bit, | 843 | } else if (dlm_query_join_proto_check("fs", bit, |
813 | &dlm->fs_locking_proto, | 844 | &dlm->fs_locking_proto, |
814 | &query->fs_proto)) { | 845 | &query->fs_proto)) { |
815 | response.packet.code = | 846 | packet.code = JOIN_PROTOCOL_MISMATCH; |
816 | JOIN_PROTOCOL_MISMATCH; | ||
817 | } else { | 847 | } else { |
818 | response.packet.dlm_minor = | 848 | packet.dlm_minor = query->dlm_proto.pv_minor; |
819 | query->dlm_proto.pv_minor; | 849 | packet.fs_minor = query->fs_proto.pv_minor; |
820 | response.packet.fs_minor = | 850 | packet.code = JOIN_OK; |
821 | query->fs_proto.pv_minor; | ||
822 | response.packet.code = JOIN_OK; | ||
823 | __dlm_set_joining_node(dlm, query->node_idx); | 851 | __dlm_set_joining_node(dlm, query->node_idx); |
824 | } | 852 | } |
825 | } | 853 | } |
@@ -830,9 +858,10 @@ unlock_respond: | |||
830 | spin_unlock(&dlm_domain_lock); | 858 | spin_unlock(&dlm_domain_lock); |
831 | 859 | ||
832 | respond: | 860 | respond: |
833 | mlog(0, "We respond with %u\n", response.packet.code); | 861 | mlog(0, "We respond with %u\n", packet.code); |
834 | 862 | ||
835 | return response.intval; | 863 | dlm_query_join_packet_to_wire(&packet, &response); |
864 | return response; | ||
836 | } | 865 | } |
837 | 866 | ||
838 | static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, | 867 | static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, |
@@ -968,7 +997,8 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
968 | { | 997 | { |
969 | int status; | 998 | int status; |
970 | struct dlm_query_join_request join_msg; | 999 | struct dlm_query_join_request join_msg; |
971 | union dlm_query_join_response join_resp; | 1000 | struct dlm_query_join_packet packet; |
1001 | u32 join_resp; | ||
972 | 1002 | ||
973 | mlog(0, "querying node %d\n", node); | 1003 | mlog(0, "querying node %d\n", node); |
974 | 1004 | ||
@@ -984,11 +1014,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
984 | 1014 | ||
985 | status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg, | 1015 | status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg, |
986 | sizeof(join_msg), node, | 1016 | sizeof(join_msg), node, |
987 | &join_resp.intval); | 1017 | &join_resp); |
988 | if (status < 0 && status != -ENOPROTOOPT) { | 1018 | if (status < 0 && status != -ENOPROTOOPT) { |
989 | mlog_errno(status); | 1019 | mlog_errno(status); |
990 | goto bail; | 1020 | goto bail; |
991 | } | 1021 | } |
1022 | dlm_query_join_wire_to_packet(join_resp, &packet); | ||
992 | 1023 | ||
993 | /* -ENOPROTOOPT from the net code means the other side isn't | 1024 | /* -ENOPROTOOPT from the net code means the other side isn't |
994 | listening for our message type -- that's fine, it means | 1025 | listening for our message type -- that's fine, it means |
@@ -997,10 +1028,10 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
997 | if (status == -ENOPROTOOPT) { | 1028 | if (status == -ENOPROTOOPT) { |
998 | status = 0; | 1029 | status = 0; |
999 | *response = JOIN_OK_NO_MAP; | 1030 | *response = JOIN_OK_NO_MAP; |
1000 | } else if (join_resp.packet.code == JOIN_DISALLOW || | 1031 | } else if (packet.code == JOIN_DISALLOW || |
1001 | join_resp.packet.code == JOIN_OK_NO_MAP) { | 1032 | packet.code == JOIN_OK_NO_MAP) { |
1002 | *response = join_resp.packet.code; | 1033 | *response = packet.code; |
1003 | } else if (join_resp.packet.code == JOIN_PROTOCOL_MISMATCH) { | 1034 | } else if (packet.code == JOIN_PROTOCOL_MISMATCH) { |
1004 | mlog(ML_NOTICE, | 1035 | mlog(ML_NOTICE, |
1005 | "This node requested DLM locking protocol %u.%u and " | 1036 | "This node requested DLM locking protocol %u.%u and " |
1006 | "filesystem locking protocol %u.%u. At least one of " | 1037 | "filesystem locking protocol %u.%u. At least one of " |
@@ -1012,14 +1043,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
1012 | dlm->fs_locking_proto.pv_minor, | 1043 | dlm->fs_locking_proto.pv_minor, |
1013 | node); | 1044 | node); |
1014 | status = -EPROTO; | 1045 | status = -EPROTO; |
1015 | *response = join_resp.packet.code; | 1046 | *response = packet.code; |
1016 | } else if (join_resp.packet.code == JOIN_OK) { | 1047 | } else if (packet.code == JOIN_OK) { |
1017 | *response = join_resp.packet.code; | 1048 | *response = packet.code; |
1018 | /* Use the same locking protocol as the remote node */ | 1049 | /* Use the same locking protocol as the remote node */ |
1019 | dlm->dlm_locking_proto.pv_minor = | 1050 | dlm->dlm_locking_proto.pv_minor = packet.dlm_minor; |
1020 | join_resp.packet.dlm_minor; | 1051 | dlm->fs_locking_proto.pv_minor = packet.fs_minor; |
1021 | dlm->fs_locking_proto.pv_minor = | ||
1022 | join_resp.packet.fs_minor; | ||
1023 | mlog(0, | 1052 | mlog(0, |
1024 | "Node %d responds JOIN_OK with DLM locking protocol " | 1053 | "Node %d responds JOIN_OK with DLM locking protocol " |
1025 | "%u.%u and fs locking protocol %u.%u\n", | 1054 | "%u.%u and fs locking protocol %u.%u\n", |
@@ -1031,11 +1060,11 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
1031 | } else { | 1060 | } else { |
1032 | status = -EINVAL; | 1061 | status = -EINVAL; |
1033 | mlog(ML_ERROR, "invalid response %d from node %u\n", | 1062 | mlog(ML_ERROR, "invalid response %d from node %u\n", |
1034 | join_resp.packet.code, node); | 1063 | packet.code, node); |
1035 | } | 1064 | } |
1036 | 1065 | ||
1037 | mlog(0, "status %d, node %d response is %d\n", status, node, | 1066 | mlog(0, "status %d, node %d response is %d\n", status, node, |
1038 | *response); | 1067 | *response); |
1039 | 1068 | ||
1040 | bail: | 1069 | bail: |
1041 | return status; | 1070 | return status; |