Whamcloud - gitweb
LU-12383 utils: only check project inherit bit for dir
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_idmap.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  *
25  * Copyright (c) 2017, Intel Corporation.
26  *
27  * Author: Joshua Walgenbach <jjw@iu.edu>
28  */
29
30 #include <linux/rbtree.h>
31 #include <lustre_net.h>
32 #include "nodemap_internal.h"
33
34 /**
35  * Allocate the lu_idmap structure
36  *
37  * \param       client_id               client uid or gid
38  * \param       fs_id                   filesystem uid or gid
39  *
40  * \retval      alloated lu_idmap structure on success, NULL otherwise
41  */
42 struct lu_idmap *idmap_create(__u32 client_id, __u32 fs_id)
43 {
44         struct lu_idmap *idmap;
45
46         OBD_ALLOC_PTR(idmap);
47         if (idmap == NULL) {
48                 CERROR("cannot allocate lu_idmap of size %zu bytes\n",
49                        sizeof(idmap));
50                 return NULL;
51         }
52
53         idmap->id_client = client_id;
54         idmap->id_fs = fs_id;
55         RB_CLEAR_NODE(&idmap->id_client_to_fs);
56         RB_CLEAR_NODE(&idmap->id_fs_to_client);
57         return idmap;
58 }
59
60 static void idmap_destroy(struct lu_idmap *idmap)
61
62 {
63         LASSERT(RB_EMPTY_NODE(&idmap->id_fs_to_client) == 0);
64         LASSERT(RB_EMPTY_NODE(&idmap->id_client_to_fs) == 0);
65         OBD_FREE_PTR(idmap);
66 }
67
68 /**
69  * Insert idmap into the proper trees
70  *
71  * \param       id_type         NODEMAP_UID or NODEMAP_GID
72  * \param       idmap           lu_idmap structure to insert
73  * \param       nodemap         nodemap to associate with the map
74  *
75  * \retval      NULL             on success
76  * \retval      ERR_PTR(-EEXIST) if this idmap already exists
77  * \retval      struct lu_idmap  if only id_client or id_fs of this idmap
78  *                               is matched, return the matched idmap.
79  *                               The caller will delete this old idmap and
80  *                               its index before insert the new idmap again.
81  */
82 struct lu_idmap *idmap_insert(enum nodemap_id_type id_type,
83                               struct lu_idmap *idmap,
84                               struct lu_nodemap *nodemap)
85 {
86         struct lu_idmap         *fwd_cur = NULL;
87         struct lu_idmap         *bck_cur = NULL;
88         struct rb_node          *fwd_parent = NULL;
89         struct rb_node          *bck_parent = NULL;
90         struct rb_node          **fwd_node;
91         struct rb_node          **bck_node;
92         struct rb_root          *fwd_root;
93         struct rb_root          *bck_root;
94         bool                    fwd_found = false;
95         bool                    bck_found = false;
96
97         ENTRY;
98
99         /* for purposes in idmap client to fs is forward
100          * mapping, fs to client is backward mapping
101          */
102         if (id_type == NODEMAP_UID) {
103                 fwd_root = &nodemap->nm_client_to_fs_uidmap;
104                 bck_root = &nodemap->nm_fs_to_client_uidmap;
105         } else {
106                 fwd_root = &nodemap->nm_client_to_fs_gidmap;
107                 bck_root = &nodemap->nm_fs_to_client_gidmap;
108         }
109
110         fwd_node = &fwd_root->rb_node;
111         bck_node = &bck_root->rb_node;
112
113         /* find fwd and bck idmap nodes before insertion or
114          * replacing to prevent split brain idmaps
115          */
116         while (*fwd_node) {
117                 fwd_parent = *fwd_node;
118                 fwd_cur = rb_entry(*fwd_node, struct lu_idmap,
119                                    id_client_to_fs);
120
121                 if (idmap->id_client < fwd_cur->id_client) {
122                         fwd_node = &((*fwd_node)->rb_left);
123                 } else if (idmap->id_client > fwd_cur->id_client) {
124                         fwd_node = &((*fwd_node)->rb_right);
125                 } else {
126                         fwd_found = true;
127                         break;
128                 }
129         }
130
131         while (*bck_node) {
132                 bck_parent = *bck_node;
133                 bck_cur = rb_entry(*bck_node, struct lu_idmap,
134                                    id_fs_to_client);
135
136                 if (idmap->id_fs < bck_cur->id_fs) {
137                         bck_node = &((*bck_node)->rb_left);
138                 } else if (idmap->id_fs > bck_cur->id_fs) {
139                         bck_node = &((*bck_node)->rb_right);
140                 } else {
141                         bck_found = true;
142                         break;
143                 }
144         }
145
146         /* Already exists */
147         if (fwd_found && bck_found)
148                 RETURN(ERR_PTR(-EEXIST));
149
150         /* Insert a new idmap */
151         if (!fwd_found && !bck_found) {
152                 CDEBUG(D_INFO, "Insert a new idmap %d:%d\n",
153                        idmap->id_client, idmap->id_fs);
154                 rb_link_node(&idmap->id_client_to_fs, fwd_parent, fwd_node);
155                 rb_insert_color(&idmap->id_client_to_fs, fwd_root);
156                 rb_link_node(&idmap->id_fs_to_client, bck_parent, bck_node);
157                 rb_insert_color(&idmap->id_fs_to_client, bck_root);
158                 RETURN(NULL);
159         }
160
161         /* Only id_client or id_fs is matched */
162         RETURN(fwd_found ? fwd_cur : bck_cur);
163 }
164
165 /**
166  * Delete idmap from the correct nodemap tree
167  *
168  * \param       node_type               0 for UID
169  *                                      1 for GID
170  * \param       idmap                   idmap to delete
171  * \param       nodemap                 assoicated idmap
172  */
173 void idmap_delete(enum nodemap_id_type id_type, struct lu_idmap *idmap,
174                   struct lu_nodemap *nodemap)
175 {
176         struct rb_root  *fwd_root;
177         struct rb_root  *bck_root;
178
179         if (id_type == NODEMAP_UID) {
180                 fwd_root = &nodemap->nm_client_to_fs_uidmap;
181                 bck_root = &nodemap->nm_fs_to_client_uidmap;
182         } else {
183                 fwd_root = &nodemap->nm_client_to_fs_gidmap;
184                 bck_root = &nodemap->nm_fs_to_client_gidmap;
185         }
186
187         rb_erase(&idmap->id_client_to_fs, fwd_root);
188         rb_erase(&idmap->id_fs_to_client, bck_root);
189
190         idmap_destroy(idmap);
191 }
192
193 /**
194  * Search for an existing id in the nodemap trees.
195  *
196  * \param       nodemap         nodemap trees to search
197  * \param       tree_type       0 for filesystem to client maps
198  *                              1 for client to filesystem maps
199  * \param       id_type         0 for UID
200  *                              1 for GID
201  * \param       id              numeric id for which to search
202  *
203  * \retval      lu_idmap structure with the map on success
204  */
205 struct lu_idmap *idmap_search(struct lu_nodemap *nodemap,
206                               enum nodemap_tree_type tree_type,
207                               enum nodemap_id_type id_type,
208                               const __u32 id)
209 {
210         struct rb_node  *node;
211         struct rb_root  *root = NULL;
212         struct lu_idmap *idmap;
213
214         ENTRY;
215
216         if (id_type == NODEMAP_UID && tree_type == NODEMAP_FS_TO_CLIENT)
217                 root = &nodemap->nm_fs_to_client_uidmap;
218         else if (id_type == NODEMAP_UID && tree_type == NODEMAP_CLIENT_TO_FS)
219                 root = &nodemap->nm_client_to_fs_uidmap;
220         else if (id_type == NODEMAP_GID && tree_type == NODEMAP_FS_TO_CLIENT)
221                 root = &nodemap->nm_fs_to_client_gidmap;
222         else if (id_type == NODEMAP_GID && tree_type == NODEMAP_CLIENT_TO_FS)
223                 root = &nodemap->nm_client_to_fs_gidmap;
224
225         node = root->rb_node;
226
227         if (tree_type == NODEMAP_FS_TO_CLIENT) {
228                 while (node) {
229                         idmap = rb_entry(node, struct lu_idmap,
230                                          id_fs_to_client);
231                         if (id < idmap->id_fs)
232                                 node = node->rb_left;
233                         else if (id > idmap->id_fs)
234                                 node = node->rb_right;
235                         else
236                                 RETURN(idmap);
237                 }
238         } else {
239                 while (node) {
240                         idmap = rb_entry(node, struct lu_idmap,
241                                          id_client_to_fs);
242                         if (id < idmap->id_client)
243                                 node = node->rb_left;
244                         else if (id > idmap->id_client)
245                                 node = node->rb_right;
246                         else
247                                 RETURN(idmap);
248                 }
249         }
250
251         RETURN(NULL);
252 }
253
254 /*
255  * delete all idmap trees from a nodemap
256  *
257  * \param       nodemap         nodemap to delete trees from
258  *
259  * This uses the postorder safe traversal code that is committed
260  * in a later kernel. Each lu_idmap strucuture is destroyed.
261  */
262 void idmap_delete_tree(struct lu_nodemap *nodemap)
263 {
264         struct lu_idmap         *idmap;
265         struct lu_idmap         *temp;
266         struct rb_root          root;
267
268         root = nodemap->nm_fs_to_client_uidmap;
269         nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
270                                                 id_fs_to_client) {
271                 idmap_destroy(idmap);
272         }
273
274         root = nodemap->nm_client_to_fs_gidmap;
275         nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
276                                                 id_client_to_fs) {
277                 idmap_destroy(idmap);
278         }
279 }