Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
- struct group_info *groups_alloc(int gidsetsize){
- struct group_info *group_info;
- int nblocks;
- int i;
- nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK;
- /* Make sure we always allocate at least one indirect block pointer */
- nblocks = nblocks ? : 1;
- group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER);
- if (!group_info)
- return NULL;
- group_info->ngroups = gidsetsize;
- group_info->nblocks = nblocks;
- atomic_set(&group_info->usage, 1);
- if (gidsetsize <= NGROUPS_SMALL)
- group_info->blocks[0] = group_info->small_block;
- else {
- for (i = 0; i < nblocks; i++) {
- gid_t *b;
- b = (void *)__get_free_page(GFP_USER);
- if (!b)
- goto out_undo_partial_alloc;
- group_info->blocks[i] = b;
- }
- }
- return group_info;
- out_undo_partial_alloc:
- while (--i >= 0) {
- free_page((unsigned long)group_info->blocks[i]);
- }
- kfree(group_info);
- return NULL;
- }
- EXPORT_SYMBOL(groups_alloc);
- void groups_free(struct group_info *group_info)
- {
- if (group_info->blocks[0] != group_info->small_block) {
- int i;
- for (i = 0; i < group_info->nblocks; i++)
- free_page((unsigned long)group_info->blocks[i]);
- }
- kfree(group_info);
- }
- EXPORT_SYMBOL(groups_free);
- /* export the group_info to a user-space array */
- static int groups_to_user(gid_t __user *grouplist,
- const struct group_info *group_info)
- {
- int i;
- unsigned int count = group_info->ngroups;
- for (i = 0; i < group_info->nblocks; i++) {
- unsigned int cp_count = min(NGROUPS_PER_BLOCK, count);
- unsigned int len = cp_count * sizeof(*grouplist);
- if (copy_to_user(grouplist, group_info->blocks[i], len))
- return -EFAULT;
- grouplist += NGROUPS_PER_BLOCK;
- count -= cp_count;
- }
- return 0;
- }
- /* fill a group_info from a user-space array - it must be allocated already */
- static int groups_from_user(struct group_info *group_info,
- gid_t __user *grouplist)
- {
- int i;
- unsigned int count = group_info->ngroups;
- for (i = 0; i < group_info->nblocks; i++) {
- unsigned int cp_count = min(NGROUPS_PER_BLOCK, count);
- unsigned int len = cp_count * sizeof(*grouplist);
- if (copy_from_user(group_info->blocks[i], grouplist, len))
- return -EFAULT;
- grouplist += NGROUPS_PER_BLOCK;
- count -= cp_count;
- }
- return 0;
- }
- /* a simple Shell sort */
- static void groups_sort(struct group_info *group_info)
- {
- int base, max, stride;
- int gidsetsize = group_info->ngroups;
- for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
- ; /* nothing */
- stride /= 3;
- while (stride) {
- max = gidsetsize
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement