2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Linux module support routines.
14 #include <afsconfig.h>
15 #include "afs/param.h"
20 #include "afs/sysincludes.h"
21 #include "afsincludes.h"
22 #include "h/unistd.h" /* For syscall numbers. */
25 #ifdef AFS_AMD64_LINUX20_ENV
26 #include "../asm/ia32_unistd.h"
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
32 #include <linux/init.h>
33 #include <linux/sched.h>
35 #if !defined(EXPORTED_SYS_CALL_TABLE) && defined(HAVE_KERNEL_LINUX_SYSCALL_H)
36 #include <linux/syscall.h>
39 #if defined(AFS_LINUX26_ENV)
40 #include <linux/vermagic.h>
41 #include <linux/compiler.h>
43 MODULE_INFO(vermagic, VERMAGIC_STRING);
47 #ifdef AFS_SPARC64_LINUX24_ENV
48 #define __NR_setgroups32 82 /* This number is not exported for some bizarre reason. */
51 #if !defined(AFS_LINUX24_ENV)
52 asmlinkage int (*sys_settimeofdayp) (struct timeval * tv,
53 struct timezone * tz);
55 asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
57 #ifdef EXPORTED_SYS_CALL_TABLE
58 #ifdef AFS_SPARC64_LINUX20_ENV
59 extern unsigned int sys_call_table[]; /* changed to uint because SPARC64 has syscaltable of 32bit items */
61 extern void *sys_call_table[]; /* safer for other linuces */
63 #else /* EXPORTED_SYS_CALL_TABLE */
64 #ifdef AFS_SPARC64_LINUX20_ENV
65 static unsigned int *sys_call_table; /* changed to uint because SPARC64 has syscaltable of 32bit items */
67 static void **sys_call_table; /* safer for other linuces */
70 extern struct file_system_type afs_fs_type;
72 static long get_page_offset(void);
74 #if defined(AFS_LINUX24_ENV)
75 DECLARE_MUTEX(afs_global_lock);
77 struct semaphore afs_global_lock = MUTEX;
79 int afs_global_owner = 0;
80 #if !defined(AFS_LINUX24_ENV)
81 unsigned long afs_linux_page_offset = 0; /* contains the PAGE_OFFSET value */
84 /* Since sys_ni_syscall is not exported, I need to cache it in order to restore
87 #ifdef AFS_SPARC64_LINUX20_ENV
88 static unsigned int afs_ni_syscall = 0;
90 static void *afs_ni_syscall = 0;
93 #ifdef AFS_AMD64_LINUX20_ENV
94 #ifdef EXPORTED_IA32_SYS_CALL_TABLE
95 extern void *ia32_sys_call_table[];
97 static void **ia32_sys_call_table;
100 static void *ia32_ni_syscall = 0;
101 asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
102 #if defined(__NR_ia32_setgroups32)
103 asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
104 #endif /* __NR_ia32_setgroups32 */
105 #endif /* AFS_AMD64_LINUX20_ENV */
107 #ifdef AFS_PPC64_LINUX20_ENV
108 asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
109 #endif /* AFS_AMD64_LINUX20_ENV */
111 #ifdef AFS_SPARC64_LINUX20_ENV
112 static unsigned int afs_ni_syscall32 = 0;
113 asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
114 __kernel_gid_t32 * grouplist);
115 #if defined(__NR_setgroups32)
116 asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
117 __kernel_gid_t32 * grouplist);
118 #endif /* __NR_setgroups32 */
119 #ifdef EXPORTED_SYS_CALL_TABLE
120 extern unsigned int sys_call_table32[];
121 #else /* EXPORTED_SYS_CALL_TABLE */
122 static unsigned int *sys_call_table32;
123 #endif /* EXPORTED_SYS_CALL_TABLE */
126 afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4,
129 __asm__ __volatile__("srl %o4, 0, %o4\n\t" "mov %o7, %i7\n\t"
130 "call afs_syscall\n\t" "srl %o5, 0, %o5\n\t"
133 #endif /* AFS_SPARC64_LINUX20_ENV */
135 #ifdef AFS_IA64_LINUX20_ENV
138 afs_syscall_stub(int r0, int r1, long r2, long r3, long r4, long gp)
140 __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t" /* save rp */
141 "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t" /* save gp */
142 ";;\n" ".L1: mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_syscall-.L1,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t" /* restore gp */
143 "br.ret.sptk.many b0\n" ".fptr_afs_syscall:\n\t"
144 "data8 @fptr(afs_syscall)");
148 afs_xsetgroups_stub(int r0, int r1, long r2, long r3, long r4, long gp)
150 __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t" /* save rp */
151 "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t" /* save gp */
152 ";;\n" ".L2: mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_xsetgroups - .L2,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t" /* restore gp */
153 "br.ret.sptk.many b0\n" ".fptr_afs_xsetgroups:\n\t"
154 "data8 @fptr(afs_xsetgroups)");
162 #endif /* AFS_IA64_LINUX20_ENV */
164 #ifdef AFS_LINUX24_ENV
165 asmlinkage int (*sys_setgroups32p) (int gidsetsize,
166 __kernel_gid32_t * grouplist);
167 #endif /* AFS_LINUX24_ENV */
169 #ifdef AFS_SPARC64_LINUX20_ENV
170 #define POINTER2SYSCALL (unsigned int)(unsigned long)
171 #define SYSCALL2POINTER (void *)(long)
173 #define POINTER2SYSCALL (void *)
174 #define SYSCALL2POINTER (void *)
177 #ifdef AFS_PPC64_LINUX20_ENV
178 extern void *set_afs_syscall(void*);
179 extern void *set_afs_xsetgroups_syscall(void*);
180 extern void *set_afs_xsetgroups_syscall32(void*);
183 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
191 #if defined(AFS_IA64_LINUX20_ENV)
192 unsigned long kernel_gp = 0;
193 static struct fptr sys_setgroups;
195 extern int afs_syscall();
196 extern long afs_xsetgroups();
197 #if defined(__NR_setgroups32)
198 extern int afs_xsetgroups32();
199 #endif /* __NR_setgroups32 */
200 #if defined(AFS_SPARC64_LINUX20_ENV) || defined (AFS_AMD64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
201 extern int afs32_xsetgroups();
202 #if (defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV))
203 extern int afs32_xsetgroups32();
205 #if (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV))
206 extern int afs32_xsetgroups32();
208 #endif /* AFS_SPARC64_LINUX20_ENV || AFS_AMD64_LINUX20_ENV */
210 #if !defined(EXPORTED_SYS_CALL_TABLE) || (defined(AFS_AMD64_LINUX20_ENV) && !defined(EXPORTED_IA32_SYS_CALL_TABLE))
212 unsigned long offset=0;
213 unsigned long datalen=0;
215 unsigned long token=0;
217 unsigned long mod_start=0;
218 unsigned long mod_end=0;
220 unsigned long sec_start=0;
221 unsigned long sec_end=0;
223 unsigned long sym_start=0;
224 unsigned long sym_end=0;
225 #endif /* EXPORTED_SYS_CALL_TABLE */
227 RWLOCK_INIT(&afs_xosi, "afs_xosi");
229 #if !defined(AFS_LINUX24_ENV)
230 /* obtain PAGE_OFFSET value */
231 afs_linux_page_offset = get_page_offset();
233 #ifndef AFS_S390_LINUX22_ENV
234 if (afs_linux_page_offset == 0) {
235 /* couldn't obtain page offset so can't continue */
236 printf("afs: Unable to obtain PAGE_OFFSET. Exiting..");
241 #ifndef EXPORTED_SYS_CALL_TABLE
244 #ifdef EXPORTED_KALLSYMS_SYMBOL
250 kallsyms_symbol_to_address("sys_call_table", &token, &mod_name,
251 &mod_start, &mod_end, &sec_name,
252 &sec_start, &sec_end, &sym_name,
253 &sym_start, &sym_end);
254 if (ret && !strcmp(mod_name, "kernel"))
257 if (ret && sym_start) {
258 sys_call_table = sym_start;
261 #ifdef EXPORTED_KALLSYMS_ADDRESS
263 kallsyms_address_to_symbol((unsigned long)&init_mm, &mod_name,
264 &mod_start, &mod_end, &sec_name,
265 &sec_start, &sec_end, &sym_name,
266 &sym_start, &sym_end);
267 ptr = (unsigned long *)sec_start;
268 datalen = (sec_end - sec_start) / sizeof(unsigned long);
270 #if defined(AFS_IA64_LINUX20_ENV)
271 ptr = (unsigned long *)(&sys_close - 0x180000);
272 datalen = 0x180000 / sizeof(ptr);
274 #if defined(AFS_AMD64_LINUX20_ENV)
275 ptr = (unsigned long *)&init_mm;
276 datalen = 0x360000 / sizeof(ptr);
278 ptr = (unsigned long *)&init_mm;
283 for (offset = 0; offset < datalen; ptr++, offset++) {
284 #if defined(AFS_IA64_LINUX20_ENV)
285 unsigned long close_ip =
286 (unsigned long)((struct fptr *)&sys_close)->ip;
287 unsigned long chdir_ip =
288 (unsigned long)((struct fptr *)&sys_chdir)->ip;
289 unsigned long write_ip =
290 (unsigned long)((struct fptr *)&sys_write)->ip;
291 if (ptr[0] == close_ip && ptr[__NR_chdir - __NR_close] == chdir_ip
292 && ptr[__NR_write - __NR_close] == write_ip) {
293 sys_call_table = (void *)&(ptr[-1 * (__NR_close - 1024)]);
297 #if defined(EXPORTED_SYS_WAIT4) && defined(EXPORTED_SYS_CLOSE)
298 if (ptr[0] == (unsigned long)&sys_close
299 && ptr[__NR_wait4 - __NR_close] == (unsigned long)&sys_wait4) {
300 sys_call_table = ptr - __NR_close;
304 #if defined(EXPORTED_SYS_CHDIR) && defined(EXPORTED_SYS_CLOSE)
305 if (ptr[0] == (unsigned long)&sys_close
306 && ptr[__NR_chdir - __NR_close] == (unsigned long)&sys_chdir) {
307 sys_call_table = ptr - __NR_close;
311 if (ptr[0] == (unsigned long)&sys_exit
312 && ptr[__NR_open - __NR_exit] == (unsigned long)&sys_open) {
313 sys_call_table = ptr - __NR_exit;
320 #ifdef EXPORTED_KALLSYMS_ADDRESS
322 kallsyms_address_to_symbol((unsigned long)sys_call_table, &mod_name,
323 &mod_start, &mod_end, &sec_name,
324 &sec_start, &sec_end, &sym_name,
325 &sym_start, &sym_end);
326 if (ret && strcmp(sym_name, "sys_call_table"))
330 if (!sys_call_table) {
331 printf("Failed to find address of sys_call_table\n");
334 printf("Found sys_call_table at %x\n", sys_call_table);
335 # ifdef AFS_SPARC64_LINUX20_ENV
336 error cant support this yet.
338 #endif /* EXPORTED_SYS_CALL_TABLE */
339 #ifdef AFS_AMD64_LINUX20_ENV
340 #ifndef EXPORTED_IA32_SYS_CALL_TABLE
341 ia32_sys_call_table = 0;
342 #ifdef EXPORTED_KALLSYMS_SYMBOL
348 kallsyms_symbol_to_address("ia32_sys_call_table", &token,
349 &mod_name, &mod_start, &mod_end,
350 &sec_name, &sec_start, &sec_end,
351 &sym_name, &sym_start, &sym_end);
352 if (ret && !strcmp(mod_name, "kernel"))
355 if (ret && sym_start) {
356 ia32_sys_call_table = sym_start;
358 #else /* EXPORTED_KALLSYMS_SYMBOL */
359 #ifdef EXPORTED_KALLSYMS_ADDRESS
361 kallsyms_address_to_symbol((unsigned long)&interruptible_sleep_on,
362 &mod_name, &mod_start, &mod_end, &sec_name,
363 &sec_start, &sec_end, &sym_name,
364 &sym_start, &sym_end);
365 ptr = (unsigned long *)sec_start;
366 datalen = (sec_end - sec_start) / sizeof(unsigned long);
367 #else /* EXPORTED_KALLSYMS_ADDRESS */
368 #if defined(AFS_AMD64_LINUX20_ENV)
369 ptr = (unsigned long *)&interruptible_sleep_on;
370 datalen = 0x180000 / sizeof(ptr);
371 #else /* AFS_AMD64_LINUX20_ENV */
372 ptr = (unsigned long *)&interruptible_sleep_on;
374 #endif /* AFS_AMD64_LINUX20_ENV */
375 #endif /* EXPORTED_KALLSYMS_ADDRESS */
376 for (offset = 0; offset < datalen; ptr++, offset++) {
377 if (ptr[0] == (unsigned long)&sys_exit
378 && ptr[__NR_ia32_open - __NR_ia32_exit] ==
379 (unsigned long)&sys_open) {
380 ia32_sys_call_table = ptr - __NR_ia32_exit;
384 #ifdef EXPORTED_KALLSYMS_ADDRESS
386 kallsyms_address_to_symbol((unsigned long)ia32_sys_call_table,
387 &mod_name, &mod_start, &mod_end, &sec_name,
388 &sec_start, &sec_end, &sym_name,
389 &sym_start, &sym_end);
390 if (ret && strcmp(sym_name, "ia32_sys_call_table"))
391 ia32_sys_call_table = 0;
392 #endif /* EXPORTED_KALLSYMS_ADDRESS */
393 #endif /* EXPORTED_KALLSYMS_SYMBOL */
394 if (!ia32_sys_call_table) {
395 printf("Warning: Failed to find address of ia32_sys_call_table\n");
397 printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table);
400 printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table);
401 #endif /* IA32_SYS_CALL_TABLE */
404 /* Initialize pointers to kernel syscalls. */
405 #if !defined(AFS_LINUX24_ENV)
406 sys_settimeofdayp = SYSCALL2POINTER sys_call_table[__NR_settimeofday];
407 #endif /* AFS_IA64_LINUX20_ENV */
409 /* setup AFS entry point. */
411 #if defined(AFS_IA64_LINUX20_ENV)
412 SYSCALL2POINTER sys_call_table[__NR_afs_syscall - 1024]
414 SYSCALL2POINTER sys_call_table[__NR_afs_syscall]
417 printf("AFS syscall entry point already in use!\n");
420 #if defined(AFS_IA64_LINUX20_ENV)
421 afs_ni_syscall = sys_call_table[__NR_afs_syscall - 1024];
422 sys_call_table[__NR_afs_syscall - 1024] =
423 POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
424 #else /* AFS_IA64_LINUX20_ENV */
425 afs_ni_syscall = sys_call_table[__NR_afs_syscall];
426 sys_call_table[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall;
427 # ifdef AFS_SPARC64_LINUX20_ENV
428 afs_ni_syscall32 = sys_call_table32[__NR_afs_syscall];
429 sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
431 #endif /* AFS_IA64_LINUX20_ENV */
432 #ifdef AFS_AMD64_LINUX20_ENV
433 if (ia32_sys_call_table) {
434 ia32_ni_syscall = ia32_sys_call_table[__NR_ia32_afs_syscall];
435 ia32_sys_call_table[__NR_ia32_afs_syscall] =
436 POINTER2SYSCALL afs_syscall;
438 #endif /* AFS_S390_LINUX22_ENV */
441 register_filesystem(&afs_fs_type);
443 /* Intercept setgroups calls */
444 #if defined(AFS_IA64_LINUX20_ENV)
445 sys_setgroupsp = (void *)&sys_setgroups;
447 ((struct fptr *)sys_setgroupsp)->ip =
448 SYSCALL2POINTER sys_call_table[__NR_setgroups - 1024];
449 ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
451 sys_call_table[__NR_setgroups - 1024] =
452 POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
453 #else /* AFS_IA64_LINUX20_ENV */
454 sys_setgroupsp = SYSCALL2POINTER sys_call_table[__NR_setgroups];
455 sys_call_table[__NR_setgroups] = POINTER2SYSCALL afs_xsetgroups;
456 #ifdef AFS_SPARC64_LINUX20_ENV
457 sys32_setgroupsp = SYSCALL2POINTER sys_call_table32[__NR_setgroups];
458 sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
459 #endif /* AFS_SPARC64_LINUX20_ENV */
460 #if defined(__NR_setgroups32)
461 sys_setgroups32p = SYSCALL2POINTER sys_call_table[__NR_setgroups32];
462 sys_call_table[__NR_setgroups32] = POINTER2SYSCALL afs_xsetgroups32;
463 #ifdef AFS_SPARC64_LINUX20_ENV
464 sys32_setgroups32p = SYSCALL2POINTER sys_call_table32[__NR_setgroups32];
465 sys_call_table32[__NR_setgroups32] = POINTER2SYSCALL afs32_xsetgroups32;
466 #endif /* AFS_SPARC64_LINUX20_ENV */
467 #endif /* __NR_setgroups32 */
468 #ifdef AFS_AMD64_LINUX20_ENV
469 if (ia32_sys_call_table) {
471 SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups];
472 ia32_sys_call_table[__NR_ia32_setgroups] =
473 POINTER2SYSCALL afs32_xsetgroups;
474 #if defined(__NR_ia32_setgroups32)
476 SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups32];
477 ia32_sys_call_table[__NR_ia32_setgroups32] =
478 POINTER2SYSCALL afs32_xsetgroups32;
479 #endif /* __NR_ia32_setgroups32 */
481 #endif /* AFS_AMD64_LINUX20_ENV */
482 #endif /* AFS_IA64_LINUX20_ENV */
484 #ifdef AFS_PPC64_LINUX20_ENV
485 afs_ni_syscall = set_afs_syscall(afs_syscall);
486 sys_setgroupsp = set_afs_xsetgroups_syscall(afs_xsetgroups);
487 sys32_setgroupsp = set_afs_xsetgroups_syscall32(afs32_xsetgroups);
495 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
503 struct task_struct *t;
507 #if defined(AFS_IA64_LINUX20_ENV)
508 sys_call_table[__NR_setgroups - 1024] =
509 POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
510 sys_call_table[__NR_afs_syscall - 1024] = afs_ni_syscall;
511 #else /* AFS_IA64_LINUX20_ENV */
512 sys_call_table[__NR_setgroups] = POINTER2SYSCALL sys_setgroupsp;
513 sys_call_table[__NR_afs_syscall] = afs_ni_syscall;
514 # ifdef AFS_SPARC64_LINUX20_ENV
515 sys_call_table32[__NR_setgroups] = POINTER2SYSCALL sys32_setgroupsp;
516 sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
518 # if defined(__NR_setgroups32)
519 sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
520 # ifdef AFS_SPARC64_LINUX20_ENV
521 sys_call_table32[__NR_setgroups32] = POINTER2SYSCALL sys32_setgroups32p;
524 #endif /* AFS_IA64_LINUX20_ENV */
525 #ifdef AFS_AMD64_LINUX20_ENV
526 if (ia32_sys_call_table) {
527 ia32_sys_call_table[__NR_ia32_setgroups] =
528 POINTER2SYSCALL sys32_setgroupsp;
529 ia32_sys_call_table[__NR_ia32_afs_syscall] =
530 POINTER2SYSCALL ia32_ni_syscall;
531 # if defined(__NR_setgroups32)
532 ia32_sys_call_table[__NR_ia32_setgroups32] =
533 POINTER2SYSCALL sys32_setgroups32p;
537 #ifdef AFS_PPC64_LINUX20_ENV
538 set_afs_syscall(afs_ni_syscall);
539 set_afs_xsetgroups_syscall(sys_setgroupsp);
540 set_afs_xsetgroups_syscall32(sys32_setgroupsp);
542 unregister_filesystem(&afs_fs_type);
544 osi_linux_free_inode_pages(); /* Invalidate all pages using AFS inodes. */
545 osi_linux_free_afs_memory();
550 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
551 module_init(afs_init);
552 module_exit(afs_cleanup);
556 #if !defined(AFS_LINUX24_ENV)
558 get_page_offset(void)
560 #if defined(AFS_PPC_LINUX22_ENV) || defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_S390_LINUX22_ENV) || defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PARISC_LINUX24_ENV) || defined(AFS_AMD64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
563 struct task_struct *p, *q;
565 /* search backward thru the circular list */
566 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
567 read_lock(&tasklist_lock);
569 /* search backward thru the circular list */
570 #ifdef DEFINED_PREV_TASK
571 for (q = current; p = q; q = prev_task(p)) {
573 for (p = current; p; p = p->prev_task) {
576 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
577 read_unlock(&tasklist_lock);
579 return p->addr_limit.seg;
583 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
584 read_unlock(&tasklist_lock);
589 #endif /* !AFS_LINUX24_ENV */