4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (C) 2013, Trustees of Indiana University
24 * Author: Joshua Walgenbach <jjw@iu.edu>
27 #include <linux/rbtree.h>
28 #include <lustre_net.h>
29 #include "nodemap_internal.h"
32 * Allocate the lu_idmap structure
34 * \param client_id client uid or gid
35 * \param fs_id filesystem uid or gid
37 * \retval alloated lu_idmap structure on success, NULL otherwise
39 struct lu_idmap *idmap_create(__u32 client_id, __u32 fs_id)
41 struct lu_idmap *idmap;
45 CERROR("cannot allocate lu_idmap of size %zu bytes\n",
50 idmap->id_client = client_id;
52 RB_CLEAR_NODE(&idmap->id_client_to_fs);
53 RB_CLEAR_NODE(&idmap->id_fs_to_client);
57 static void idmap_destroy(struct lu_idmap *idmap)
60 LASSERT(RB_EMPTY_NODE(&idmap->id_fs_to_client) == 0);
61 LASSERT(RB_EMPTY_NODE(&idmap->id_client_to_fs) == 0);
66 * Insert idmap into the proper trees
68 * \param id_type NODEMAP_UID or NODEMAP_GID
69 * \param idmap lu_idmap structure to insert
70 * \param nodemap nodemap to associate with the map
72 * \retval NULL on success
73 * \retval ERR_PTR(-EEXIST) if this idmap already exists
74 * \retval struct lu_idmap if only id_client or id_fs of this idmap
75 * is matched, return the matched idmap.
76 * The caller will delete this old idmap and
77 * its index before insert the new idmap again.
79 struct lu_idmap *idmap_insert(enum nodemap_id_type id_type,
80 struct lu_idmap *idmap,
81 struct lu_nodemap *nodemap)
83 struct lu_idmap *fwd_cur = NULL;
84 struct lu_idmap *bck_cur = NULL;
85 struct rb_node *fwd_parent = NULL;
86 struct rb_node *bck_parent = NULL;
87 struct rb_node **fwd_node;
88 struct rb_node **bck_node;
89 struct rb_root *fwd_root;
90 struct rb_root *bck_root;
91 bool fwd_found = false;
92 bool bck_found = false;
96 /* for purposes in idmap client to fs is forward
97 * mapping, fs to client is backward mapping
99 if (id_type == NODEMAP_UID) {
100 fwd_root = &nodemap->nm_client_to_fs_uidmap;
101 bck_root = &nodemap->nm_fs_to_client_uidmap;
103 fwd_root = &nodemap->nm_client_to_fs_gidmap;
104 bck_root = &nodemap->nm_fs_to_client_gidmap;
107 fwd_node = &fwd_root->rb_node;
108 bck_node = &bck_root->rb_node;
110 /* find fwd and bck idmap nodes before insertion or
111 * replacing to prevent split brain idmaps
114 fwd_parent = *fwd_node;
115 fwd_cur = rb_entry(*fwd_node, struct lu_idmap,
118 if (idmap->id_client < fwd_cur->id_client) {
119 fwd_node = &((*fwd_node)->rb_left);
120 } else if (idmap->id_client > fwd_cur->id_client) {
121 fwd_node = &((*fwd_node)->rb_right);
129 bck_parent = *bck_node;
130 bck_cur = rb_entry(*bck_node, struct lu_idmap,
133 if (idmap->id_fs < bck_cur->id_fs) {
134 bck_node = &((*bck_node)->rb_left);
135 } else if (idmap->id_fs > bck_cur->id_fs) {
136 bck_node = &((*bck_node)->rb_right);
144 if (fwd_found && bck_found)
145 RETURN(ERR_PTR(-EEXIST));
147 /* Insert a new idmap */
148 if (!fwd_found && !bck_found) {
149 CDEBUG(D_INFO, "Insert a new idmap %d:%d\n",
150 idmap->id_client, idmap->id_fs);
151 rb_link_node(&idmap->id_client_to_fs, fwd_parent, fwd_node);
152 rb_insert_color(&idmap->id_client_to_fs, fwd_root);
153 rb_link_node(&idmap->id_fs_to_client, bck_parent, bck_node);
154 rb_insert_color(&idmap->id_fs_to_client, bck_root);
158 /* Only id_client or id_fs is matched */
159 RETURN(fwd_found ? fwd_cur : bck_cur);
163 * Delete idmap from the correct nodemap tree
165 * \param node_type 0 for UID
167 * \param idmap idmap to delete
168 * \param nodemap assoicated idmap
170 void idmap_delete(enum nodemap_id_type id_type, struct lu_idmap *idmap,
171 struct lu_nodemap *nodemap)
173 struct rb_root *fwd_root;
174 struct rb_root *bck_root;
176 if (id_type == NODEMAP_UID) {
177 fwd_root = &nodemap->nm_client_to_fs_uidmap;
178 bck_root = &nodemap->nm_fs_to_client_uidmap;
180 fwd_root = &nodemap->nm_client_to_fs_gidmap;
181 bck_root = &nodemap->nm_fs_to_client_gidmap;
184 rb_erase(&idmap->id_client_to_fs, fwd_root);
185 rb_erase(&idmap->id_fs_to_client, bck_root);
187 idmap_destroy(idmap);
191 * Search for an existing id in the nodemap trees.
193 * \param nodemap nodemap trees to search
194 * \param tree_type 0 for filesystem to client maps
195 * 1 for client to filesystem maps
196 * \param id_type 0 for UID
198 * \param id numeric id for which to search
200 * \retval lu_idmap structure with the map on success
202 struct lu_idmap *idmap_search(struct lu_nodemap *nodemap,
203 enum nodemap_tree_type tree_type,
204 enum nodemap_id_type id_type,
207 struct rb_node *node;
208 struct rb_root *root = NULL;
209 struct lu_idmap *idmap;
213 if (id_type == NODEMAP_UID && tree_type == NODEMAP_FS_TO_CLIENT)
214 root = &nodemap->nm_fs_to_client_uidmap;
215 else if (id_type == NODEMAP_UID && tree_type == NODEMAP_CLIENT_TO_FS)
216 root = &nodemap->nm_client_to_fs_uidmap;
217 else if (id_type == NODEMAP_GID && tree_type == NODEMAP_FS_TO_CLIENT)
218 root = &nodemap->nm_fs_to_client_gidmap;
219 else if (id_type == NODEMAP_GID && tree_type == NODEMAP_CLIENT_TO_FS)
220 root = &nodemap->nm_client_to_fs_gidmap;
222 node = root->rb_node;
224 if (tree_type == NODEMAP_FS_TO_CLIENT) {
226 idmap = rb_entry(node, struct lu_idmap,
228 if (id < idmap->id_fs)
229 node = node->rb_left;
230 else if (id > idmap->id_fs)
231 node = node->rb_right;
237 idmap = rb_entry(node, struct lu_idmap,
239 if (id < idmap->id_client)
240 node = node->rb_left;
241 else if (id > idmap->id_client)
242 node = node->rb_right;
252 * delete all idmap trees from a nodemap
254 * \param nodemap nodemap to delete trees from
256 * This uses the postorder safe traversal code that is committed
257 * in a later kernel. Each lu_idmap strucuture is destroyed.
259 void idmap_delete_tree(struct lu_nodemap *nodemap)
261 struct lu_idmap *idmap;
262 struct lu_idmap *temp;
265 root = nodemap->nm_fs_to_client_uidmap;
266 nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
268 idmap_destroy(idmap);
271 root = nodemap->nm_client_to_fs_gidmap;
272 nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
274 idmap_destroy(idmap);