Whamcloud - gitweb
- update from 1_5
[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 list_head *tmp, *n;
90         struct uuid_nid_data *data, *entry;
91         int nob = strnlen (uuid, PAGE_SIZE) + 1;
92         int found = 0;
93
94         LASSERT(nid != 0);  /* valid newconfig NID is never zero */
95
96         if (nob > PAGE_SIZE)
97                 return -EINVAL;
98
99         OBD_ALLOC(data, sizeof(*data));
100         if (data == NULL)
101                 return -ENOMEM;
102
103         OBD_ALLOC(data->un_uuid, nob);
104         if (data == NULL) {
105                 OBD_FREE(data, sizeof(*data));
106                 return -ENOMEM;
107         }
108
109         memcpy(data->un_uuid, uuid, nob);
110         data->un_nid = nid;
111         data->un_count = 1;
112
113         spin_lock (&g_uuid_lock);
114
115         list_for_each_safe(tmp, n, &g_uuid_list) {
116                 entry = list_entry(tmp, struct uuid_nid_data, un_list);
117                 if (entry->un_nid == nid && 
118                     (strcmp(entry->un_uuid, uuid) == 0)) {
119                         found++;
120                         entry->un_count++;
121                         break;
122                 }
123         }
124         if (!found) 
125                 list_add(&data->un_list, &g_uuid_list);
126
127         spin_unlock (&g_uuid_lock);
128
129         if (found) {
130                 CDEBUG(D_INFO, "found uuid %s %s cnt=%d\n", uuid, 
131                        libcfs_nid2str(nid), entry->un_count);
132                 OBD_FREE(data->un_uuid, nob);
133                 OBD_FREE(data, sizeof(*data));
134         } else {
135                 CDEBUG(D_INFO, "add uuid %s %s\n", uuid, libcfs_nid2str(nid));
136         }
137         return 0;
138 }
139
140 /* Delete the nids for one uuid if specified, otherwise delete all */
141 int class_del_uuid(const char *uuid)
142 {
143         struct list_head  deathrow;
144         struct list_head *tmp;
145         struct list_head *n;
146         struct uuid_nid_data *data;
147
148         CFS_INIT_LIST_HEAD (&deathrow);
149
150         spin_lock (&g_uuid_lock);
151
152         list_for_each_safe(tmp, n, &g_uuid_list) {
153                 data = list_entry(tmp, struct uuid_nid_data, un_list);
154
155                 if (uuid == NULL) {
156                         list_del (&data->un_list);
157                         list_add (&data->un_list, &deathrow);
158                 } else if (strcmp(data->un_uuid, uuid) == 0) {
159                         --data->un_count;
160                         if (data->un_count <= 0) {
161                                 list_del (&data->un_list);
162                                 list_add (&data->un_list, &deathrow);
163                         }
164                         break;
165                 }
166         }
167
168         spin_unlock (&g_uuid_lock);
169
170         if (list_empty (&deathrow)) {
171                 if (uuid)
172                         CERROR("delete non-existent uuid %s\n", uuid);
173                 return -EINVAL;
174         }
175
176         do {
177                 data = list_entry(deathrow.next, struct uuid_nid_data, un_list);
178
179                 list_del (&data->un_list);
180                 CDEBUG(D_INFO, "del uuid %s %s\n", data->un_uuid,
181                        libcfs_nid2str(data->un_nid));
182
183                 OBD_FREE(data->un_uuid, strlen(data->un_uuid) + 1);
184                 OBD_FREE(data, sizeof(*data));
185         } while (!list_empty (&deathrow));
186
187         return 0;
188 }