Respuestas
truct 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;
/ * Asegúrese de que siempre asignemos al menos un puntero de bloque indirecto * /
nblocks = nblocks? : 1;
group_info = kmalloc (sizeof (* group_info) + nblocks * sizeof (gid_t *), GFP_USER);
if (! group_info)
devuelve NULL;
group_info-> ngroups = gidsetsize;
group_info-> nblocks = nblocks;
atomic_set (& group_info-> use, 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;
}
}
devolver group_info;
out_undo_partial_alloc:
while (--i> = 0) {
free_page ((sin signo largo) group_info-> blocks [i]);
}
kfree (group_info);
devuelve NULL;
}
EXPORT_SYMBOL (groups_alloc);
void groups_free (struct group_info * group_info)
{
if (group_info-> blocks [0]! = group_info-> small_block) {
int i;
para (i = 0; i <group_info-> nblocks; i ++)
free_page ((sin signo largo) group_info-> bloques [i]);
}
kfree (group_info);
}
EXPORT_SYMBOL (groups_free);
/ * exportar group_info a una matriz de espacio de usuario * /
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, cuenta);
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;
}
devuelve 0;
}
/ * rellene un group_info desde una matriz de espacio de usuario: ya debe estar asignado * /
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, cuenta);
unsigned int len = cp_count * sizeof (* grouplist