aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-12-03 06:05:29 -0500
committerSteve French <smfrench@gmail.com>2012-12-08 23:04:25 -0500
commitfaa65f07d21e7d37190c91fdcf9f940d733ae3cc (patch)
tree68f77248b24fa59c3ec6218c6accfe0404f10f32 /fs/cifs
parent03eca704cfa426aebf6edcc0208536835c109a9f (diff)
cifs: simplify id_to_sid and sid_to_id mapping code
The cifs.idmap handling code currently causes the kernel to cache the data from userspace twice. It first looks in a rbtree to see if there is a matching entry for the given id. If there isn't then it calls request_key which then checks its cache and then calls out to userland if it doesn't have one. If the userland program establishes a mapping and downcalls with that info, it then gets cached in the keyring and in this rbtree. Aside from the double memory usage and the performance penalty in doing all of these extra copies, there are some nasty bugs in here too. The code declares four rbtrees and spinlocks to protect them, but only seems to use two of them. The upshot is that the same tree is used to hold (eg) uid:sid and sid:uid mappings. The comparitors aren't equipped to deal with that. I think we'd be best off to remove a layer of caching in this code. If this was originally done for performance reasons, then that really seems like a premature optimization. This patch does that -- it removes the rbtrees and the locks that protect them and simply has the code do a request_key call on each call into sid_to_id and id_to_sid. This greatly simplifies this code and should roughly halve the memory utilization from using the idmapping code. Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsacl.c535
-rw-r--r--fs/cifs/cifsacl.h28
-rw-r--r--fs/cifs/cifsfs.c1
-rw-r--r--fs/cifs/cifsproto.h1
4 files changed, 99 insertions, 466 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 42b3fe981a0..f4508ee4e80 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -44,128 +44,6 @@ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44 44
45static const struct cred *root_cred; 45static const struct cred *root_cred;
46 46
47static void
48shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
49 int *nr_del)
50{
51 struct rb_node *node;
52 struct rb_node *tmp;
53 struct cifs_sid_id *psidid;
54
55 node = rb_first(root);
56 while (node) {
57 tmp = node;
58 node = rb_next(tmp);
59 psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
60 if (nr_to_scan == 0 || *nr_del == nr_to_scan)
61 ++(*nr_rem);
62 else {
63 if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
64 && psidid->refcount == 0) {
65 rb_erase(tmp, root);
66 ++(*nr_del);
67 } else
68 ++(*nr_rem);
69 }
70 }
71}
72
73/*
74 * Run idmap cache shrinker.
75 */
76static int
77cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
78{
79 int nr_to_scan = sc->nr_to_scan;
80 int nr_del = 0;
81 int nr_rem = 0;
82 struct rb_root *root;
83
84 root = &uidtree;
85 spin_lock(&siduidlock);
86 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
87 spin_unlock(&siduidlock);
88
89 root = &gidtree;
90 spin_lock(&sidgidlock);
91 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
92 spin_unlock(&sidgidlock);
93
94 root = &siduidtree;
95 spin_lock(&uidsidlock);
96 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
97 spin_unlock(&uidsidlock);
98
99 root = &sidgidtree;
100 spin_lock(&gidsidlock);
101 shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
102 spin_unlock(&gidsidlock);
103
104 return nr_rem;
105}
106
107static void
108sid_rb_insert(struct rb_root *root, unsigned long cid,
109 struct cifs_sid_id **psidid, char *typestr)
110{
111 char *strptr;
112 struct rb_node *node = root->rb_node;
113 struct rb_node *parent = NULL;
114 struct rb_node **linkto = &(root->rb_node);
115 struct cifs_sid_id *lsidid;
116
117 while (node) {
118 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
119 parent = node;
120 if (cid > lsidid->id) {
121 linkto = &(node->rb_left);
122 node = node->rb_left;
123 }
124 if (cid < lsidid->id) {
125 linkto = &(node->rb_right);
126 node = node->rb_right;
127 }
128 }
129
130 (*psidid)->id = cid;
131 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
132 (*psidid)->refcount = 0;
133
134 sprintf((*psidid)->sidstr, "%s", typestr);
135 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
136 sprintf(strptr, "%ld", cid);
137
138 clear_bit(SID_ID_PENDING, &(*psidid)->state);
139 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
140
141 rb_link_node(&(*psidid)->rbnode, parent, linkto);
142 rb_insert_color(&(*psidid)->rbnode, root);
143}
144
145static struct cifs_sid_id *
146sid_rb_search(struct rb_root *root, unsigned long cid)
147{
148 struct rb_node *node = root->rb_node;
149 struct cifs_sid_id *lsidid;
150
151 while (node) {
152 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
153 if (cid > lsidid->id)
154 node = node->rb_left;
155 else if (cid < lsidid->id)
156 node = node->rb_right;
157 else /* node found */
158 return lsidid;
159 }
160
161 return NULL;
162}
163
164static struct shrinker cifs_shrinker = {
165 .shrink = cifs_idmap_shrinker,
166 .seeks = DEFAULT_SEEKS,
167};
168
169static int 47static int
170cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) 48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
171{ 49{
@@ -195,30 +73,39 @@ static struct key_type cifs_idmap_key_type = {
195 .match = user_match, 73 .match = user_match,
196}; 74};
197 75
198static void 76static char *
199sid_to_str(struct cifs_sid *sidptr, char *sidstr) 77sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
200{ 78{
201 int i; 79 int i, len;
202 unsigned int saval; 80 unsigned int saval;
203 char *strptr; 81 char *sidstr, *strptr;
204 82
205 strptr = sidstr; 83 /* 3 bytes for prefix */
84 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
85 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
86 GFP_KERNEL);
87 if (!sidstr)
88 return sidstr;
206 89
207 sprintf(strptr, "S-%hhu", sidptr->revision); 90 strptr = sidstr;
208 strptr = sidstr + strlen(sidstr); 91 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
92 sidptr->revision);
93 strptr += len;
209 94
210 for (i = 0; i < NUM_AUTHS; ++i) { 95 for (i = 0; i < NUM_AUTHS; ++i) {
211 if (sidptr->authority[i]) { 96 if (sidptr->authority[i]) {
212 sprintf(strptr, "-%hhu", sidptr->authority[i]); 97 len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
213 strptr = sidstr + strlen(sidstr); 98 strptr += len;
214 } 99 }
215 } 100 }
216 101
217 for (i = 0; i < sidptr->num_subauth; ++i) { 102 for (i = 0; i < sidptr->num_subauth; ++i) {
218 saval = le32_to_cpu(sidptr->sub_auth[i]); 103 saval = le32_to_cpu(sidptr->sub_auth[i]);
219 sprintf(strptr, "-%u", saval); 104 len = sprintf(strptr, "-%u", saval);
220 strptr = sidstr + strlen(sidstr); 105 strptr += len;
221 } 106 }
107
108 return sidstr;
222} 109}
223 110
224/* 111/*
@@ -284,184 +171,38 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
284 dst->sub_auth[i] = src->sub_auth[i]; 171 dst->sub_auth[i] = src->sub_auth[i];
285} 172}
286 173
287static void
288id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
289 struct cifs_sid_id **psidid, char *typestr)
290{
291 int rc;
292 char *strptr;
293 struct rb_node *node = root->rb_node;
294 struct rb_node *parent = NULL;
295 struct rb_node **linkto = &(root->rb_node);
296 struct cifs_sid_id *lsidid;
297
298 while (node) {
299 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
300 parent = node;
301 rc = compare_sids(sidptr, &((lsidid)->sid));
302 if (rc > 0) {
303 linkto = &(node->rb_left);
304 node = node->rb_left;
305 } else if (rc < 0) {
306 linkto = &(node->rb_right);
307 node = node->rb_right;
308 }
309 }
310
311 cifs_copy_sid(&(*psidid)->sid, sidptr);
312 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
313 (*psidid)->refcount = 0;
314
315 sprintf((*psidid)->sidstr, "%s", typestr);
316 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
317 sid_to_str(&(*psidid)->sid, strptr);
318
319 clear_bit(SID_ID_PENDING, &(*psidid)->state);
320 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
321
322 rb_link_node(&(*psidid)->rbnode, parent, linkto);
323 rb_insert_color(&(*psidid)->rbnode, root);
324}
325
326static struct cifs_sid_id *
327id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
328{
329 int rc;
330 struct rb_node *node = root->rb_node;
331 struct cifs_sid_id *lsidid;
332
333 while (node) {
334 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
335 rc = compare_sids(sidptr, &((lsidid)->sid));
336 if (rc > 0) {
337 node = node->rb_left;
338 } else if (rc < 0) {
339 node = node->rb_right;
340 } else /* node found */
341 return lsidid;
342 }
343
344 return NULL;
345}
346
347static int
348sidid_pending_wait(void *unused)
349{
350 schedule();
351 return signal_pending(current) ? -ERESTARTSYS : 0;
352}
353
354static int 174static int
355id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) 175id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
356{ 176{
357 int rc = 0; 177 int rc;
358 struct key *sidkey; 178 struct key *sidkey;
179 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
359 const struct cred *saved_cred; 180 const struct cred *saved_cred;
360 struct cifs_sid *lsid;
361 struct cifs_sid_id *psidid, *npsidid;
362 struct rb_root *cidtree;
363 spinlock_t *cidlock;
364
365 if (sidtype == SIDOWNER) {
366 cidlock = &siduidlock;
367 cidtree = &uidtree;
368 } else if (sidtype == SIDGROUP) {
369 cidlock = &sidgidlock;
370 cidtree = &gidtree;
371 } else
372 return -EINVAL;
373
374 spin_lock(cidlock);
375 psidid = sid_rb_search(cidtree, cid);
376
377 if (!psidid) { /* node does not exist, allocate one & attempt adding */
378 spin_unlock(cidlock);
379 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
380 if (!npsidid)
381 return -ENOMEM;
382
383 npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
384 if (!npsidid->sidstr) {
385 kfree(npsidid);
386 return -ENOMEM;
387 }
388
389 spin_lock(cidlock);
390 psidid = sid_rb_search(cidtree, cid);
391 if (psidid) { /* node happened to get inserted meanwhile */
392 ++psidid->refcount;
393 spin_unlock(cidlock);
394 kfree(npsidid->sidstr);
395 kfree(npsidid);
396 } else {
397 psidid = npsidid;
398 sid_rb_insert(cidtree, cid, &psidid,
399 sidtype == SIDOWNER ? "oi:" : "gi:");
400 ++psidid->refcount;
401 spin_unlock(cidlock);
402 }
403 } else {
404 ++psidid->refcount;
405 spin_unlock(cidlock);
406 }
407 181
408 /* 182 rc = snprintf(desc, sizeof(desc), "%ci:%u",
409 * If we are here, it is safe to access psidid and its fields 183 sidtype == SIDOWNER ? 'o' : 'g', cid);
410 * since a reference was taken earlier while holding the spinlock. 184 if (rc >= sizeof(desc))
411 * A reference on the node is put without holding the spinlock 185 return -EINVAL;
412 * and it is OK to do so in this case, shrinker will not erase
413 * this node until all references are put and we do not access
414 * any fields of the node after a reference is put .
415 */
416 if (test_bit(SID_ID_MAPPED, &psidid->state)) {
417 cifs_copy_sid(ssid, &psidid->sid);
418 psidid->time = jiffies; /* update ts for accessing */
419 goto id_sid_out;
420 }
421 186
422 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) { 187 rc = 0;
188 saved_cred = override_creds(root_cred);
189 sidkey = request_key(&cifs_idmap_key_type, desc, "");
190 if (IS_ERR(sidkey)) {
423 rc = -EINVAL; 191 rc = -EINVAL;
424 goto id_sid_out; 192 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
425 } 193 sidtype == SIDOWNER ? 'u' : 'g', cid);
426 194 goto out_revert_creds;
427 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { 195 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
428 saved_cred = override_creds(root_cred); 196 rc = -EIO;
429 sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); 197 cFYI(1, "%s: Downcall contained malformed key "
430 if (IS_ERR(sidkey)) { 198 "(datalen=%hu)", __func__, sidkey->datalen);
431 rc = -EINVAL; 199 goto out_key_put;
432 cFYI(1, "%s: Can't map and id to a SID", __func__); 200 }
433 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) { 201 cifs_copy_sid(ssid, (struct cifs_sid *)sidkey->payload.data);
434 rc = -EIO; 202out_key_put:
435 cFYI(1, "%s: Downcall contained malformed key " 203 key_put(sidkey);
436 "(datalen=%hu)", __func__, sidkey->datalen); 204out_revert_creds:
437 } else { 205 revert_creds(saved_cred);
438 lsid = (struct cifs_sid *)sidkey->payload.data;
439 cifs_copy_sid(&psidid->sid, lsid);
440 cifs_copy_sid(ssid, &psidid->sid);
441 set_bit(SID_ID_MAPPED, &psidid->state);
442 key_put(sidkey);
443 kfree(psidid->sidstr);
444 }
445 psidid->time = jiffies; /* update ts for accessing */
446 revert_creds(saved_cred);
447 clear_bit(SID_ID_PENDING, &psidid->state);
448 wake_up_bit(&psidid->state, SID_ID_PENDING);
449 } else {
450 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
451 sidid_pending_wait, TASK_INTERRUPTIBLE);
452 if (rc) {
453 cFYI(1, "%s: sidid_pending_wait interrupted %d",
454 __func__, rc);
455 --psidid->refcount;
456 return rc;
457 }
458 if (test_bit(SID_ID_MAPPED, &psidid->state))
459 cifs_copy_sid(ssid, &psidid->sid);
460 else
461 rc = -EINVAL;
462 }
463id_sid_out:
464 --psidid->refcount;
465 return rc; 206 return rc;
466} 207}
467 208
@@ -470,111 +211,66 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
470 struct cifs_fattr *fattr, uint sidtype) 211 struct cifs_fattr *fattr, uint sidtype)
471{ 212{
472 int rc; 213 int rc;
473 unsigned long cid; 214 struct key *sidkey;
474 struct key *idkey; 215 char *sidstr;
475 const struct cred *saved_cred; 216 const struct cred *saved_cred;
476 struct cifs_sid_id *psidid, *npsidid; 217 uid_t fuid = cifs_sb->mnt_uid;
477 struct rb_root *cidtree; 218 gid_t fgid = cifs_sb->mnt_gid;
478 spinlock_t *cidlock;
479
480 if (sidtype == SIDOWNER) {
481 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
482 cidlock = &siduidlock;
483 cidtree = &uidtree;
484 } else if (sidtype == SIDGROUP) {
485 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
486 cidlock = &sidgidlock;
487 cidtree = &gidtree;
488 } else
489 return -ENOENT;
490
491 spin_lock(cidlock);
492 psidid = id_rb_search(cidtree, psid);
493
494 if (!psidid) { /* node does not exist, allocate one & attempt adding */
495 spin_unlock(cidlock);
496 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
497 if (!npsidid)
498 return -ENOMEM;
499
500 npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
501 if (!npsidid->sidstr) {
502 kfree(npsidid);
503 return -ENOMEM;
504 }
505
506 spin_lock(cidlock);
507 psidid = id_rb_search(cidtree, psid);
508 if (psidid) { /* node happened to get inserted meanwhile */
509 ++psidid->refcount;
510 spin_unlock(cidlock);
511 kfree(npsidid->sidstr);
512 kfree(npsidid);
513 } else {
514 psidid = npsidid;
515 id_rb_insert(cidtree, psid, &psidid,
516 sidtype == SIDOWNER ? "os:" : "gs:");
517 ++psidid->refcount;
518 spin_unlock(cidlock);
519 }
520 } else {
521 ++psidid->refcount;
522 spin_unlock(cidlock);
523 }
524 219
525 /* 220 /*
526 * If we are here, it is safe to access psidid and its fields 221 * If we have too many subauthorities, then something is really wrong.
527 * since a reference was taken earlier while holding the spinlock. 222 * Just return an error.
528 * A reference on the node is put without holding the spinlock
529 * and it is OK to do so in this case, shrinker will not erase
530 * this node until all references are put and we do not access
531 * any fields of the node after a reference is put .
532 */ 223 */
533 if (test_bit(SID_ID_MAPPED, &psidid->state)) { 224 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
534 cid = psidid->id; 225 cFYI(1, "%s: %u subauthorities is too many!", __func__,
535 psidid->time = jiffies; /* update ts for accessing */ 226 psid->num_subauth);
536 goto sid_to_id_out; 227 return -EIO;
537 } 228 }
538 229
539 if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) 230 sidstr = sid_to_key_str(psid, sidtype);
540 goto sid_to_id_out; 231 if (!sidstr)
541 232 return -ENOMEM;
542 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { 233
543 saved_cred = override_creds(root_cred); 234 saved_cred = override_creds(root_cred);
544 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); 235 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
545 if (IS_ERR(idkey)) 236 if (IS_ERR(sidkey)) {
546 cFYI(1, "%s: Can't map SID to an id", __func__); 237 rc = -EINVAL;
547 else { 238 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
548 cid = *(unsigned long *)idkey->payload.value; 239 sidtype == SIDOWNER ? 'u' : 'g');
549 psidid->id = cid; 240 goto out_revert_creds;
550 set_bit(SID_ID_MAPPED, &psidid->state); 241 }
551 key_put(idkey); 242
552 kfree(psidid->sidstr); 243 /*
553 } 244 * FIXME: Here we assume that uid_t and gid_t are same size. It's
554 revert_creds(saved_cred); 245 * probably a safe assumption but might be better to check based on
555 psidid->time = jiffies; /* update ts for accessing */ 246 * sidtype.
556 clear_bit(SID_ID_PENDING, &psidid->state); 247 */
557 wake_up_bit(&psidid->state, SID_ID_PENDING); 248 if (sidkey->datalen < sizeof(uid_t)) {
558 } else { 249 rc = -EIO;
559 rc = wait_on_bit(&psidid->state, SID_ID_PENDING, 250 cFYI(1, "%s: Downcall contained malformed key "
560 sidid_pending_wait, TASK_INTERRUPTIBLE); 251 "(datalen=%hu)", __func__, sidkey->datalen);
561 if (rc) { 252 goto out_key_put;
562 cFYI(1, "%s: sidid_pending_wait interrupted %d",
563 __func__, rc);
564 --psidid->refcount; /* decremented without spinlock */
565 return rc;
566 }
567 if (test_bit(SID_ID_MAPPED, &psidid->state))
568 cid = psidid->id;
569 } 253 }
570 254
571sid_to_id_out:
572 --psidid->refcount; /* decremented without spinlock */
573 if (sidtype == SIDOWNER) 255 if (sidtype == SIDOWNER)
574 fattr->cf_uid = cid; 256 fuid = *(uid_t *)sidkey->payload.value;
575 else 257 else
576 fattr->cf_gid = cid; 258 fgid = *(gid_t *)sidkey->payload.value;
577 259
260out_key_put:
261 key_put(sidkey);
262out_revert_creds:
263 revert_creds(saved_cred);
264 kfree(sidstr);
265
266 /*
267 * Note that we return 0 here unconditionally. If the mapping
268 * fails then we just fall back to using the mnt_uid/mnt_gid.
269 */
270 if (sidtype == SIDOWNER)
271 fattr->cf_uid = fuid;
272 else
273 fattr->cf_gid = fgid;
578 return 0; 274 return 0;
579} 275}
580 276
@@ -621,17 +317,6 @@ init_cifs_idmap(void)
621 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; 317 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
622 root_cred = cred; 318 root_cred = cred;
623 319
624 spin_lock_init(&siduidlock);
625 uidtree = RB_ROOT;
626 spin_lock_init(&sidgidlock);
627 gidtree = RB_ROOT;
628
629 spin_lock_init(&uidsidlock);
630 siduidtree = RB_ROOT;
631 spin_lock_init(&gidsidlock);
632 sidgidtree = RB_ROOT;
633 register_shrinker(&cifs_shrinker);
634
635 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring)); 320 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
636 return 0; 321 return 0;
637 322
@@ -648,41 +333,9 @@ exit_cifs_idmap(void)
648 key_revoke(root_cred->thread_keyring); 333 key_revoke(root_cred->thread_keyring);
649 unregister_key_type(&cifs_idmap_key_type); 334 unregister_key_type(&cifs_idmap_key_type);
650 put_cred(root_cred); 335 put_cred(root_cred);
651 unregister_shrinker(&cifs_shrinker);
652 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name); 336 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
653} 337}
654 338
655void
656cifs_destroy_idmaptrees(void)
657{
658 struct rb_root *root;
659 struct rb_node *node;
660
661 root = &uidtree;
662 spin_lock(&siduidlock);
663 while ((node = rb_first(root)))
664 rb_erase(node, root);
665 spin_unlock(&siduidlock);
666
667 root = &gidtree;
668 spin_lock(&sidgidlock);
669 while ((node = rb_first(root)))
670 rb_erase(node, root);
671 spin_unlock(&sidgidlock);
672
673 root = &siduidtree;
674 spin_lock(&uidsidlock);
675 while ((node = rb_first(root)))
676 rb_erase(node, root);
677 spin_unlock(&uidsidlock);
678
679 root = &sidgidtree;
680 spin_lock(&gidsidlock);
681 while ((node = rb_first(root)))
682 rb_erase(node, root);
683 spin_unlock(&gidsidlock);
684}
685
686/* copy ntsd, owner sid, and group sid from a security descriptor to another */ 339/* copy ntsd, owner sid, and group sid from a security descriptor to another */
687static void copy_sec_desc(const struct cifs_ntsd *pntsd, 340static void copy_sec_desc(const struct cifs_ntsd *pntsd,
688 struct cifs_ntsd *pnntsd, __u32 sidsoffset) 341 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 249c94f3963..46cd444ea2f 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -23,7 +23,7 @@
23#define _CIFSACL_H 23#define _CIFSACL_H
24 24
25 25
26#define NUM_AUTHS 6 /* number of authority fields */ 26#define NUM_AUTHS (6) /* number of authority fields */
27#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */ 27#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
28#define NUM_WK_SIDS 7 /* number of well known sids */ 28#define NUM_WK_SIDS 7 /* number of well known sids */
29#define SIDNAMELENGTH 20 /* long enough for the ones we care about */ 29#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
@@ -51,15 +51,12 @@
51 * u32: max 10 bytes in decimal 51 * u32: max 10 bytes in decimal
52 * 52 *
53 * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes 53 * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes
54 * per number + 1 for '-') + 11 bytes for each subauthority field (10 bytes
55 * per number + 1 for '-') + NULL terminator. 54 * per number + 1 for '-') + NULL terminator.
55 *
56 * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
56 */ 57 */
57#define SID_STRING_MAX (195) 58#define SID_STRING_BASE_SIZE (2 + 3 + (4 * NUM_AUTHS) + 1)
58 59#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
59#define SID_ID_MAPPED 0
60#define SID_ID_PENDING 1
61#define SID_MAP_EXPIRE (3600 * HZ) /* map entry expires after one hour */
62#define SID_MAP_RETRY (300 * HZ) /* wait 5 minutes for next attempt to map */
63 60
64struct cifs_ntsd { 61struct cifs_ntsd {
65 __le16 revision; /* revision level */ 62 __le16 revision; /* revision level */
@@ -94,19 +91,4 @@ struct cifs_ace {
94 struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ 91 struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
95} __attribute__((packed)); 92} __attribute__((packed));
96 93
97struct cifs_wksid {
98 struct cifs_sid cifssid;
99 char sidname[SIDNAMELENGTH];
100} __attribute__((packed));
101
102struct cifs_sid_id {
103 unsigned int refcount; /* increment with spinlock, decrement without */
104 unsigned long id;
105 unsigned long time;
106 unsigned long state;
107 char *sidstr;
108 struct rb_node rbnode;
109 struct cifs_sid sid;
110};
111
112#endif /* _CIFSACL_H */ 94#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 273b34904d5..c6e32f22fbd 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1204,7 +1204,6 @@ exit_cifs(void)
1204 unregister_filesystem(&cifs_fs_type); 1204 unregister_filesystem(&cifs_fs_type);
1205 cifs_dfs_release_automount_timer(); 1205 cifs_dfs_release_automount_timer();
1206#ifdef CONFIG_CIFS_ACL 1206#ifdef CONFIG_CIFS_ACL
1207 cifs_destroy_idmaptrees();
1208 exit_cifs_idmap(); 1207 exit_cifs_idmap();
1209#endif 1208#endif
1210#ifdef CONFIG_CIFS_UPCALL 1209#ifdef CONFIG_CIFS_UPCALL
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a152f3645b0..1988c1baa22 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -58,7 +58,6 @@ do { \
58} while (0) 58} while (0)
59extern int init_cifs_idmap(void); 59extern int init_cifs_idmap(void);
60extern void exit_cifs_idmap(void); 60extern void exit_cifs_idmap(void);
61extern void cifs_destroy_idmaptrees(void);
62extern char *build_path_from_dentry(struct dentry *); 61extern char *build_path_from_dentry(struct dentry *);
63extern char *cifs_build_path_to_root(struct smb_vol *vol, 62extern char *cifs_build_path_to_root(struct smb_vol *vol,
64 struct cifs_sb_info *cifs_sb, 63 struct cifs_sb_info *cifs_sb,