user.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * The "user cache".
  3.  *
  4.  * (C) Copyright 1991-2000 Linus Torvalds
  5.  *
  6.  * We have a per-user structure to keep track of how many
  7.  * processes, files etc the user has claimed, in order to be
  8.  * able to have per-user limits for system resources. 
  9.  */
  10. #include <linux/init.h>
  11. #include <linux/sched.h>
  12. #include <linux/slab.h>
  13. /*
  14.  * UID task count cache, to get fast user lookup in "alloc_uid"
  15.  * when changing user ID's (ie setuid() and friends).
  16.  */
  17. #define UIDHASH_BITS 8
  18. #define UIDHASH_SZ (1 << UIDHASH_BITS)
  19. #define UIDHASH_MASK (UIDHASH_SZ - 1)
  20. #define __uidhashfn(uid) (((uid >> UIDHASH_BITS) ^ uid) & UIDHASH_MASK)
  21. #define uidhashentry(uid) (uidhash_table + __uidhashfn(uid))
  22. static kmem_cache_t *uid_cachep;
  23. static struct user_struct *uidhash_table[UIDHASH_SZ];
  24. static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;
  25. struct user_struct root_user = {
  26. __count: ATOMIC_INIT(1),
  27. processes: ATOMIC_INIT(1),
  28. files: ATOMIC_INIT(0)
  29. };
  30. /*
  31.  * These routines must be called with the uidhash spinlock held!
  32.  */
  33. static inline void uid_hash_insert(struct user_struct *up, struct user_struct **hashent)
  34. {
  35. struct user_struct *next = *hashent;
  36. up->next = next;
  37. if (next)
  38. next->pprev = &up->next;
  39. up->pprev = hashent;
  40. *hashent = up;
  41. }
  42. static inline void uid_hash_remove(struct user_struct *up)
  43. {
  44. struct user_struct *next = up->next;
  45. struct user_struct **pprev = up->pprev;
  46. if (next)
  47. next->pprev = pprev;
  48. *pprev = next;
  49. }
  50. static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent)
  51. {
  52. struct user_struct *next;
  53. next = *hashent;
  54. for (;;) {
  55. struct user_struct *up = next;
  56. if (next) {
  57. next = up->next;
  58. if (up->uid != uid)
  59. continue;
  60. atomic_inc(&up->__count);
  61. }
  62. return up;
  63. }
  64. }
  65. void free_uid(struct user_struct *up)
  66. {
  67. if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
  68. uid_hash_remove(up);
  69. kmem_cache_free(uid_cachep, up);
  70. spin_unlock(&uidhash_lock);
  71. }
  72. }
  73. struct user_struct * alloc_uid(uid_t uid)
  74. {
  75. struct user_struct **hashent = uidhashentry(uid);
  76. struct user_struct *up;
  77. spin_lock(&uidhash_lock);
  78. up = uid_hash_find(uid, hashent);
  79. spin_unlock(&uidhash_lock);
  80. if (!up) {
  81. struct user_struct *new;
  82. new = kmem_cache_alloc(uid_cachep, SLAB_KERNEL);
  83. if (!new)
  84. return NULL;
  85. new->uid = uid;
  86. atomic_set(&new->__count, 1);
  87. atomic_set(&new->processes, 0);
  88. atomic_set(&new->files, 0);
  89. /*
  90.  * Before adding this, check whether we raced
  91.  * on adding the same user already..
  92.  */
  93. spin_lock(&uidhash_lock);
  94. up = uid_hash_find(uid, hashent);
  95. if (up) {
  96. kmem_cache_free(uid_cachep, new);
  97. } else {
  98. uid_hash_insert(new, hashent);
  99. up = new;
  100. }
  101. spin_unlock(&uidhash_lock);
  102. }
  103. return up;
  104. }
  105. static int __init uid_cache_init(void)
  106. {
  107. uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct),
  108.        0,
  109.        SLAB_HWCACHE_ALIGN, NULL, NULL);
  110. if(!uid_cachep)
  111. panic("Cannot create uid taskcount SLAB cachen");
  112. /* Insert the root user immediately - init already runs with this */
  113. uid_hash_insert(&root_user, uidhashentry(0));
  114. return 0;
  115. }
  116. module_init(uid_cache_init);