Whamcloud - gitweb
ca08d11565f267e23c1593114f9acf31f1b46e3d
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_range.c
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (C) 2013, Trustees of Indiana University
24  * Author: Joshua Walgenbach <jjw@iu.edu>
25  */
26
27 #include <lustre_net.h>
28 #include "nodemap_internal.h"
29 #include <linux/interval_tree_generic.h>
30
31 /*
32  * Range trees
33  *
34  * To classify clients when they connect, build a global range tree
35  * containing all admin defined ranges. Incoming clients can then be
36  * classified into their nodemaps, and the lu_nodemap structure will be
37  * set in the export structure for the connecting client. Pointers to
38  * the lu_nid_range nodes will be added to linked links within the
39  * lu_nodemap structure for reporting purposes. Access to range tree should be
40  * controlled to prevent read access during update operations.
41  */
42
43 #define START(node)     ((node)->rn_start)
44 #define LAST(node)      ((node)->rn_end)
45
46 INTERVAL_TREE_DEFINE(struct lu_nid_range, rn_rb, lnet_nid_t, rn_subtree_last,
47                      START, LAST, static, nm_range)
48
49 /*
50  * range constructor
51  *
52  * \param       min             starting nid of the range
53  * \param       max             ending nid of the range
54  * \param       nodemap         nodemap that contains this range
55  * \retval      lu_nid_range on success, NULL on failure
56  */
57 struct lu_nid_range *range_create(struct nodemap_range_tree *nm_range_tree,
58                                   lnet_nid_t start_nid, lnet_nid_t end_nid,
59                                   struct lu_nodemap *nodemap, unsigned range_id)
60 {
61         struct lu_nid_range *range;
62
63         if (LNET_NIDNET(start_nid) != LNET_NIDNET(end_nid) ||
64             LNET_NIDADDR(start_nid) > LNET_NIDADDR(end_nid))
65                 return NULL;
66
67         OBD_ALLOC_PTR(range);
68         if (range == NULL) {
69                 CERROR("cannot allocate lu_nid_range of size %zu bytes\n",
70                        sizeof(*range));
71                 return NULL;
72         }
73
74         /* if we are loading from save, use on disk id num */
75         if (range_id != 0) {
76                 if (nm_range_tree->nmrt_range_highest_id < range_id)
77                         nm_range_tree->nmrt_range_highest_id = range_id;
78                 range->rn_id = range_id;
79         } else {
80                 nm_range_tree->nmrt_range_highest_id++;
81                 range->rn_id = nm_range_tree->nmrt_range_highest_id;
82         }
83         range->rn_nodemap = nodemap;
84
85         range->rn_start = start_nid;
86         range->rn_end = end_nid;
87
88         INIT_LIST_HEAD(&range->rn_list);
89
90         return range;
91 }
92
93 /*
94  * find the exact range
95  *
96  * \param       start_nid               starting nid
97  * \param       end_nid                 ending nid
98  * \retval      matching range or NULL
99  */
100 struct lu_nid_range *range_find(struct nodemap_range_tree *nm_range_tree,
101                                 lnet_nid_t start_nid, lnet_nid_t end_nid)
102 {
103         struct lu_nid_range *range;
104
105         range = nm_range_iter_first(
106                 &nm_range_tree->nmrt_range_interval_root, start_nid, end_nid);
107         while (range &&
108                (range->rn_start != start_nid || range->rn_end != end_nid))
109                 range = nm_range_iter_next(range, start_nid, end_nid);
110
111         return range;
112 }
113
114 /*
115  * range destructor
116  */
117 void range_destroy(struct lu_nid_range *range)
118 {
119         LASSERT(list_empty(&range->rn_list) == 0);
120
121         OBD_FREE_PTR(range);
122 }
123
124 /*
125  * insert an nid range into the interval tree
126  *
127  * \param       range           range to insetr
128  * \retval      0 on success
129  *
130  * This function checks that the given nid range
131  * does not overlap so that each nid can belong
132  * to exactly one range
133  */
134 int range_insert(struct nodemap_range_tree *nm_range_tree,
135                  struct lu_nid_range *range)
136 {
137         if (nm_range_iter_first(&nm_range_tree->nmrt_range_interval_root,
138                                 range->rn_start,
139                                 range->rn_end))
140                 return -EEXIST;
141
142         nm_range_insert(range, &nm_range_tree->nmrt_range_interval_root);
143
144         return 0;
145 }
146
147 /*
148  * delete a range from the interval tree and any
149  * associated nodemap references
150  *
151  * \param       range           range to remove
152  */
153 void range_delete(struct nodemap_range_tree *nm_range_tree,
154                   struct lu_nid_range *range)
155 {
156         list_del(&range->rn_list);
157         nm_range_remove(range, &nm_range_tree->nmrt_range_interval_root);
158         range_destroy(range);
159 }
160
161 /*
162  * search the interval tree for an nid within a range
163  *
164  * \param       nid             nid to search for
165  */
166 struct lu_nid_range *range_search(struct nodemap_range_tree *nm_range_tree,
167                                   lnet_nid_t nid)
168 {
169         return nm_range_iter_first(
170                 &nm_range_tree->nmrt_range_interval_root, nid, nid);
171 }