• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 
37 #define DEBUG_SUBSYSTEM S_RPC
38 
39 #include "../include/obd.h"
40 #include "../include/obd_support.h"
41 #include "../include/obd_class.h"
42 #include "../include/lustre_lib.h"
43 #include "../include/lustre_ha.h"
44 #include "../include/lustre_net.h"
45 #include "../include/lprocfs_status.h"
46 
47 #define NIDS_MAX	32
48 
49 struct uuid_nid_data {
50 	struct list_head       un_list;
51 	struct obd_uuid  un_uuid;
52 	int	      un_nid_count;
53 	lnet_nid_t       un_nids[NIDS_MAX];
54 };
55 
56 /* FIXME: This should probably become more elegant than a global linked list */
57 static struct list_head	g_uuid_list;
58 static spinlock_t	g_uuid_lock;
59 
class_init_uuidlist(void)60 void class_init_uuidlist(void)
61 {
62 	INIT_LIST_HEAD(&g_uuid_list);
63 	spin_lock_init(&g_uuid_lock);
64 }
65 
class_exit_uuidlist(void)66 void class_exit_uuidlist(void)
67 {
68 	/* delete all */
69 	class_del_uuid(NULL);
70 }
71 
lustre_uuid_to_peer(const char * uuid,lnet_nid_t * peer_nid,int index)72 int lustre_uuid_to_peer(const char *uuid, lnet_nid_t *peer_nid, int index)
73 {
74 	struct uuid_nid_data *data;
75 	struct obd_uuid tmp;
76 	int rc = -ENOENT;
77 
78 	obd_str2uuid(&tmp, uuid);
79 	spin_lock(&g_uuid_lock);
80 	list_for_each_entry(data, &g_uuid_list, un_list) {
81 		if (obd_uuid_equals(&data->un_uuid, &tmp)) {
82 			if (index >= data->un_nid_count)
83 				break;
84 
85 			rc = 0;
86 			*peer_nid = data->un_nids[index];
87 			break;
88 		}
89 	}
90 	spin_unlock(&g_uuid_lock);
91 	return rc;
92 }
93 EXPORT_SYMBOL(lustre_uuid_to_peer);
94 
95 /* Add a nid to a niduuid.  Multiple nids can be added to a single uuid;
96    LNET will choose the best one. */
class_add_uuid(const char * uuid,__u64 nid)97 int class_add_uuid(const char *uuid, __u64 nid)
98 {
99 	struct uuid_nid_data *data, *entry;
100 	int found = 0;
101 
102 	LASSERT(nid != 0);  /* valid newconfig NID is never zero */
103 
104 	if (strlen(uuid) > UUID_MAX - 1)
105 		return -EOVERFLOW;
106 
107 	data = kzalloc(sizeof(*data), GFP_NOFS);
108 	if (!data)
109 		return -ENOMEM;
110 
111 	obd_str2uuid(&data->un_uuid, uuid);
112 	data->un_nids[0] = nid;
113 	data->un_nid_count = 1;
114 
115 	spin_lock(&g_uuid_lock);
116 	list_for_each_entry(entry, &g_uuid_list, un_list) {
117 		if (obd_uuid_equals(&entry->un_uuid, &data->un_uuid)) {
118 			int i;
119 
120 			found = 1;
121 			for (i = 0; i < entry->un_nid_count; i++)
122 				if (nid == entry->un_nids[i])
123 					break;
124 
125 			if (i == entry->un_nid_count) {
126 				LASSERT(entry->un_nid_count < NIDS_MAX);
127 				entry->un_nids[entry->un_nid_count++] = nid;
128 			}
129 			break;
130 		}
131 	}
132 	if (!found)
133 		list_add(&data->un_list, &g_uuid_list);
134 	spin_unlock(&g_uuid_lock);
135 
136 	if (found) {
137 		CDEBUG(D_INFO, "found uuid %s %s cnt=%d\n", uuid,
138 		       libcfs_nid2str(nid), entry->un_nid_count);
139 		kfree(data);
140 	} else {
141 		CDEBUG(D_INFO, "add uuid %s %s\n", uuid, libcfs_nid2str(nid));
142 	}
143 	return 0;
144 }
145 EXPORT_SYMBOL(class_add_uuid);
146 
147 /* Delete the nids for one uuid if specified, otherwise delete all */
class_del_uuid(const char * uuid)148 int class_del_uuid(const char *uuid)
149 {
150 	LIST_HEAD(deathrow);
151 	struct uuid_nid_data *data;
152 
153 	spin_lock(&g_uuid_lock);
154 	if (uuid != NULL) {
155 		struct obd_uuid tmp;
156 
157 		obd_str2uuid(&tmp, uuid);
158 		list_for_each_entry(data, &g_uuid_list, un_list) {
159 			if (obd_uuid_equals(&data->un_uuid, &tmp)) {
160 				list_move(&data->un_list, &deathrow);
161 				break;
162 			}
163 		}
164 	} else
165 		list_splice_init(&g_uuid_list, &deathrow);
166 	spin_unlock(&g_uuid_lock);
167 
168 	if (uuid != NULL && list_empty(&deathrow)) {
169 		CDEBUG(D_INFO, "Try to delete a non-existent uuid %s\n", uuid);
170 		return -EINVAL;
171 	}
172 
173 	while (!list_empty(&deathrow)) {
174 		data = list_entry(deathrow.next, struct uuid_nid_data,
175 				      un_list);
176 		list_del(&data->un_list);
177 
178 		CDEBUG(D_INFO, "del uuid %s %s/%d\n",
179 		       obd_uuid2str(&data->un_uuid),
180 		       libcfs_nid2str(data->un_nids[0]),
181 		       data->un_nid_count);
182 
183 		kfree(data);
184 	}
185 
186 	return 0;
187 }
188 
189 /* check if @nid exists in nid list of @uuid */
class_check_uuid(struct obd_uuid * uuid,__u64 nid)190 int class_check_uuid(struct obd_uuid *uuid, __u64 nid)
191 {
192 	struct uuid_nid_data *entry;
193 	int found = 0;
194 
195 	CDEBUG(D_INFO, "check if uuid %s has %s.\n",
196 	       obd_uuid2str(uuid), libcfs_nid2str(nid));
197 
198 	spin_lock(&g_uuid_lock);
199 	list_for_each_entry(entry, &g_uuid_list, un_list) {
200 		int i;
201 
202 		if (!obd_uuid_equals(&entry->un_uuid, uuid))
203 			continue;
204 
205 		/* found the uuid, check if it has @nid */
206 		for (i = 0; i < entry->un_nid_count; i++) {
207 			if (entry->un_nids[i] == nid) {
208 				found = 1;
209 				break;
210 			}
211 		}
212 		break;
213 	}
214 	spin_unlock(&g_uuid_lock);
215 	return found;
216 }
217 EXPORT_SYMBOL(class_check_uuid);
218