Name: Simple Dynamic Allocation of groups array Author: Rusty Russell Status: Experimental D: This is a safe, naive approach to group addition. It applies to x86 D: and s390. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/arch/i386/kernel/init_task.c .9886-linux-2.4.19.updated/arch/i386/kernel/init_task.c --- .9886-linux-2.4.19/arch/i386/kernel/init_task.c 2003-02-27 14:46:17.000000000 +1100 +++ .9886-linux-2.4.19.updated/arch/i386/kernel/init_task.c 2003-09-18 17:44:43.000000000 +1000 @@ -10,6 +10,7 @@ static struct fs_struct init_fs = INIT_F static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); +static gid_t init_groups[NGROUPS]; /* * Initial task structure. @@ -20,7 +21,7 @@ struct mm_struct init_mm = INIT_MM(init_ */ union task_union init_task_union __attribute__((__section__(".data.init_task"))) = - { INIT_TASK(init_task_union.task) }; + { INIT_TASK(init_task_union.task,init_groups) }; /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/arch/s390/kernel/init_task.c .9886-linux-2.4.19.updated/arch/s390/kernel/init_task.c --- .9886-linux-2.4.19/arch/s390/kernel/init_task.c 2003-02-27 14:51:56.000000000 +1100 +++ .9886-linux-2.4.19.updated/arch/s390/kernel/init_task.c 2003-09-18 17:44:43.000000000 +1000 @@ -16,6 +16,7 @@ static struct fs_struct init_fs = INIT_F static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); +static gid_t init_groups[NGROUPS]; /* * Initial task structure. @@ -28,4 +29,4 @@ struct mm_struct init_mm = INIT_MM(init_ * The things we do for performance.. */ union task_union init_task_union __attribute__((aligned(8192))) = - { INIT_TASK(init_task_union.task) }; + { INIT_TASK(init_task_union.task,init_groups) }; diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/asm-i386/param.h .9886-linux-2.4.19.updated/include/asm-i386/param.h --- .9886-linux-2.4.19/include/asm-i386/param.h 2000-10-28 05:04:43.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/asm-i386/param.h 2003-09-18 17:44:43.000000000 +1000 @@ -8,7 +8,7 @@ #define EXEC_PAGESIZE 4096 #ifndef NGROUPS -#define NGROUPS 32 +#define NGROUPS 256 #endif #ifndef NOGROUP diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/asm-i386/processor.h .9886-linux-2.4.19.updated/include/asm-i386/processor.h --- .9886-linux-2.4.19/include/asm-i386/processor.h 2003-03-18 04:59:15.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/asm-i386/processor.h 2003-09-18 17:44:43.000000000 +1000 @@ -452,8 +452,8 @@ unsigned long get_wchan(struct task_stru #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) #define THREAD_SIZE (2*PAGE_SIZE) -#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) -#define free_task_struct(p) free_pages((unsigned long) (p), 1) +#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) +#define __free_task_struct(p) free_pages((unsigned long) (p), 1) #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) #define init_task (init_task_union.task) diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/asm-s390/param.h .9886-linux-2.4.19.updated/include/asm-s390/param.h --- .9886-linux-2.4.19/include/asm-s390/param.h 2001-02-14 09:13:44.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/asm-s390/param.h 2003-09-18 17:44:43.000000000 +1000 @@ -16,7 +16,7 @@ #define EXEC_PAGESIZE 4096 #ifndef NGROUPS -#define NGROUPS 32 +#define NGROUPS 256 #endif #ifndef NOGROUP diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/asm-s390/processor.h .9886-linux-2.4.19.updated/include/asm-s390/processor.h --- .9886-linux-2.4.19/include/asm-s390/processor.h 2003-03-18 04:59:20.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/asm-s390/processor.h 2003-09-18 17:44:43.000000000 +1000 @@ -144,9 +144,9 @@ unsigned long get_wchan(struct task_stru /* * NOTE! The task struct and the stack go together */ -#define alloc_task_struct() \ +#define __alloc_task_struct() \ ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) -#define free_task_struct(p) free_pages((unsigned long)(p),1) +#define __free_task_struct(p) free_pages((unsigned long)(p),1) #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) #define init_task (init_task_union.task) diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/linux/limits.h .9886-linux-2.4.19.updated/include/linux/limits.h --- .9886-linux-2.4.19/include/linux/limits.h 2003-02-27 14:52:03.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/linux/limits.h 2003-09-18 17:44:43.000000000 +1000 @@ -3,7 +3,7 @@ #define NR_OPEN 1024 -#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define NGROUPS_MAX 256 /* supplemental group IDs are available */ #define ARG_MAX 131072 /* # bytes of args + environ for exec() */ #define CHILD_MAX 999 /* no limit :-) */ #define OPEN_MAX 256 /* # open files a process may have */ diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/linux/mm.h .9886-linux-2.4.19.updated/include/linux/mm.h --- .9886-linux-2.4.19/include/linux/mm.h 2003-03-18 04:59:22.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/linux/mm.h 2003-09-18 17:44:43.000000000 +1000 @@ -454,8 +454,8 @@ extern unsigned long FASTCALL(get_zeroed /* * There is only one 'core' page-freeing function. */ -extern void FASTCALL(__free_pages(struct page *page, unsigned int order)); -extern void FASTCALL(free_pages(unsigned long addr, unsigned int order)); +extern int FASTCALL(__free_pages(struct page *page, unsigned int order)); +extern int FASTCALL(free_pages(unsigned long addr, unsigned int order)); #define __free_page(page) __free_pages((page), 0) #define free_page(addr) free_pages((addr),0) diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/include/linux/sched.h .9886-linux-2.4.19.updated/include/linux/sched.h --- .9886-linux-2.4.19/include/linux/sched.h 2003-03-18 04:59:22.000000000 +1100 +++ .9886-linux-2.4.19.updated/include/linux/sched.h 2003-09-18 17:44:51.000000000 +1000 @@ -374,7 +374,7 @@ struct task_struct { uid_t uid,euid,suid,fsuid; gid_t gid,egid,sgid,fsgid; int ngroups; - gid_t groups[NGROUPS]; + gid_t *groups; kernel_cap_t cap_effective, cap_inheritable, cap_permitted; int keep_capabilities:1; struct user_struct *user; @@ -470,7 +470,7 @@ extern struct exec_domain default_exec_d * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) */ -#define INIT_TASK(tsk) \ +#define INIT_TASK(tsk,_groups) \ { \ state: 0, \ flags: 0, \ @@ -511,6 +511,7 @@ extern struct exec_domain default_exec_d blocked: {{0}}, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + groups: _groups, \ } @@ -946,4 +947,7 @@ static inline char * d_path(struct dentr #endif /* __KERNEL__ */ +struct task_struct *alloc_task_struct(void); +void free_task_struct(struct task_struct *p); + #endif diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/kernel/fork.c .9886-linux-2.4.19.updated/kernel/fork.c --- .9886-linux-2.4.19/kernel/fork.c 2003-03-18 04:59:25.000000000 +1100 +++ .9886-linux-2.4.19.updated/kernel/fork.c 2003-09-18 17:44:43.000000000 +1000 @@ -580,6 +580,7 @@ int do_fork(unsigned long clone_flags, u int retval; struct task_struct *p; struct completion vfork; + gid_t *newgroups; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return -EINVAL; @@ -600,7 +601,11 @@ int do_fork(unsigned long clone_flags, u if (!p) goto fork_out; + /* Preserve group pointer, and copy across */ + newgroups = p->groups; *p = *current; + p->groups = newgroups; + memcpy(p->groups, current->groups, sizeof(p->groups[0])*NGROUPS); retval = -EAGAIN; /* diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/kernel/sched.c .9886-linux-2.4.19.updated/kernel/sched.c --- .9886-linux-2.4.19/kernel/sched.c 2003-03-18 04:59:25.000000000 +1100 +++ .9886-linux-2.4.19.updated/kernel/sched.c 2003-09-18 17:44:43.000000000 +1000 @@ -1314,6 +1314,28 @@ void __init init_idle(void) clear_bit(current->processor, &wait_init_idle); } +struct task_struct *alloc_task_struct(void) +{ + struct task_struct *p = __alloc_task_struct(); + if (p) { + p->groups = kmalloc(sizeof(p->groups[0])*NGROUPS, GFP_KERNEL); + if (!p->groups) { + __free_task_struct(p); + p = NULL; + } + } + return p; +} + +void free_task_struct(struct task_struct *p) +{ + if (p) { + gid_t *groups = p->groups; + if (__free_task_struct(p)) + kfree(groups); + } +} + extern void init_timervecs (void); void __init sched_init(void) diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9886-linux-2.4.19/mm/page_alloc.c .9886-linux-2.4.19.updated/mm/page_alloc.c --- .9886-linux-2.4.19/mm/page_alloc.c 2003-03-18 04:59:25.000000000 +1100 +++ .9886-linux-2.4.19.updated/mm/page_alloc.c 2003-09-18 17:44:43.000000000 +1000 @@ -439,16 +439,22 @@ unsigned long get_zeroed_page(unsigned i return 0; } -void __free_pages(struct page *page, unsigned int order) +/* Return true if refcount hit zero. */ +int __free_pages(struct page *page, unsigned int order) { - if (!PageReserved(page) && put_page_testzero(page)) + if (!PageReserved(page) && put_page_testzero(page)) { __free_pages_ok(page, order); + return 1; + } + return 0; } -void free_pages(unsigned long addr, unsigned int order) +/* Return true if refcount hit zero. */ +int free_pages(unsigned long addr, unsigned int order) { if (addr != 0) - __free_pages(virt_to_page(addr), order); + return __free_pages(virt_to_page(addr), order); + return 0; } /*