Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / obdclass / lustre_peer.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   You may have signed or agreed to another license before downloading
10  *   this software.  If so, you are bound by the terms and conditions
11  *   of that agreement, and the following does not apply to you.  See the
12  *   LICENSE file included with this distribution for more information.
13  *
14  *   If you did not agree to a different license, then this copy of Lustre
15  *   is open source software; you can redistribute it and/or modify it
16  *   under the terms of version 2 of the GNU General Public License as
17  *   published by the Free Software Foundation.
18  *
19  *   In either case, Lustre is distributed in the hope that it will be
20  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   license text for more details.
23  *
24  */
25
26 #define DEBUG_SUBSYSTEM S_RPC
27
28 #ifndef __KERNEL__
29 # include <liblustre.h>
30 #endif
31 #include <obd.h>
32 #include <obd_support.h>
33 #include <obd_class.h>
34 #include <lustre_lib.h>
35 #include <lustre_ha.h>
36 #include <lustre_net.h>
37 #include <lprocfs_status.h>
38
39 struct uuid_nid_data {
40         struct list_head un_list;
41         lnet_nid_t       un_nid;
42         char            *un_uuid;
43         int              un_count;  /* nid/uuid pair refcount */
44 };
45
46 /* FIXME: This should probably become more elegant than a global linked list */
47 static struct list_head g_uuid_list;
48 static spinlock_t       g_uuid_lock;
49
50 void class_init_uuidlist(void)
51 {
52         CFS_INIT_LIST_HEAD(&g_uuid_list);
53         spin_lock_init(&g_uuid_lock);
54 }
55
56 void class_exit_uuidlist(void)
57 {
58         /* delete all */
59         class_del_uuid(NULL);
60 }
61
62 int lustre_uuid_to_peer(const char *uuid, lnet_nid_t *peer_nid, int index)
63 {
64         struct list_head *tmp;
65
66         spin_lock (&g_uuid_lock);
67
68         list_for_each(tmp, &g_uuid_list) {
69                 struct uuid_nid_data *data =
70                         list_entry(tmp, struct uuid_nid_data, un_list);
71
72                 if (!strcmp(data->un_uuid, uuid) &&
73                     index-- == 0) {
74                         *peer_nid = data->un_nid;
75
76                         spin_unlock (&g_uuid_lock);
77                         return 0;
78                 }
79         }
80
81         spin_unlock (&g_uuid_lock);
82         return -ENOENT;
83 }
84
85 /* Add a nid to a niduuid.  Multiple nids can be added to a single uuid;
86    LNET will choose the best one. */
87 int class_add_uuid(const char *uuid, __u64 nid)
88 {
89         struct uuid_nid_data *data, *entry;
90         int nob = strnlen (uuid, CFS_PAGE_SIZE) + 1;
91         int found = 0;
92
93         LASSERT(nid != 0);  /* valid newconfig NID is never zero */
94
95         if (nob > CFS_PAGE_SIZE)
96                 return -EINVAL;
97
98         OBD_ALLOC(data, sizeof(*data));
99         if (data == NULL)
100                 return -ENOMEM;
101
102         OBD_ALLOC(data->un_uuid, nob);
103         if (data == NULL) {
104                 OBD_FREE(data, sizeof(*data));
105                 return -ENOMEM;
106         }
107
108         memcpy(data->un_uuid, uuid, nob);
109         data->un_nid = nid;
110         data->un_count = 1;
111
112         spin_lock (&g_uuid_lock);
113
114         list_for_each_entry(entry, &g_uuid_list, un_list) {
115                 if (entry->un_nid == nid && 
116                     (strcmp(entry->un_uuid, uuid) == 0)) {
117                         found++;
118                         entry->un_count++;
119                         break;
120                 }
121         }
122         if (!found) 
123                 list_add(&data->un_list, &g_uuid_list);
124         spin_unlock (&g_uuid_lock);
125
126         if (found) {
127                 CDEBUG(D_INFO, "found uuid %s %s cnt=%d\n", uuid, 
128                        libcfs_nid2str(nid), entry->un_count);
129                 OBD_FREE(data->un_uuid, nob);
130                 OBD_FREE(data, sizeof(*data));
131         } else {
132                 CDEBUG(D_INFO, "add uuid %s %s\n", uuid, libcfs_nid2str(nid));
133         }
134         return 0;
135 }
136
137 /* Delete the nids for one uuid if specified, otherwise delete all */
138 int class_del_uuid(const char *uuid)
139 {
140         CFS_LIST_HEAD(deathrow);
141         struct uuid_nid_data *data;
142         int found = 0;
143
144         spin_lock (&g_uuid_lock);
145         if (uuid == NULL) {
146                 list_splice_init(&g_uuid_list, &deathrow);
147                 found = 1;
148         } else {
149                 list_for_each_entry(data, &g_uuid_list, un_list) {
150                         if (strcmp(data->un_uuid, uuid))
151                                 continue;
152                         --data->un_count;
153                         LASSERT(data->un_count >= 0);
154                         if (data->un_count == 0)
155                                 list_move(&data->un_list, &deathrow);
156                         found = 1;
157                         break;
158                 }
159         }
160         spin_unlock (&g_uuid_lock);
161
162         if (!found) {
163                 if (uuid)
164                         CERROR("Try to delete a non-existent uuid %s\n", uuid);
165                 return -EINVAL;
166         }
167
168         while (!list_empty(&deathrow)) {
169                 data = list_entry(deathrow.next, struct uuid_nid_data, un_list);
170                 list_del(&data->un_list);
171
172                 CDEBUG(D_INFO, "del uuid %s %s\n", data->un_uuid,
173                        libcfs_nid2str(data->un_nid));
174
175                 OBD_FREE(data->un_uuid, strlen(data->un_uuid) + 1);
176                 OBD_FREE(data, sizeof(*data));
177         }
178
179         return 0;
180 }