aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-02-12 17:56:25 -0500
committerMark Fasheh <mark.fasheh@oracle.com>2008-03-10 18:13:54 -0400
commit0f71b7b40f55de909e40fa5ab217a5da3439c7d8 (patch)
tree3afad178b200b0a16e10ccaca2b05da1197034d4 /fs
parent2af37ce82d199d1d8cd6286f42f37d321627a807 (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.h20
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c101
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
605struct 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
605union dlm_query_join_response { 615union 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
618struct dlm_lock_request 620struct 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 */
729static 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
738static 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
716static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, 747static 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
832respond: 860respond:
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
838static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, 867static 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
1040bail: 1069bail:
1041 return status; 1070 return status;