diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 22 | ||||
-rw-r--r-- | fs/cifs/sess.c | 6 | ||||
-rw-r--r-- | fs/compat.c | 2 | ||||
-rw-r--r-- | fs/dnotify.c | 2 | ||||
-rw-r--r-- | fs/exec.c | 2 | ||||
-rw-r--r-- | fs/fcntl.c | 79 | ||||
-rw-r--r-- | fs/file_table.c | 1 | ||||
-rw-r--r-- | fs/inode.c | 14 | ||||
-rw-r--r-- | fs/lockd/clntlock.c | 2 | ||||
-rw-r--r-- | fs/lockd/clntproc.c | 4 | ||||
-rw-r--r-- | fs/lockd/mon.c | 2 | ||||
-rw-r--r-- | fs/lockd/svc.c | 74 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 2 | ||||
-rw-r--r-- | fs/lockd/xdr.c | 2 | ||||
-rw-r--r-- | fs/locks.c | 2 | ||||
-rw-r--r-- | fs/namespace.c | 22 | ||||
-rw-r--r-- | fs/nfs/callback.c | 7 | ||||
-rw-r--r-- | fs/nfs/client.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 2 | ||||
-rw-r--r-- | fs/nfsd/export.c | 12 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 152 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 318 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 8 | ||||
-rw-r--r-- | fs/nls/nls_base.c | 2 | ||||
-rw-r--r-- | fs/proc/array.c | 85 | ||||
-rw-r--r-- | fs/proc/base.c | 1759 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 3 | ||||
-rw-r--r-- | fs/proc/root.c | 12 |
30 files changed, 1400 insertions, 1205 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0e9ba0b9d71e..c78762051da4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -772,12 +772,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
772 | separator[1] = 0; | 772 | separator[1] = 0; |
773 | 773 | ||
774 | memset(vol->source_rfc1001_name,0x20,15); | 774 | memset(vol->source_rfc1001_name,0x20,15); |
775 | for(i=0;i < strnlen(system_utsname.nodename,15);i++) { | 775 | for(i=0;i < strnlen(utsname()->nodename,15);i++) { |
776 | /* does not have to be a perfect mapping since the field is | 776 | /* does not have to be a perfect mapping since the field is |
777 | informational, only used for servers that do not support | 777 | informational, only used for servers that do not support |
778 | port 445 and it can be overridden at mount time */ | 778 | port 445 and it can be overridden at mount time */ |
779 | vol->source_rfc1001_name[i] = | 779 | vol->source_rfc1001_name[i] = |
780 | toupper(system_utsname.nodename[i]); | 780 | toupper(utsname()->nodename[i]); |
781 | } | 781 | } |
782 | vol->source_rfc1001_name[15] = 0; | 782 | vol->source_rfc1001_name[15] = 0; |
783 | /* null target name indicates to use *SMBSERVR default called name | 783 | /* null target name indicates to use *SMBSERVR default called name |
@@ -2153,7 +2153,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2153 | 32, nls_codepage); | 2153 | 32, nls_codepage); |
2154 | bcc_ptr += 2 * bytes_returned; | 2154 | bcc_ptr += 2 * bytes_returned; |
2155 | bytes_returned = | 2155 | bytes_returned = |
2156 | cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, | 2156 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, |
2157 | 32, nls_codepage); | 2157 | 32, nls_codepage); |
2158 | bcc_ptr += 2 * bytes_returned; | 2158 | bcc_ptr += 2 * bytes_returned; |
2159 | bcc_ptr += 2; | 2159 | bcc_ptr += 2; |
@@ -2180,8 +2180,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2180 | } | 2180 | } |
2181 | strcpy(bcc_ptr, "Linux version "); | 2181 | strcpy(bcc_ptr, "Linux version "); |
2182 | bcc_ptr += strlen("Linux version "); | 2182 | bcc_ptr += strlen("Linux version "); |
2183 | strcpy(bcc_ptr, system_utsname.release); | 2183 | strcpy(bcc_ptr, utsname()->release); |
2184 | bcc_ptr += strlen(system_utsname.release) + 1; | 2184 | bcc_ptr += strlen(utsname()->release) + 1; |
2185 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | 2185 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); |
2186 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | 2186 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; |
2187 | } | 2187 | } |
@@ -2445,7 +2445,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2445 | 32, nls_codepage); | 2445 | 32, nls_codepage); |
2446 | bcc_ptr += 2 * bytes_returned; | 2446 | bcc_ptr += 2 * bytes_returned; |
2447 | bytes_returned = | 2447 | bytes_returned = |
2448 | cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32, | 2448 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, |
2449 | nls_codepage); | 2449 | nls_codepage); |
2450 | bcc_ptr += 2 * bytes_returned; | 2450 | bcc_ptr += 2 * bytes_returned; |
2451 | bcc_ptr += 2; /* null terminate Linux version */ | 2451 | bcc_ptr += 2; /* null terminate Linux version */ |
@@ -2462,8 +2462,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2462 | } else { /* ASCII */ | 2462 | } else { /* ASCII */ |
2463 | strcpy(bcc_ptr, "Linux version "); | 2463 | strcpy(bcc_ptr, "Linux version "); |
2464 | bcc_ptr += strlen("Linux version "); | 2464 | bcc_ptr += strlen("Linux version "); |
2465 | strcpy(bcc_ptr, system_utsname.release); | 2465 | strcpy(bcc_ptr, utsname()->release); |
2466 | bcc_ptr += strlen(system_utsname.release) + 1; | 2466 | bcc_ptr += strlen(utsname()->release) + 1; |
2467 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | 2467 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); |
2468 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | 2468 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; |
2469 | bcc_ptr++; /* empty domain field */ | 2469 | bcc_ptr++; /* empty domain field */ |
@@ -2836,7 +2836,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2836 | 32, nls_codepage); | 2836 | 32, nls_codepage); |
2837 | bcc_ptr += 2 * bytes_returned; | 2837 | bcc_ptr += 2 * bytes_returned; |
2838 | bytes_returned = | 2838 | bytes_returned = |
2839 | cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32, | 2839 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, |
2840 | nls_codepage); | 2840 | nls_codepage); |
2841 | bcc_ptr += 2 * bytes_returned; | 2841 | bcc_ptr += 2 * bytes_returned; |
2842 | bcc_ptr += 2; /* null term version string */ | 2842 | bcc_ptr += 2; /* null term version string */ |
@@ -2888,8 +2888,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2888 | 2888 | ||
2889 | strcpy(bcc_ptr, "Linux version "); | 2889 | strcpy(bcc_ptr, "Linux version "); |
2890 | bcc_ptr += strlen("Linux version "); | 2890 | bcc_ptr += strlen("Linux version "); |
2891 | strcpy(bcc_ptr, system_utsname.release); | 2891 | strcpy(bcc_ptr, utsname()->release); |
2892 | bcc_ptr += strlen(system_utsname.release) + 1; | 2892 | bcc_ptr += strlen(utsname()->release) + 1; |
2893 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | 2893 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); |
2894 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | 2894 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; |
2895 | bcc_ptr++; /* null domain */ | 2895 | bcc_ptr++; /* null domain */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index d1705ab8136e..22b4c35dcfe3 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -111,7 +111,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
111 | bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, | 111 | bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, |
112 | nls_cp); | 112 | nls_cp); |
113 | bcc_ptr += 2 * bytes_ret; | 113 | bcc_ptr += 2 * bytes_ret; |
114 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, | 114 | bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, |
115 | 32, nls_cp); | 115 | 32, nls_cp); |
116 | bcc_ptr += 2 * bytes_ret; | 116 | bcc_ptr += 2 * bytes_ret; |
117 | bcc_ptr += 2; /* trailing null */ | 117 | bcc_ptr += 2; /* trailing null */ |
@@ -158,8 +158,8 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, | |||
158 | 158 | ||
159 | strcpy(bcc_ptr, "Linux version "); | 159 | strcpy(bcc_ptr, "Linux version "); |
160 | bcc_ptr += strlen("Linux version "); | 160 | bcc_ptr += strlen("Linux version "); |
161 | strcpy(bcc_ptr, system_utsname.release); | 161 | strcpy(bcc_ptr, init_utsname()->release); |
162 | bcc_ptr += strlen(system_utsname.release) + 1; | 162 | bcc_ptr += strlen(init_utsname()->release) + 1; |
163 | 163 | ||
164 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | 164 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); |
165 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | 165 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; |
diff --git a/fs/compat.c b/fs/compat.c index 13fb08d096c4..d98c96f4a44d 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -56,8 +56,6 @@ | |||
56 | 56 | ||
57 | int compat_log = 1; | 57 | int compat_log = 1; |
58 | 58 | ||
59 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
60 | |||
61 | int compat_printk(const char *fmt, ...) | 59 | int compat_printk(const char *fmt, ...) |
62 | { | 60 | { |
63 | va_list ap; | 61 | va_list ap; |
diff --git a/fs/dnotify.c b/fs/dnotify.c index f932591df5a4..2b0442db67e0 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c | |||
@@ -92,7 +92,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
92 | prev = &odn->dn_next; | 92 | prev = &odn->dn_next; |
93 | } | 93 | } |
94 | 94 | ||
95 | error = f_setown(filp, current->pid, 0); | 95 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
96 | if (error) | 96 | if (error) |
97 | goto out_free; | 97 | goto out_free; |
98 | 98 | ||
@@ -1318,7 +1318,7 @@ static void format_corename(char *corename, const char *pattern, long signr) | |||
1318 | case 'h': | 1318 | case 'h': |
1319 | down_read(&uts_sem); | 1319 | down_read(&uts_sem); |
1320 | rc = snprintf(out_ptr, out_end - out_ptr, | 1320 | rc = snprintf(out_ptr, out_end - out_ptr, |
1321 | "%s", system_utsname.nodename); | 1321 | "%s", utsname()->nodename); |
1322 | up_read(&uts_sem); | 1322 | up_read(&uts_sem); |
1323 | if (rc > out_end - out_ptr) | 1323 | if (rc > out_end - out_ptr) |
1324 | goto out; | 1324 | goto out; |
diff --git a/fs/fcntl.c b/fs/fcntl.c index d35cbc6bc112..e4f26165f12a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -250,19 +250,22 @@ static int setfl(int fd, struct file * filp, unsigned long arg) | |||
250 | return error; | 250 | return error; |
251 | } | 251 | } |
252 | 252 | ||
253 | static void f_modown(struct file *filp, unsigned long pid, | 253 | static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, |
254 | uid_t uid, uid_t euid, int force) | 254 | uid_t uid, uid_t euid, int force) |
255 | { | 255 | { |
256 | write_lock_irq(&filp->f_owner.lock); | 256 | write_lock_irq(&filp->f_owner.lock); |
257 | if (force || !filp->f_owner.pid) { | 257 | if (force || !filp->f_owner.pid) { |
258 | filp->f_owner.pid = pid; | 258 | put_pid(filp->f_owner.pid); |
259 | filp->f_owner.pid = get_pid(pid); | ||
260 | filp->f_owner.pid_type = type; | ||
259 | filp->f_owner.uid = uid; | 261 | filp->f_owner.uid = uid; |
260 | filp->f_owner.euid = euid; | 262 | filp->f_owner.euid = euid; |
261 | } | 263 | } |
262 | write_unlock_irq(&filp->f_owner.lock); | 264 | write_unlock_irq(&filp->f_owner.lock); |
263 | } | 265 | } |
264 | 266 | ||
265 | int f_setown(struct file *filp, unsigned long arg, int force) | 267 | int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, |
268 | int force) | ||
266 | { | 269 | { |
267 | int err; | 270 | int err; |
268 | 271 | ||
@@ -270,15 +273,44 @@ int f_setown(struct file *filp, unsigned long arg, int force) | |||
270 | if (err) | 273 | if (err) |
271 | return err; | 274 | return err; |
272 | 275 | ||
273 | f_modown(filp, arg, current->uid, current->euid, force); | 276 | f_modown(filp, pid, type, current->uid, current->euid, force); |
274 | return 0; | 277 | return 0; |
275 | } | 278 | } |
279 | EXPORT_SYMBOL(__f_setown); | ||
276 | 280 | ||
281 | int f_setown(struct file *filp, unsigned long arg, int force) | ||
282 | { | ||
283 | enum pid_type type; | ||
284 | struct pid *pid; | ||
285 | int who = arg; | ||
286 | int result; | ||
287 | type = PIDTYPE_PID; | ||
288 | if (who < 0) { | ||
289 | type = PIDTYPE_PGID; | ||
290 | who = -who; | ||
291 | } | ||
292 | rcu_read_lock(); | ||
293 | pid = find_pid(who); | ||
294 | result = __f_setown(filp, pid, type, force); | ||
295 | rcu_read_unlock(); | ||
296 | return result; | ||
297 | } | ||
277 | EXPORT_SYMBOL(f_setown); | 298 | EXPORT_SYMBOL(f_setown); |
278 | 299 | ||
279 | void f_delown(struct file *filp) | 300 | void f_delown(struct file *filp) |
280 | { | 301 | { |
281 | f_modown(filp, 0, 0, 0, 1); | 302 | f_modown(filp, NULL, PIDTYPE_PID, 0, 0, 1); |
303 | } | ||
304 | |||
305 | pid_t f_getown(struct file *filp) | ||
306 | { | ||
307 | pid_t pid; | ||
308 | read_lock(&filp->f_owner.lock); | ||
309 | pid = pid_nr(filp->f_owner.pid); | ||
310 | if (filp->f_owner.pid_type == PIDTYPE_PGID) | ||
311 | pid = -pid; | ||
312 | read_unlock(&filp->f_owner.lock); | ||
313 | return pid; | ||
282 | } | 314 | } |
283 | 315 | ||
284 | static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | 316 | static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, |
@@ -319,7 +351,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
319 | * current syscall conventions, the only way | 351 | * current syscall conventions, the only way |
320 | * to fix this will be in libc. | 352 | * to fix this will be in libc. |
321 | */ | 353 | */ |
322 | err = filp->f_owner.pid; | 354 | err = f_getown(filp); |
323 | force_successful_syscall_return(); | 355 | force_successful_syscall_return(); |
324 | break; | 356 | break; |
325 | case F_SETOWN: | 357 | case F_SETOWN: |
@@ -470,24 +502,19 @@ static void send_sigio_to_task(struct task_struct *p, | |||
470 | void send_sigio(struct fown_struct *fown, int fd, int band) | 502 | void send_sigio(struct fown_struct *fown, int fd, int band) |
471 | { | 503 | { |
472 | struct task_struct *p; | 504 | struct task_struct *p; |
473 | int pid; | 505 | enum pid_type type; |
506 | struct pid *pid; | ||
474 | 507 | ||
475 | read_lock(&fown->lock); | 508 | read_lock(&fown->lock); |
509 | type = fown->pid_type; | ||
476 | pid = fown->pid; | 510 | pid = fown->pid; |
477 | if (!pid) | 511 | if (!pid) |
478 | goto out_unlock_fown; | 512 | goto out_unlock_fown; |
479 | 513 | ||
480 | read_lock(&tasklist_lock); | 514 | read_lock(&tasklist_lock); |
481 | if (pid > 0) { | 515 | do_each_pid_task(pid, type, p) { |
482 | p = find_task_by_pid(pid); | 516 | send_sigio_to_task(p, fown, fd, band); |
483 | if (p) { | 517 | } while_each_pid_task(pid, type, p); |
484 | send_sigio_to_task(p, fown, fd, band); | ||
485 | } | ||
486 | } else { | ||
487 | do_each_task_pid(-pid, PIDTYPE_PGID, p) { | ||
488 | send_sigio_to_task(p, fown, fd, band); | ||
489 | } while_each_task_pid(-pid, PIDTYPE_PGID, p); | ||
490 | } | ||
491 | read_unlock(&tasklist_lock); | 518 | read_unlock(&tasklist_lock); |
492 | out_unlock_fown: | 519 | out_unlock_fown: |
493 | read_unlock(&fown->lock); | 520 | read_unlock(&fown->lock); |
@@ -503,9 +530,12 @@ static void send_sigurg_to_task(struct task_struct *p, | |||
503 | int send_sigurg(struct fown_struct *fown) | 530 | int send_sigurg(struct fown_struct *fown) |
504 | { | 531 | { |
505 | struct task_struct *p; | 532 | struct task_struct *p; |
506 | int pid, ret = 0; | 533 | enum pid_type type; |
534 | struct pid *pid; | ||
535 | int ret = 0; | ||
507 | 536 | ||
508 | read_lock(&fown->lock); | 537 | read_lock(&fown->lock); |
538 | type = fown->pid_type; | ||
509 | pid = fown->pid; | 539 | pid = fown->pid; |
510 | if (!pid) | 540 | if (!pid) |
511 | goto out_unlock_fown; | 541 | goto out_unlock_fown; |
@@ -513,16 +543,9 @@ int send_sigurg(struct fown_struct *fown) | |||
513 | ret = 1; | 543 | ret = 1; |
514 | 544 | ||
515 | read_lock(&tasklist_lock); | 545 | read_lock(&tasklist_lock); |
516 | if (pid > 0) { | 546 | do_each_pid_task(pid, type, p) { |
517 | p = find_task_by_pid(pid); | 547 | send_sigurg_to_task(p, fown); |
518 | if (p) { | 548 | } while_each_pid_task(pid, type, p); |
519 | send_sigurg_to_task(p, fown); | ||
520 | } | ||
521 | } else { | ||
522 | do_each_task_pid(-pid, PIDTYPE_PGID, p) { | ||
523 | send_sigurg_to_task(p, fown); | ||
524 | } while_each_task_pid(-pid, PIDTYPE_PGID, p); | ||
525 | } | ||
526 | read_unlock(&tasklist_lock); | 549 | read_unlock(&tasklist_lock); |
527 | out_unlock_fown: | 550 | out_unlock_fown: |
528 | read_unlock(&fown->lock); | 551 | read_unlock(&fown->lock); |
diff --git a/fs/file_table.c b/fs/file_table.c index bc35a40417d7..24f25a057d9c 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -174,6 +174,7 @@ void fastcall __fput(struct file *file) | |||
174 | fops_put(file->f_op); | 174 | fops_put(file->f_op); |
175 | if (file->f_mode & FMODE_WRITE) | 175 | if (file->f_mode & FMODE_WRITE) |
176 | put_write_access(inode); | 176 | put_write_access(inode); |
177 | put_pid(file->f_owner.pid); | ||
177 | file_kill(file); | 178 | file_kill(file); |
178 | file->f_dentry = NULL; | 179 | file->f_dentry = NULL; |
179 | file->f_vfsmnt = NULL; | 180 | file->f_vfsmnt = NULL; |
diff --git a/fs/inode.c b/fs/inode.c index ada7643104e1..bf6bec4e54ff 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -657,7 +657,7 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_he | |||
657 | return inode; | 657 | return inode; |
658 | } | 658 | } |
659 | 659 | ||
660 | static inline unsigned long hash(struct super_block *sb, unsigned long hashval) | 660 | static unsigned long hash(struct super_block *sb, unsigned long hashval) |
661 | { | 661 | { |
662 | unsigned long tmp; | 662 | unsigned long tmp; |
663 | 663 | ||
@@ -1003,7 +1003,7 @@ void generic_delete_inode(struct inode *inode) | |||
1003 | 1003 | ||
1004 | list_del_init(&inode->i_list); | 1004 | list_del_init(&inode->i_list); |
1005 | list_del_init(&inode->i_sb_list); | 1005 | list_del_init(&inode->i_sb_list); |
1006 | inode->i_state|=I_FREEING; | 1006 | inode->i_state |= I_FREEING; |
1007 | inodes_stat.nr_inodes--; | 1007 | inodes_stat.nr_inodes--; |
1008 | spin_unlock(&inode_lock); | 1008 | spin_unlock(&inode_lock); |
1009 | 1009 | ||
@@ -1210,13 +1210,15 @@ void file_update_time(struct file *file) | |||
1210 | return; | 1210 | return; |
1211 | 1211 | ||
1212 | now = current_fs_time(inode->i_sb); | 1212 | now = current_fs_time(inode->i_sb); |
1213 | if (!timespec_equal(&inode->i_mtime, &now)) | 1213 | if (!timespec_equal(&inode->i_mtime, &now)) { |
1214 | inode->i_mtime = now; | ||
1214 | sync_it = 1; | 1215 | sync_it = 1; |
1215 | inode->i_mtime = now; | 1216 | } |
1216 | 1217 | ||
1217 | if (!timespec_equal(&inode->i_ctime, &now)) | 1218 | if (!timespec_equal(&inode->i_ctime, &now)) { |
1219 | inode->i_ctime = now; | ||
1218 | sync_it = 1; | 1220 | sync_it = 1; |
1219 | inode->i_ctime = now; | 1221 | } |
1220 | 1222 | ||
1221 | if (sync_it) | 1223 | if (sync_it) |
1222 | mark_inode_dirty_sync(inode); | 1224 | mark_inode_dirty_sync(inode); |
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index f95cc3f3c42d..87e1d03e8267 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -202,7 +202,7 @@ reclaimer(void *ptr) | |||
202 | /* This one ensures that our parent doesn't terminate while the | 202 | /* This one ensures that our parent doesn't terminate while the |
203 | * reclaim is in progress */ | 203 | * reclaim is in progress */ |
204 | lock_kernel(); | 204 | lock_kernel(); |
205 | lockd_up(); | 205 | lockd_up(0); /* note: this cannot fail as lockd is already running */ |
206 | 206 | ||
207 | nlmclnt_prepare_reclaim(host); | 207 | nlmclnt_prepare_reclaim(host); |
208 | /* First, reclaim all locks that have been marked. */ | 208 | /* First, reclaim all locks that have been marked. */ |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 271e2165fff6..0116729cec5f 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -129,11 +129,11 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) | |||
129 | nlmclnt_next_cookie(&argp->cookie); | 129 | nlmclnt_next_cookie(&argp->cookie); |
130 | argp->state = nsm_local_state; | 130 | argp->state = nsm_local_state; |
131 | memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh)); | 131 | memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh)); |
132 | lock->caller = system_utsname.nodename; | 132 | lock->caller = utsname()->nodename; |
133 | lock->oh.data = req->a_owner; | 133 | lock->oh.data = req->a_owner; |
134 | lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", | 134 | lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", |
135 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, | 135 | (unsigned int)fl->fl_u.nfs_fl.owner->pid, |
136 | system_utsname.nodename); | 136 | utsname()->nodename); |
137 | lock->svid = fl->fl_u.nfs_fl.owner->pid; | 137 | lock->svid = fl->fl_u.nfs_fl.owner->pid; |
138 | lock->fl.fl_start = fl->fl_start; | 138 | lock->fl.fl_start = fl->fl_start; |
139 | lock->fl.fl_end = fl->fl_end; | 139 | lock->fl.fl_end = fl->fl_end; |
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 5954dcb497e4..a816b920d431 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
@@ -145,7 +145,7 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) | |||
145 | */ | 145 | */ |
146 | sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); | 146 | sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); |
147 | if (!(p = xdr_encode_string(p, buffer)) | 147 | if (!(p = xdr_encode_string(p, buffer)) |
148 | || !(p = xdr_encode_string(p, system_utsname.nodename))) | 148 | || !(p = xdr_encode_string(p, utsname()->nodename))) |
149 | return ERR_PTR(-EIO); | 149 | return ERR_PTR(-EIO); |
150 | *p++ = htonl(argp->prog); | 150 | *p++ = htonl(argp->prog); |
151 | *p++ = htonl(argp->vers); | 151 | *p++ = htonl(argp->vers); |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 9a991b52c647..3cc369e5693f 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/sunrpc/clnt.h> | 31 | #include <linux/sunrpc/clnt.h> |
32 | #include <linux/sunrpc/svc.h> | 32 | #include <linux/sunrpc/svc.h> |
33 | #include <linux/sunrpc/svcsock.h> | 33 | #include <linux/sunrpc/svcsock.h> |
34 | #include <net/ip.h> | ||
34 | #include <linux/lockd/lockd.h> | 35 | #include <linux/lockd/lockd.h> |
35 | #include <linux/nfs.h> | 36 | #include <linux/nfs.h> |
36 | 37 | ||
@@ -46,6 +47,7 @@ EXPORT_SYMBOL(nlmsvc_ops); | |||
46 | static DEFINE_MUTEX(nlmsvc_mutex); | 47 | static DEFINE_MUTEX(nlmsvc_mutex); |
47 | static unsigned int nlmsvc_users; | 48 | static unsigned int nlmsvc_users; |
48 | static pid_t nlmsvc_pid; | 49 | static pid_t nlmsvc_pid; |
50 | static struct svc_serv *nlmsvc_serv; | ||
49 | int nlmsvc_grace_period; | 51 | int nlmsvc_grace_period; |
50 | unsigned long nlmsvc_timeout; | 52 | unsigned long nlmsvc_timeout; |
51 | 53 | ||
@@ -96,7 +98,6 @@ static inline void clear_grace_period(void) | |||
96 | static void | 98 | static void |
97 | lockd(struct svc_rqst *rqstp) | 99 | lockd(struct svc_rqst *rqstp) |
98 | { | 100 | { |
99 | struct svc_serv *serv = rqstp->rq_server; | ||
100 | int err = 0; | 101 | int err = 0; |
101 | unsigned long grace_period_expire; | 102 | unsigned long grace_period_expire; |
102 | 103 | ||
@@ -112,6 +113,7 @@ lockd(struct svc_rqst *rqstp) | |||
112 | * Let our maker know we're running. | 113 | * Let our maker know we're running. |
113 | */ | 114 | */ |
114 | nlmsvc_pid = current->pid; | 115 | nlmsvc_pid = current->pid; |
116 | nlmsvc_serv = rqstp->rq_server; | ||
115 | complete(&lockd_start_done); | 117 | complete(&lockd_start_done); |
116 | 118 | ||
117 | daemonize("lockd"); | 119 | daemonize("lockd"); |
@@ -161,7 +163,7 @@ lockd(struct svc_rqst *rqstp) | |||
161 | * Find a socket with data available and call its | 163 | * Find a socket with data available and call its |
162 | * recvfrom routine. | 164 | * recvfrom routine. |
163 | */ | 165 | */ |
164 | err = svc_recv(serv, rqstp, timeout); | 166 | err = svc_recv(rqstp, timeout); |
165 | if (err == -EAGAIN || err == -EINTR) | 167 | if (err == -EAGAIN || err == -EINTR) |
166 | continue; | 168 | continue; |
167 | if (err < 0) { | 169 | if (err < 0) { |
@@ -174,7 +176,7 @@ lockd(struct svc_rqst *rqstp) | |||
174 | dprintk("lockd: request from %08x\n", | 176 | dprintk("lockd: request from %08x\n", |
175 | (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); | 177 | (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); |
176 | 178 | ||
177 | svc_process(serv, rqstp); | 179 | svc_process(rqstp); |
178 | 180 | ||
179 | } | 181 | } |
180 | 182 | ||
@@ -189,6 +191,7 @@ lockd(struct svc_rqst *rqstp) | |||
189 | nlmsvc_invalidate_all(); | 191 | nlmsvc_invalidate_all(); |
190 | nlm_shutdown_hosts(); | 192 | nlm_shutdown_hosts(); |
191 | nlmsvc_pid = 0; | 193 | nlmsvc_pid = 0; |
194 | nlmsvc_serv = NULL; | ||
192 | } else | 195 | } else |
193 | printk(KERN_DEBUG | 196 | printk(KERN_DEBUG |
194 | "lockd: new process, skipping host shutdown\n"); | 197 | "lockd: new process, skipping host shutdown\n"); |
@@ -205,54 +208,77 @@ lockd(struct svc_rqst *rqstp) | |||
205 | module_put_and_exit(0); | 208 | module_put_and_exit(0); |
206 | } | 209 | } |
207 | 210 | ||
211 | |||
212 | static int find_socket(struct svc_serv *serv, int proto) | ||
213 | { | ||
214 | struct svc_sock *svsk; | ||
215 | int found = 0; | ||
216 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | ||
217 | if (svsk->sk_sk->sk_protocol == proto) { | ||
218 | found = 1; | ||
219 | break; | ||
220 | } | ||
221 | return found; | ||
222 | } | ||
223 | |||
224 | static int make_socks(struct svc_serv *serv, int proto) | ||
225 | { | ||
226 | /* Make any sockets that are needed but not present. | ||
227 | * If nlm_udpport or nlm_tcpport were set as module | ||
228 | * options, make those sockets unconditionally | ||
229 | */ | ||
230 | static int warned; | ||
231 | int err = 0; | ||
232 | if (proto == IPPROTO_UDP || nlm_udpport) | ||
233 | if (!find_socket(serv, IPPROTO_UDP)) | ||
234 | err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport); | ||
235 | if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport)) | ||
236 | if (!find_socket(serv, IPPROTO_TCP)) | ||
237 | err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport); | ||
238 | if (!err) | ||
239 | warned = 0; | ||
240 | else if (warned++ == 0) | ||
241 | printk(KERN_WARNING | ||
242 | "lockd_up: makesock failed, error=%d\n", err); | ||
243 | return err; | ||
244 | } | ||
245 | |||
208 | /* | 246 | /* |
209 | * Bring up the lockd process if it's not already up. | 247 | * Bring up the lockd process if it's not already up. |
210 | */ | 248 | */ |
211 | int | 249 | int |
212 | lockd_up(void) | 250 | lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */ |
213 | { | 251 | { |
214 | static int warned; | ||
215 | struct svc_serv * serv; | 252 | struct svc_serv * serv; |
216 | int error = 0; | 253 | int error = 0; |
217 | 254 | ||
218 | mutex_lock(&nlmsvc_mutex); | 255 | mutex_lock(&nlmsvc_mutex); |
219 | /* | 256 | /* |
220 | * Unconditionally increment the user count ... this is | ||
221 | * the number of clients who _want_ a lockd process. | ||
222 | */ | ||
223 | nlmsvc_users++; | ||
224 | /* | ||
225 | * Check whether we're already up and running. | 257 | * Check whether we're already up and running. |
226 | */ | 258 | */ |
227 | if (nlmsvc_pid) | 259 | if (nlmsvc_pid) { |
260 | if (proto) | ||
261 | error = make_socks(nlmsvc_serv, proto); | ||
228 | goto out; | 262 | goto out; |
263 | } | ||
229 | 264 | ||
230 | /* | 265 | /* |
231 | * Sanity check: if there's no pid, | 266 | * Sanity check: if there's no pid, |
232 | * we should be the first user ... | 267 | * we should be the first user ... |
233 | */ | 268 | */ |
234 | if (nlmsvc_users > 1) | 269 | if (nlmsvc_users) |
235 | printk(KERN_WARNING | 270 | printk(KERN_WARNING |
236 | "lockd_up: no pid, %d users??\n", nlmsvc_users); | 271 | "lockd_up: no pid, %d users??\n", nlmsvc_users); |
237 | 272 | ||
238 | error = -ENOMEM; | 273 | error = -ENOMEM; |
239 | serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE); | 274 | serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); |
240 | if (!serv) { | 275 | if (!serv) { |
241 | printk(KERN_WARNING "lockd_up: create service failed\n"); | 276 | printk(KERN_WARNING "lockd_up: create service failed\n"); |
242 | goto out; | 277 | goto out; |
243 | } | 278 | } |
244 | 279 | ||
245 | if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0 | 280 | if ((error = make_socks(serv, proto)) < 0) |
246 | #ifdef CONFIG_NFSD_TCP | ||
247 | || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0 | ||
248 | #endif | ||
249 | ) { | ||
250 | if (warned++ == 0) | ||
251 | printk(KERN_WARNING | ||
252 | "lockd_up: makesock failed, error=%d\n", error); | ||
253 | goto destroy_and_out; | 281 | goto destroy_and_out; |
254 | } | ||
255 | warned = 0; | ||
256 | 282 | ||
257 | /* | 283 | /* |
258 | * Create the kernel thread and wait for it to start. | 284 | * Create the kernel thread and wait for it to start. |
@@ -272,6 +298,8 @@ lockd_up(void) | |||
272 | destroy_and_out: | 298 | destroy_and_out: |
273 | svc_destroy(serv); | 299 | svc_destroy(serv); |
274 | out: | 300 | out: |
301 | if (!error) | ||
302 | nlmsvc_users++; | ||
275 | mutex_unlock(&nlmsvc_mutex); | 303 | mutex_unlock(&nlmsvc_mutex); |
276 | return error; | 304 | return error; |
277 | } | 305 | } |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index c9d419703cf3..93c00ee7189d 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -325,7 +325,7 @@ static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) | |||
325 | { | 325 | { |
326 | locks_copy_lock(&call->a_args.lock.fl, &lock->fl); | 326 | locks_copy_lock(&call->a_args.lock.fl, &lock->fl); |
327 | memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); | 327 | memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); |
328 | call->a_args.lock.caller = system_utsname.nodename; | 328 | call->a_args.lock.caller = utsname()->nodename; |
329 | call->a_args.lock.oh.len = lock->oh.len; | 329 | call->a_args.lock.oh.len = lock->oh.len; |
330 | 330 | ||
331 | /* set default data area */ | 331 | /* set default data area */ |
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 033ea4ac2c30..61c46facf257 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c | |||
@@ -515,7 +515,7 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) | |||
515 | */ | 515 | */ |
516 | #define NLM_void_sz 0 | 516 | #define NLM_void_sz 0 |
517 | #define NLM_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) | 517 | #define NLM_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) |
518 | #define NLM_caller_sz 1+XDR_QUADLEN(sizeof(system_utsname.nodename)) | 518 | #define NLM_caller_sz 1+XDR_QUADLEN(sizeof(utsname()->nodename)) |
519 | #define NLM_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) | 519 | #define NLM_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) |
520 | /* #define NLM_owner_sz 1+XDR_QUADLEN(NLM_MAXOWNER) */ | 520 | /* #define NLM_owner_sz 1+XDR_QUADLEN(NLM_MAXOWNER) */ |
521 | #define NLM_fhandle_sz 1+XDR_QUADLEN(NFS2_FHSIZE) | 521 | #define NLM_fhandle_sz 1+XDR_QUADLEN(NFS2_FHSIZE) |
diff --git a/fs/locks.c b/fs/locks.c index 21dfadfca2bc..e0b6a80649a0 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1514,7 +1514,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | |||
1514 | goto out_unlock; | 1514 | goto out_unlock; |
1515 | } | 1515 | } |
1516 | 1516 | ||
1517 | error = f_setown(filp, current->pid, 0); | 1517 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
1518 | out_unlock: | 1518 | out_unlock: |
1519 | unlock_kernel(); | 1519 | unlock_kernel(); |
1520 | return error; | 1520 | return error; |
diff --git a/fs/namespace.c b/fs/namespace.c index 66d921e14fee..55442a6cf221 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -133,7 +133,7 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | |||
133 | 133 | ||
134 | static inline int check_mnt(struct vfsmount *mnt) | 134 | static inline int check_mnt(struct vfsmount *mnt) |
135 | { | 135 | { |
136 | return mnt->mnt_namespace == current->namespace; | 136 | return mnt->mnt_namespace == current->nsproxy->namespace; |
137 | } | 137 | } |
138 | 138 | ||
139 | static void touch_namespace(struct namespace *ns) | 139 | static void touch_namespace(struct namespace *ns) |
@@ -830,7 +830,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
830 | if (parent_nd) { | 830 | if (parent_nd) { |
831 | detach_mnt(source_mnt, parent_nd); | 831 | detach_mnt(source_mnt, parent_nd); |
832 | attach_mnt(source_mnt, nd); | 832 | attach_mnt(source_mnt, nd); |
833 | touch_namespace(current->namespace); | 833 | touch_namespace(current->nsproxy->namespace); |
834 | } else { | 834 | } else { |
835 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); | 835 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); |
836 | commit_tree(source_mnt); | 836 | commit_tree(source_mnt); |
@@ -1441,7 +1441,7 @@ dput_out: | |||
1441 | */ | 1441 | */ |
1442 | struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) | 1442 | struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) |
1443 | { | 1443 | { |
1444 | struct namespace *namespace = tsk->namespace; | 1444 | struct namespace *namespace = tsk->nsproxy->namespace; |
1445 | struct namespace *new_ns; | 1445 | struct namespace *new_ns; |
1446 | struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; | 1446 | struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; |
1447 | struct vfsmount *p, *q; | 1447 | struct vfsmount *p, *q; |
@@ -1508,7 +1508,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) | |||
1508 | 1508 | ||
1509 | int copy_namespace(int flags, struct task_struct *tsk) | 1509 | int copy_namespace(int flags, struct task_struct *tsk) |
1510 | { | 1510 | { |
1511 | struct namespace *namespace = tsk->namespace; | 1511 | struct namespace *namespace = tsk->nsproxy->namespace; |
1512 | struct namespace *new_ns; | 1512 | struct namespace *new_ns; |
1513 | int err = 0; | 1513 | int err = 0; |
1514 | 1514 | ||
@@ -1531,7 +1531,7 @@ int copy_namespace(int flags, struct task_struct *tsk) | |||
1531 | goto out; | 1531 | goto out; |
1532 | } | 1532 | } |
1533 | 1533 | ||
1534 | tsk->namespace = new_ns; | 1534 | tsk->nsproxy->namespace = new_ns; |
1535 | 1535 | ||
1536 | out: | 1536 | out: |
1537 | put_namespace(namespace); | 1537 | put_namespace(namespace); |
@@ -1754,7 +1754,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1754 | detach_mnt(user_nd.mnt, &root_parent); | 1754 | detach_mnt(user_nd.mnt, &root_parent); |
1755 | attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ | 1755 | attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ |
1756 | attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ | 1756 | attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ |
1757 | touch_namespace(current->namespace); | 1757 | touch_namespace(current->nsproxy->namespace); |
1758 | spin_unlock(&vfsmount_lock); | 1758 | spin_unlock(&vfsmount_lock); |
1759 | chroot_fs_refs(&user_nd, &new_nd); | 1759 | chroot_fs_refs(&user_nd, &new_nd); |
1760 | security_sb_post_pivotroot(&user_nd, &new_nd); | 1760 | security_sb_post_pivotroot(&user_nd, &new_nd); |
@@ -1780,7 +1780,6 @@ static void __init init_mount_tree(void) | |||
1780 | { | 1780 | { |
1781 | struct vfsmount *mnt; | 1781 | struct vfsmount *mnt; |
1782 | struct namespace *namespace; | 1782 | struct namespace *namespace; |
1783 | struct task_struct *g, *p; | ||
1784 | 1783 | ||
1785 | mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); | 1784 | mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); |
1786 | if (IS_ERR(mnt)) | 1785 | if (IS_ERR(mnt)) |
@@ -1796,13 +1795,8 @@ static void __init init_mount_tree(void) | |||
1796 | namespace->root = mnt; | 1795 | namespace->root = mnt; |
1797 | mnt->mnt_namespace = namespace; | 1796 | mnt->mnt_namespace = namespace; |
1798 | 1797 | ||
1799 | init_task.namespace = namespace; | 1798 | init_task.nsproxy->namespace = namespace; |
1800 | read_lock(&tasklist_lock); | 1799 | get_namespace(namespace); |
1801 | do_each_thread(g, p) { | ||
1802 | get_namespace(namespace); | ||
1803 | p->namespace = namespace; | ||
1804 | } while_each_thread(g, p); | ||
1805 | read_unlock(&tasklist_lock); | ||
1806 | 1800 | ||
1807 | set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root); | 1801 | set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root); |
1808 | set_fs_root(current->fs, namespace->root, namespace->root->mnt_root); | 1802 | set_fs_root(current->fs, namespace->root, namespace->root->mnt_root); |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index a3ee11364db0..7933e2e99dbc 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -58,7 +58,6 @@ module_param_call(callback_tcpport, param_set_port, param_get_int, | |||
58 | */ | 58 | */ |
59 | static void nfs_callback_svc(struct svc_rqst *rqstp) | 59 | static void nfs_callback_svc(struct svc_rqst *rqstp) |
60 | { | 60 | { |
61 | struct svc_serv *serv = rqstp->rq_server; | ||
62 | int err; | 61 | int err; |
63 | 62 | ||
64 | __module_get(THIS_MODULE); | 63 | __module_get(THIS_MODULE); |
@@ -80,7 +79,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
80 | /* | 79 | /* |
81 | * Listen for a request on the socket | 80 | * Listen for a request on the socket |
82 | */ | 81 | */ |
83 | err = svc_recv(serv, rqstp, MAX_SCHEDULE_TIMEOUT); | 82 | err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); |
84 | if (err == -EAGAIN || err == -EINTR) | 83 | if (err == -EAGAIN || err == -EINTR) |
85 | continue; | 84 | continue; |
86 | if (err < 0) { | 85 | if (err < 0) { |
@@ -91,7 +90,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
91 | } | 90 | } |
92 | dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__, | 91 | dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__, |
93 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr)); | 92 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr)); |
94 | svc_process(serv, rqstp); | 93 | svc_process(rqstp); |
95 | } | 94 | } |
96 | 95 | ||
97 | svc_exit_thread(rqstp); | 96 | svc_exit_thread(rqstp); |
@@ -116,7 +115,7 @@ int nfs_callback_up(void) | |||
116 | goto out; | 115 | goto out; |
117 | init_completion(&nfs_callback_info.started); | 116 | init_completion(&nfs_callback_info.started); |
118 | init_completion(&nfs_callback_info.stopped); | 117 | init_completion(&nfs_callback_info.stopped); |
119 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE); | 118 | serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); |
120 | ret = -ENOMEM; | 119 | ret = -ENOMEM; |
121 | if (!serv) | 120 | if (!serv) |
122 | goto out_err; | 121 | goto out_err; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ec1938d4b814..8106f3b29e4a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -460,7 +460,8 @@ static int nfs_start_lockd(struct nfs_server *server) | |||
460 | goto out; | 460 | goto out; |
461 | if (server->flags & NFS_MOUNT_NONLM) | 461 | if (server->flags & NFS_MOUNT_NONLM) |
462 | goto out; | 462 | goto out; |
463 | error = lockd_up(); | 463 | error = lockd_up((server->flags & NFS_MOUNT_TCP) ? |
464 | IPPROTO_TCP : IPPROTO_UDP); | ||
464 | if (error < 0) | 465 | if (error < 0) |
465 | server->flags |= NFS_MOUNT_NONLM; | 466 | server->flags |= NFS_MOUNT_NONLM; |
466 | else | 467 | else |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index c0a754ecdee6..1d656a645199 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -312,7 +312,7 @@ static int __init root_nfs_name(char *name) | |||
312 | /* Override them by options set on kernel command-line */ | 312 | /* Override them by options set on kernel command-line */ |
313 | root_nfs_parse(name, buf); | 313 | root_nfs_parse(name, buf); |
314 | 314 | ||
315 | cp = system_utsname.nodename; | 315 | cp = utsname()->nodename; |
316 | if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) { | 316 | if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) { |
317 | printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n"); | 317 | printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n"); |
318 | return -1; | 318 | return -1; |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 01bc68c628ad..cfe141e5d759 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -370,7 +370,7 @@ static int check_export(struct inode *inode, int flags) | |||
370 | */ | 370 | */ |
371 | if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && | 371 | if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && |
372 | !(flags & NFSEXP_FSID)) { | 372 | !(flags & NFSEXP_FSID)) { |
373 | dprintk("exp_export: export of non-dev fs without fsid"); | 373 | dprintk("exp_export: export of non-dev fs without fsid\n"); |
374 | return -EINVAL; | 374 | return -EINVAL; |
375 | } | 375 | } |
376 | if (!inode->i_sb->s_export_op) { | 376 | if (!inode->i_sb->s_export_op) { |
@@ -1078,6 +1078,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
1078 | /* Iterator */ | 1078 | /* Iterator */ |
1079 | 1079 | ||
1080 | static void *e_start(struct seq_file *m, loff_t *pos) | 1080 | static void *e_start(struct seq_file *m, loff_t *pos) |
1081 | __acquires(svc_export_cache.hash_lock) | ||
1081 | { | 1082 | { |
1082 | loff_t n = *pos; | 1083 | loff_t n = *pos; |
1083 | unsigned hash, export; | 1084 | unsigned hash, export; |
@@ -1086,7 +1087,7 @@ static void *e_start(struct seq_file *m, loff_t *pos) | |||
1086 | exp_readlock(); | 1087 | exp_readlock(); |
1087 | read_lock(&svc_export_cache.hash_lock); | 1088 | read_lock(&svc_export_cache.hash_lock); |
1088 | if (!n--) | 1089 | if (!n--) |
1089 | return (void *)1; | 1090 | return SEQ_START_TOKEN; |
1090 | hash = n >> 32; | 1091 | hash = n >> 32; |
1091 | export = n & ((1LL<<32) - 1); | 1092 | export = n & ((1LL<<32) - 1); |
1092 | 1093 | ||
@@ -1110,7 +1111,7 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) | |||
1110 | struct cache_head *ch = p; | 1111 | struct cache_head *ch = p; |
1111 | int hash = (*pos >> 32); | 1112 | int hash = (*pos >> 32); |
1112 | 1113 | ||
1113 | if (p == (void *)1) | 1114 | if (p == SEQ_START_TOKEN) |
1114 | hash = 0; | 1115 | hash = 0; |
1115 | else if (ch->next == NULL) { | 1116 | else if (ch->next == NULL) { |
1116 | hash++; | 1117 | hash++; |
@@ -1131,6 +1132,7 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) | |||
1131 | } | 1132 | } |
1132 | 1133 | ||
1133 | static void e_stop(struct seq_file *m, void *p) | 1134 | static void e_stop(struct seq_file *m, void *p) |
1135 | __releases(svc_export_cache.hash_lock) | ||
1134 | { | 1136 | { |
1135 | read_unlock(&svc_export_cache.hash_lock); | 1137 | read_unlock(&svc_export_cache.hash_lock); |
1136 | exp_readunlock(); | 1138 | exp_readunlock(); |
@@ -1178,15 +1180,13 @@ static int e_show(struct seq_file *m, void *p) | |||
1178 | { | 1180 | { |
1179 | struct cache_head *cp = p; | 1181 | struct cache_head *cp = p; |
1180 | struct svc_export *exp = container_of(cp, struct svc_export, h); | 1182 | struct svc_export *exp = container_of(cp, struct svc_export, h); |
1181 | svc_client *clp; | ||
1182 | 1183 | ||
1183 | if (p == (void *)1) { | 1184 | if (p == SEQ_START_TOKEN) { |
1184 | seq_puts(m, "# Version 1.1\n"); | 1185 | seq_puts(m, "# Version 1.1\n"); |
1185 | seq_puts(m, "# Path Client(Flags) # IPs\n"); | 1186 | seq_puts(m, "# Path Client(Flags) # IPs\n"); |
1186 | return 0; | 1187 | return 0; |
1187 | } | 1188 | } |
1188 | 1189 | ||
1189 | clp = exp->ex_client; | ||
1190 | cache_get(&exp->h); | 1190 | cache_get(&exp->h); |
1191 | if (cache_check(&svc_export_cache, &exp->h, NULL)) | 1191 | if (cache_check(&svc_export_cache, &exp->h, NULL)) |
1192 | return 0; | 1192 | return 0; |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 8583d99ee740..f6ca9fb3fc63 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -131,7 +131,7 @@ xdr_error: \ | |||
131 | #define READ_BUF(nbytes) do { \ | 131 | #define READ_BUF(nbytes) do { \ |
132 | p = xdr_inline_decode(xdr, nbytes); \ | 132 | p = xdr_inline_decode(xdr, nbytes); \ |
133 | if (!p) { \ | 133 | if (!p) { \ |
134 | dprintk("NFSD: %s: reply buffer overflowed in line %d.", \ | 134 | dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \ |
135 | __FUNCTION__, __LINE__); \ | 135 | __FUNCTION__, __LINE__); \ |
136 | return -EIO; \ | 136 | return -EIO; \ |
137 | } \ | 137 | } \ |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index ee4eff27aedc..15ded7a30a72 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -600,7 +600,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se | |||
600 | &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); | 600 | &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); |
601 | nfs4_unlock_state(); | 601 | nfs4_unlock_state(); |
602 | if (status) { | 602 | if (status) { |
603 | dprintk("NFSD: nfsd4_setattr: couldn't process stateid!"); | 603 | dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); |
604 | return status; | 604 | return status; |
605 | } | 605 | } |
606 | } | 606 | } |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 7046ac9cf97f..5c6a477c20ec 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -23,10 +23,14 @@ | |||
23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/ctype.h> | ||
26 | 28 | ||
27 | #include <linux/nfs.h> | 29 | #include <linux/nfs.h> |
28 | #include <linux/nfsd_idmap.h> | 30 | #include <linux/nfsd_idmap.h> |
31 | #include <linux/lockd/bind.h> | ||
29 | #include <linux/sunrpc/svc.h> | 32 | #include <linux/sunrpc/svc.h> |
33 | #include <linux/sunrpc/svcsock.h> | ||
30 | #include <linux/nfsd/nfsd.h> | 34 | #include <linux/nfsd/nfsd.h> |
31 | #include <linux/nfsd/cache.h> | 35 | #include <linux/nfsd/cache.h> |
32 | #include <linux/nfsd/xdr.h> | 36 | #include <linux/nfsd/xdr.h> |
@@ -35,8 +39,6 @@ | |||
35 | 39 | ||
36 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
37 | 41 | ||
38 | unsigned int nfsd_versbits = ~0; | ||
39 | |||
40 | /* | 42 | /* |
41 | * We have a single directory with 9 nodes in it. | 43 | * We have a single directory with 9 nodes in it. |
42 | */ | 44 | */ |
@@ -52,7 +54,9 @@ enum { | |||
52 | NFSD_List, | 54 | NFSD_List, |
53 | NFSD_Fh, | 55 | NFSD_Fh, |
54 | NFSD_Threads, | 56 | NFSD_Threads, |
57 | NFSD_Pool_Threads, | ||
55 | NFSD_Versions, | 58 | NFSD_Versions, |
59 | NFSD_Ports, | ||
56 | /* | 60 | /* |
57 | * The below MUST come last. Otherwise we leave a hole in nfsd_files[] | 61 | * The below MUST come last. Otherwise we leave a hole in nfsd_files[] |
58 | * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops | 62 | * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops |
@@ -75,7 +79,9 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); | |||
75 | static ssize_t write_getfs(struct file *file, char *buf, size_t size); | 79 | static ssize_t write_getfs(struct file *file, char *buf, size_t size); |
76 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size); | 80 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size); |
77 | static ssize_t write_threads(struct file *file, char *buf, size_t size); | 81 | static ssize_t write_threads(struct file *file, char *buf, size_t size); |
82 | static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); | ||
78 | static ssize_t write_versions(struct file *file, char *buf, size_t size); | 83 | static ssize_t write_versions(struct file *file, char *buf, size_t size); |
84 | static ssize_t write_ports(struct file *file, char *buf, size_t size); | ||
79 | #ifdef CONFIG_NFSD_V4 | 85 | #ifdef CONFIG_NFSD_V4 |
80 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size); | 86 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size); |
81 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); | 87 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); |
@@ -91,7 +97,9 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { | |||
91 | [NFSD_Getfs] = write_getfs, | 97 | [NFSD_Getfs] = write_getfs, |
92 | [NFSD_Fh] = write_filehandle, | 98 | [NFSD_Fh] = write_filehandle, |
93 | [NFSD_Threads] = write_threads, | 99 | [NFSD_Threads] = write_threads, |
100 | [NFSD_Pool_Threads] = write_pool_threads, | ||
94 | [NFSD_Versions] = write_versions, | 101 | [NFSD_Versions] = write_versions, |
102 | [NFSD_Ports] = write_ports, | ||
95 | #ifdef CONFIG_NFSD_V4 | 103 | #ifdef CONFIG_NFSD_V4 |
96 | [NFSD_Leasetime] = write_leasetime, | 104 | [NFSD_Leasetime] = write_leasetime, |
97 | [NFSD_RecoveryDir] = write_recoverydir, | 105 | [NFSD_RecoveryDir] = write_recoverydir, |
@@ -358,6 +366,72 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) | |||
358 | return strlen(buf); | 366 | return strlen(buf); |
359 | } | 367 | } |
360 | 368 | ||
369 | extern int nfsd_nrpools(void); | ||
370 | extern int nfsd_get_nrthreads(int n, int *); | ||
371 | extern int nfsd_set_nrthreads(int n, int *); | ||
372 | |||
373 | static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | ||
374 | { | ||
375 | /* if size > 0, look for an array of number of threads per node | ||
376 | * and apply them then write out number of threads per node as reply | ||
377 | */ | ||
378 | char *mesg = buf; | ||
379 | int i; | ||
380 | int rv; | ||
381 | int len; | ||
382 | int npools = nfsd_nrpools(); | ||
383 | int *nthreads; | ||
384 | |||
385 | if (npools == 0) { | ||
386 | /* | ||
387 | * NFS is shut down. The admin can start it by | ||
388 | * writing to the threads file but NOT the pool_threads | ||
389 | * file, sorry. Report zero threads. | ||
390 | */ | ||
391 | strcpy(buf, "0\n"); | ||
392 | return strlen(buf); | ||
393 | } | ||
394 | |||
395 | nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); | ||
396 | if (nthreads == NULL) | ||
397 | return -ENOMEM; | ||
398 | |||
399 | if (size > 0) { | ||
400 | for (i = 0; i < npools; i++) { | ||
401 | rv = get_int(&mesg, &nthreads[i]); | ||
402 | if (rv == -ENOENT) | ||
403 | break; /* fewer numbers than pools */ | ||
404 | if (rv) | ||
405 | goto out_free; /* syntax error */ | ||
406 | rv = -EINVAL; | ||
407 | if (nthreads[i] < 0) | ||
408 | goto out_free; | ||
409 | } | ||
410 | rv = nfsd_set_nrthreads(i, nthreads); | ||
411 | if (rv) | ||
412 | goto out_free; | ||
413 | } | ||
414 | |||
415 | rv = nfsd_get_nrthreads(npools, nthreads); | ||
416 | if (rv) | ||
417 | goto out_free; | ||
418 | |||
419 | mesg = buf; | ||
420 | size = SIMPLE_TRANSACTION_LIMIT; | ||
421 | for (i = 0; i < npools && size > 0; i++) { | ||
422 | snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' ')); | ||
423 | len = strlen(mesg); | ||
424 | size -= len; | ||
425 | mesg += len; | ||
426 | } | ||
427 | |||
428 | return (mesg-buf); | ||
429 | |||
430 | out_free: | ||
431 | kfree(nthreads); | ||
432 | return rv; | ||
433 | } | ||
434 | |||
361 | static ssize_t write_versions(struct file *file, char *buf, size_t size) | 435 | static ssize_t write_versions(struct file *file, char *buf, size_t size) |
362 | { | 436 | { |
363 | /* | 437 | /* |
@@ -372,6 +446,10 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
372 | 446 | ||
373 | if (size>0) { | 447 | if (size>0) { |
374 | if (nfsd_serv) | 448 | if (nfsd_serv) |
449 | /* Cannot change versions without updating | ||
450 | * nfsd_serv->sv_xdrsize, and reallocing | ||
451 | * rq_argp and rq_resp | ||
452 | */ | ||
375 | return -EBUSY; | 453 | return -EBUSY; |
376 | if (buf[size-1] != '\n') | 454 | if (buf[size-1] != '\n') |
377 | return -EINVAL; | 455 | return -EINVAL; |
@@ -390,10 +468,7 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
390 | case 2: | 468 | case 2: |
391 | case 3: | 469 | case 3: |
392 | case 4: | 470 | case 4: |
393 | if (sign != '-') | 471 | nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET); |
394 | NFSCTL_VERSET(nfsd_versbits, num); | ||
395 | else | ||
396 | NFSCTL_VERUNSET(nfsd_versbits, num); | ||
397 | break; | 472 | break; |
398 | default: | 473 | default: |
399 | return -EINVAL; | 474 | return -EINVAL; |
@@ -404,16 +479,15 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
404 | /* If all get turned off, turn them back on, as | 479 | /* If all get turned off, turn them back on, as |
405 | * having no versions is BAD | 480 | * having no versions is BAD |
406 | */ | 481 | */ |
407 | if ((nfsd_versbits & NFSCTL_VERALL)==0) | 482 | nfsd_reset_versions(); |
408 | nfsd_versbits = NFSCTL_VERALL; | ||
409 | } | 483 | } |
410 | /* Now write current state into reply buffer */ | 484 | /* Now write current state into reply buffer */ |
411 | len = 0; | 485 | len = 0; |
412 | sep = ""; | 486 | sep = ""; |
413 | for (num=2 ; num <= 4 ; num++) | 487 | for (num=2 ; num <= 4 ; num++) |
414 | if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { | 488 | if (nfsd_vers(num, NFSD_AVAIL)) { |
415 | len += sprintf(buf+len, "%s%c%d", sep, | 489 | len += sprintf(buf+len, "%s%c%d", sep, |
416 | NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', | 490 | nfsd_vers(num, NFSD_TEST)?'+':'-', |
417 | num); | 491 | num); |
418 | sep = " "; | 492 | sep = " "; |
419 | } | 493 | } |
@@ -421,6 +495,62 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
421 | return len; | 495 | return len; |
422 | } | 496 | } |
423 | 497 | ||
498 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | ||
499 | { | ||
500 | if (size == 0) { | ||
501 | int len = 0; | ||
502 | lock_kernel(); | ||
503 | if (nfsd_serv) | ||
504 | len = svc_sock_names(buf, nfsd_serv, NULL); | ||
505 | unlock_kernel(); | ||
506 | return len; | ||
507 | } | ||
508 | /* Either a single 'fd' number is written, in which | ||
509 | * case it must be for a socket of a supported family/protocol, | ||
510 | * and we use it as an nfsd socket, or | ||
511 | * A '-' followed by the 'name' of a socket in which case | ||
512 | * we close the socket. | ||
513 | */ | ||
514 | if (isdigit(buf[0])) { | ||
515 | char *mesg = buf; | ||
516 | int fd; | ||
517 | int err; | ||
518 | err = get_int(&mesg, &fd); | ||
519 | if (err) | ||
520 | return -EINVAL; | ||
521 | if (fd < 0) | ||
522 | return -EINVAL; | ||
523 | err = nfsd_create_serv(); | ||
524 | if (!err) { | ||
525 | int proto = 0; | ||
526 | err = lockd_up(proto); | ||
527 | if (!err) { | ||
528 | err = svc_addsock(nfsd_serv, fd, buf, &proto); | ||
529 | if (err) | ||
530 | lockd_down(); | ||
531 | } | ||
532 | /* Decrease the count, but don't shutdown the | ||
533 | * the service | ||
534 | */ | ||
535 | nfsd_serv->sv_nrthreads--; | ||
536 | } | ||
537 | return err; | ||
538 | } | ||
539 | if (buf[0] == '-') { | ||
540 | char *toclose = kstrdup(buf+1, GFP_KERNEL); | ||
541 | int len = 0; | ||
542 | if (!toclose) | ||
543 | return -ENOMEM; | ||
544 | lock_kernel(); | ||
545 | if (nfsd_serv) | ||
546 | len = svc_sock_names(buf, nfsd_serv, toclose); | ||
547 | unlock_kernel(); | ||
548 | kfree(toclose); | ||
549 | return len; | ||
550 | } | ||
551 | return -EINVAL; | ||
552 | } | ||
553 | |||
424 | #ifdef CONFIG_NFSD_V4 | 554 | #ifdef CONFIG_NFSD_V4 |
425 | extern time_t nfs4_leasetime(void); | 555 | extern time_t nfs4_leasetime(void); |
426 | 556 | ||
@@ -483,7 +613,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
483 | [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, | 613 | [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, |
484 | [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, | 614 | [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, |
485 | [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, | 615 | [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, |
616 | [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, | ||
486 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, | 617 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, |
618 | [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, | ||
487 | #ifdef CONFIG_NFSD_V4 | 619 | #ifdef CONFIG_NFSD_V4 |
488 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, | 620 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, |
489 | [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, | 621 | [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index ec1decf29bab..19443056ec30 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -57,12 +57,6 @@ static atomic_t nfsd_busy; | |||
57 | static unsigned long nfsd_last_call; | 57 | static unsigned long nfsd_last_call; |
58 | static DEFINE_SPINLOCK(nfsd_call_lock); | 58 | static DEFINE_SPINLOCK(nfsd_call_lock); |
59 | 59 | ||
60 | struct nfsd_list { | ||
61 | struct list_head list; | ||
62 | struct task_struct *task; | ||
63 | }; | ||
64 | static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); | ||
65 | |||
66 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 60 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
67 | static struct svc_stat nfsd_acl_svcstats; | 61 | static struct svc_stat nfsd_acl_svcstats; |
68 | static struct svc_version * nfsd_acl_version[] = { | 62 | static struct svc_version * nfsd_acl_version[] = { |
@@ -117,6 +111,32 @@ struct svc_program nfsd_program = { | |||
117 | 111 | ||
118 | }; | 112 | }; |
119 | 113 | ||
114 | int nfsd_vers(int vers, enum vers_op change) | ||
115 | { | ||
116 | if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) | ||
117 | return -1; | ||
118 | switch(change) { | ||
119 | case NFSD_SET: | ||
120 | nfsd_versions[vers] = nfsd_version[vers]; | ||
121 | break; | ||
122 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | ||
123 | if (vers < NFSD_ACL_NRVERS) | ||
124 | nfsd_acl_version[vers] = nfsd_acl_version[vers]; | ||
125 | #endif | ||
126 | case NFSD_CLEAR: | ||
127 | nfsd_versions[vers] = NULL; | ||
128 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | ||
129 | if (vers < NFSD_ACL_NRVERS) | ||
130 | nfsd_acl_version[vers] = NULL; | ||
131 | #endif | ||
132 | break; | ||
133 | case NFSD_TEST: | ||
134 | return nfsd_versions[vers] != NULL; | ||
135 | case NFSD_AVAIL: | ||
136 | return nfsd_version[vers] != NULL; | ||
137 | } | ||
138 | return 0; | ||
139 | } | ||
120 | /* | 140 | /* |
121 | * Maximum number of nfsd processes | 141 | * Maximum number of nfsd processes |
122 | */ | 142 | */ |
@@ -130,16 +150,175 @@ int nfsd_nrthreads(void) | |||
130 | return nfsd_serv->sv_nrthreads; | 150 | return nfsd_serv->sv_nrthreads; |
131 | } | 151 | } |
132 | 152 | ||
153 | static int killsig; /* signal that was used to kill last nfsd */ | ||
154 | static void nfsd_last_thread(struct svc_serv *serv) | ||
155 | { | ||
156 | /* When last nfsd thread exits we need to do some clean-up */ | ||
157 | struct svc_sock *svsk; | ||
158 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | ||
159 | lockd_down(); | ||
160 | nfsd_serv = NULL; | ||
161 | nfsd_racache_shutdown(); | ||
162 | nfs4_state_shutdown(); | ||
163 | |||
164 | printk(KERN_WARNING "nfsd: last server has exited\n"); | ||
165 | if (killsig != SIG_NOCLEAN) { | ||
166 | printk(KERN_WARNING "nfsd: unexporting all filesystems\n"); | ||
167 | nfsd_export_flush(); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | void nfsd_reset_versions(void) | ||
172 | { | ||
173 | int found_one = 0; | ||
174 | int i; | ||
175 | |||
176 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { | ||
177 | if (nfsd_program.pg_vers[i]) | ||
178 | found_one = 1; | ||
179 | } | ||
180 | |||
181 | if (!found_one) { | ||
182 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) | ||
183 | nfsd_program.pg_vers[i] = nfsd_version[i]; | ||
184 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | ||
185 | for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) | ||
186 | nfsd_acl_program.pg_vers[i] = | ||
187 | nfsd_acl_version[i]; | ||
188 | #endif | ||
189 | } | ||
190 | } | ||
191 | |||
192 | int nfsd_create_serv(void) | ||
193 | { | ||
194 | int err = 0; | ||
195 | lock_kernel(); | ||
196 | if (nfsd_serv) { | ||
197 | svc_get(nfsd_serv); | ||
198 | unlock_kernel(); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | atomic_set(&nfsd_busy, 0); | ||
203 | nfsd_serv = svc_create_pooled(&nfsd_program, NFSD_BUFSIZE, | ||
204 | nfsd_last_thread, | ||
205 | nfsd, SIG_NOCLEAN, THIS_MODULE); | ||
206 | if (nfsd_serv == NULL) | ||
207 | err = -ENOMEM; | ||
208 | unlock_kernel(); | ||
209 | do_gettimeofday(&nfssvc_boot); /* record boot time */ | ||
210 | return err; | ||
211 | } | ||
212 | |||
213 | static int nfsd_init_socks(int port) | ||
214 | { | ||
215 | int error; | ||
216 | if (!list_empty(&nfsd_serv->sv_permsocks)) | ||
217 | return 0; | ||
218 | |||
219 | error = lockd_up(IPPROTO_UDP); | ||
220 | if (error >= 0) { | ||
221 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); | ||
222 | if (error < 0) | ||
223 | lockd_down(); | ||
224 | } | ||
225 | if (error < 0) | ||
226 | return error; | ||
227 | |||
228 | #ifdef CONFIG_NFSD_TCP | ||
229 | error = lockd_up(IPPROTO_TCP); | ||
230 | if (error >= 0) { | ||
231 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); | ||
232 | if (error < 0) | ||
233 | lockd_down(); | ||
234 | } | ||
235 | if (error < 0) | ||
236 | return error; | ||
237 | #endif | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | int nfsd_nrpools(void) | ||
242 | { | ||
243 | if (nfsd_serv == NULL) | ||
244 | return 0; | ||
245 | else | ||
246 | return nfsd_serv->sv_nrpools; | ||
247 | } | ||
248 | |||
249 | int nfsd_get_nrthreads(int n, int *nthreads) | ||
250 | { | ||
251 | int i = 0; | ||
252 | |||
253 | if (nfsd_serv != NULL) { | ||
254 | for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++) | ||
255 | nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | int nfsd_set_nrthreads(int n, int *nthreads) | ||
262 | { | ||
263 | int i = 0; | ||
264 | int tot = 0; | ||
265 | int err = 0; | ||
266 | |||
267 | if (nfsd_serv == NULL || n <= 0) | ||
268 | return 0; | ||
269 | |||
270 | if (n > nfsd_serv->sv_nrpools) | ||
271 | n = nfsd_serv->sv_nrpools; | ||
272 | |||
273 | /* enforce a global maximum number of threads */ | ||
274 | tot = 0; | ||
275 | for (i = 0; i < n; i++) { | ||
276 | if (nthreads[i] > NFSD_MAXSERVS) | ||
277 | nthreads[i] = NFSD_MAXSERVS; | ||
278 | tot += nthreads[i]; | ||
279 | } | ||
280 | if (tot > NFSD_MAXSERVS) { | ||
281 | /* total too large: scale down requested numbers */ | ||
282 | for (i = 0; i < n && tot > 0; i++) { | ||
283 | int new = nthreads[i] * NFSD_MAXSERVS / tot; | ||
284 | tot -= (nthreads[i] - new); | ||
285 | nthreads[i] = new; | ||
286 | } | ||
287 | for (i = 0; i < n && tot > 0; i++) { | ||
288 | nthreads[i]--; | ||
289 | tot--; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * There must always be a thread in pool 0; the admin | ||
295 | * can't shut down NFS completely using pool_threads. | ||
296 | */ | ||
297 | if (nthreads[0] == 0) | ||
298 | nthreads[0] = 1; | ||
299 | |||
300 | /* apply the new numbers */ | ||
301 | lock_kernel(); | ||
302 | svc_get(nfsd_serv); | ||
303 | for (i = 0; i < n; i++) { | ||
304 | err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i], | ||
305 | nthreads[i]); | ||
306 | if (err) | ||
307 | break; | ||
308 | } | ||
309 | svc_destroy(nfsd_serv); | ||
310 | unlock_kernel(); | ||
311 | |||
312 | return err; | ||
313 | } | ||
314 | |||
133 | int | 315 | int |
134 | nfsd_svc(unsigned short port, int nrservs) | 316 | nfsd_svc(unsigned short port, int nrservs) |
135 | { | 317 | { |
136 | int error; | 318 | int error; |
137 | int none_left, found_one, i; | ||
138 | struct list_head *victim; | ||
139 | 319 | ||
140 | lock_kernel(); | 320 | lock_kernel(); |
141 | dprintk("nfsd: creating service: vers 0x%x\n", | 321 | dprintk("nfsd: creating service\n"); |
142 | nfsd_versbits); | ||
143 | error = -EINVAL; | 322 | error = -EINVAL; |
144 | if (nrservs <= 0) | 323 | if (nrservs <= 0) |
145 | nrservs = 0; | 324 | nrservs = 0; |
@@ -153,91 +332,20 @@ nfsd_svc(unsigned short port, int nrservs) | |||
153 | error = nfs4_state_start(); | 332 | error = nfs4_state_start(); |
154 | if (error<0) | 333 | if (error<0) |
155 | goto out; | 334 | goto out; |
156 | if (!nfsd_serv) { | ||
157 | /* | ||
158 | * Use the nfsd_ctlbits to define which | ||
159 | * versions that will be advertised. | ||
160 | * If nfsd_ctlbits doesn't list any version, | ||
161 | * export them all. | ||
162 | */ | ||
163 | found_one = 0; | ||
164 | |||
165 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { | ||
166 | if (NFSCTL_VERISSET(nfsd_versbits, i)) { | ||
167 | nfsd_program.pg_vers[i] = nfsd_version[i]; | ||
168 | found_one = 1; | ||
169 | } else | ||
170 | nfsd_program.pg_vers[i] = NULL; | ||
171 | } | ||
172 | 335 | ||
173 | if (!found_one) { | 336 | nfsd_reset_versions(); |
174 | for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) | ||
175 | nfsd_program.pg_vers[i] = nfsd_version[i]; | ||
176 | } | ||
177 | 337 | ||
338 | error = nfsd_create_serv(); | ||
178 | 339 | ||
179 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 340 | if (error) |
180 | found_one = 0; | 341 | goto out; |
181 | 342 | error = nfsd_init_socks(port); | |
182 | for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) { | 343 | if (error) |
183 | if (NFSCTL_VERISSET(nfsd_versbits, i)) { | 344 | goto failure; |
184 | nfsd_acl_program.pg_vers[i] = | ||
185 | nfsd_acl_version[i]; | ||
186 | found_one = 1; | ||
187 | } else | ||
188 | nfsd_acl_program.pg_vers[i] = NULL; | ||
189 | } | ||
190 | |||
191 | if (!found_one) { | ||
192 | for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) | ||
193 | nfsd_acl_program.pg_vers[i] = | ||
194 | nfsd_acl_version[i]; | ||
195 | } | ||
196 | #endif | ||
197 | |||
198 | atomic_set(&nfsd_busy, 0); | ||
199 | error = -ENOMEM; | ||
200 | nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); | ||
201 | if (nfsd_serv == NULL) | ||
202 | goto out; | ||
203 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); | ||
204 | if (error < 0) | ||
205 | goto failure; | ||
206 | 345 | ||
207 | #ifdef CONFIG_NFSD_TCP | 346 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); |
208 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); | ||
209 | if (error < 0) | ||
210 | goto failure; | ||
211 | #endif | ||
212 | do_gettimeofday(&nfssvc_boot); /* record boot time */ | ||
213 | } else | ||
214 | nfsd_serv->sv_nrthreads++; | ||
215 | nrservs -= (nfsd_serv->sv_nrthreads-1); | ||
216 | while (nrservs > 0) { | ||
217 | nrservs--; | ||
218 | __module_get(THIS_MODULE); | ||
219 | error = svc_create_thread(nfsd, nfsd_serv); | ||
220 | if (error < 0) { | ||
221 | module_put(THIS_MODULE); | ||
222 | break; | ||
223 | } | ||
224 | } | ||
225 | victim = nfsd_list.next; | ||
226 | while (nrservs < 0 && victim != &nfsd_list) { | ||
227 | struct nfsd_list *nl = | ||
228 | list_entry(victim,struct nfsd_list, list); | ||
229 | victim = victim->next; | ||
230 | send_sig(SIG_NOCLEAN, nl->task, 1); | ||
231 | nrservs++; | ||
232 | } | ||
233 | failure: | 347 | failure: |
234 | none_left = (nfsd_serv->sv_nrthreads == 1); | ||
235 | svc_destroy(nfsd_serv); /* Release server */ | 348 | svc_destroy(nfsd_serv); /* Release server */ |
236 | if (none_left) { | ||
237 | nfsd_serv = NULL; | ||
238 | nfsd_racache_shutdown(); | ||
239 | nfs4_state_shutdown(); | ||
240 | } | ||
241 | out: | 349 | out: |
242 | unlock_kernel(); | 350 | unlock_kernel(); |
243 | return error; | 351 | return error; |
@@ -270,10 +378,8 @@ update_thread_usage(int busy_threads) | |||
270 | static void | 378 | static void |
271 | nfsd(struct svc_rqst *rqstp) | 379 | nfsd(struct svc_rqst *rqstp) |
272 | { | 380 | { |
273 | struct svc_serv *serv = rqstp->rq_server; | ||
274 | struct fs_struct *fsp; | 381 | struct fs_struct *fsp; |
275 | int err; | 382 | int err; |
276 | struct nfsd_list me; | ||
277 | sigset_t shutdown_mask, allowed_mask; | 383 | sigset_t shutdown_mask, allowed_mask; |
278 | 384 | ||
279 | /* Lock module and set up kernel thread */ | 385 | /* Lock module and set up kernel thread */ |
@@ -297,10 +403,7 @@ nfsd(struct svc_rqst *rqstp) | |||
297 | 403 | ||
298 | nfsdstats.th_cnt++; | 404 | nfsdstats.th_cnt++; |
299 | 405 | ||
300 | lockd_up(); /* start lockd */ | 406 | rqstp->rq_task = current; |
301 | |||
302 | me.task = current; | ||
303 | list_add(&me.list, &nfsd_list); | ||
304 | 407 | ||
305 | unlock_kernel(); | 408 | unlock_kernel(); |
306 | 409 | ||
@@ -322,8 +425,7 @@ nfsd(struct svc_rqst *rqstp) | |||
322 | * Find a socket with data available and call its | 425 | * Find a socket with data available and call its |
323 | * recvfrom routine. | 426 | * recvfrom routine. |
324 | */ | 427 | */ |
325 | while ((err = svc_recv(serv, rqstp, | 428 | while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) |
326 | 60*60*HZ)) == -EAGAIN) | ||
327 | ; | 429 | ; |
328 | if (err < 0) | 430 | if (err < 0) |
329 | break; | 431 | break; |
@@ -336,7 +438,7 @@ nfsd(struct svc_rqst *rqstp) | |||
336 | /* Process request with signals blocked. */ | 438 | /* Process request with signals blocked. */ |
337 | sigprocmask(SIG_SETMASK, &allowed_mask, NULL); | 439 | sigprocmask(SIG_SETMASK, &allowed_mask, NULL); |
338 | 440 | ||
339 | svc_process(serv, rqstp); | 441 | svc_process(rqstp); |
340 | 442 | ||
341 | /* Unlock export hash tables */ | 443 | /* Unlock export hash tables */ |
342 | exp_readunlock(); | 444 | exp_readunlock(); |
@@ -353,29 +455,13 @@ nfsd(struct svc_rqst *rqstp) | |||
353 | if (sigismember(¤t->pending.signal, signo) && | 455 | if (sigismember(¤t->pending.signal, signo) && |
354 | !sigismember(¤t->blocked, signo)) | 456 | !sigismember(¤t->blocked, signo)) |
355 | break; | 457 | break; |
356 | err = signo; | 458 | killsig = signo; |
357 | } | 459 | } |
358 | /* Clear signals before calling lockd_down() and svc_exit_thread() */ | 460 | /* Clear signals before calling svc_exit_thread() */ |
359 | flush_signals(current); | 461 | flush_signals(current); |
360 | 462 | ||
361 | lock_kernel(); | 463 | lock_kernel(); |
362 | 464 | ||
363 | /* Release lockd */ | ||
364 | lockd_down(); | ||
365 | |||
366 | /* Check if this is last thread */ | ||
367 | if (serv->sv_nrthreads==1) { | ||
368 | |||
369 | printk(KERN_WARNING "nfsd: last server has exited\n"); | ||
370 | if (err != SIG_NOCLEAN) { | ||
371 | printk(KERN_WARNING "nfsd: unexporting all filesystems\n"); | ||
372 | nfsd_export_flush(); | ||
373 | } | ||
374 | nfsd_serv = NULL; | ||
375 | nfsd_racache_shutdown(); /* release read-ahead cache */ | ||
376 | nfs4_state_shutdown(); | ||
377 | } | ||
378 | list_del(&me.list); | ||
379 | nfsdstats.th_cnt --; | 465 | nfsdstats.th_cnt --; |
380 | 466 | ||
381 | out: | 467 | out: |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index c9e3b5a8fe07..443ebc52e382 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1114,7 +1114,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1114 | */ | 1114 | */ |
1115 | if (!resfhp->fh_dentry) { | 1115 | if (!resfhp->fh_dentry) { |
1116 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ | 1116 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ |
1117 | fh_lock(fhp); | 1117 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1118 | dchild = lookup_one_len(fname, dentry, flen); | 1118 | dchild = lookup_one_len(fname, dentry, flen); |
1119 | err = PTR_ERR(dchild); | 1119 | err = PTR_ERR(dchild); |
1120 | if (IS_ERR(dchild)) | 1120 | if (IS_ERR(dchild)) |
@@ -1240,7 +1240,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1240 | err = nfserr_notdir; | 1240 | err = nfserr_notdir; |
1241 | if(!dirp->i_op || !dirp->i_op->lookup) | 1241 | if(!dirp->i_op || !dirp->i_op->lookup) |
1242 | goto out; | 1242 | goto out; |
1243 | fh_lock(fhp); | 1243 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1244 | 1244 | ||
1245 | /* | 1245 | /* |
1246 | * Compose the response file handle. | 1246 | * Compose the response file handle. |
@@ -1494,7 +1494,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1494 | if (isdotent(name, len)) | 1494 | if (isdotent(name, len)) |
1495 | goto out; | 1495 | goto out; |
1496 | 1496 | ||
1497 | fh_lock(ffhp); | 1497 | fh_lock_nested(ffhp, I_MUTEX_PARENT); |
1498 | ddir = ffhp->fh_dentry; | 1498 | ddir = ffhp->fh_dentry; |
1499 | dirp = ddir->d_inode; | 1499 | dirp = ddir->d_inode; |
1500 | 1500 | ||
@@ -1644,7 +1644,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1644 | if (err) | 1644 | if (err) |
1645 | goto out; | 1645 | goto out; |
1646 | 1646 | ||
1647 | fh_lock(fhp); | 1647 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1648 | dentry = fhp->fh_dentry; | 1648 | dentry = fhp->fh_dentry; |
1649 | dirp = dentry->d_inode; | 1649 | dirp = dentry->d_inode; |
1650 | 1650 | ||
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 9de6b495f112..b1317ad5ca18 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c | |||
@@ -163,8 +163,6 @@ int register_nls(struct nls_table * nls) | |||
163 | { | 163 | { |
164 | struct nls_table ** tmp = &tables; | 164 | struct nls_table ** tmp = &tables; |
165 | 165 | ||
166 | if (!nls) | ||
167 | return -EINVAL; | ||
168 | if (nls->next) | 166 | if (nls->next) |
169 | return -EBUSY; | 167 | return -EBUSY; |
170 | 168 | ||
diff --git a/fs/proc/array.c b/fs/proc/array.c index c0e554971df0..25e917fb4739 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -162,7 +162,7 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
162 | int g; | 162 | int g; |
163 | struct fdtable *fdt = NULL; | 163 | struct fdtable *fdt = NULL; |
164 | 164 | ||
165 | read_lock(&tasklist_lock); | 165 | rcu_read_lock(); |
166 | buffer += sprintf(buffer, | 166 | buffer += sprintf(buffer, |
167 | "State:\t%s\n" | 167 | "State:\t%s\n" |
168 | "SleepAVG:\t%lu%%\n" | 168 | "SleepAVG:\t%lu%%\n" |
@@ -174,14 +174,13 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
174 | "Gid:\t%d\t%d\t%d\t%d\n", | 174 | "Gid:\t%d\t%d\t%d\t%d\n", |
175 | get_task_state(p), | 175 | get_task_state(p), |
176 | (p->sleep_avg/1024)*100/(1020000000/1024), | 176 | (p->sleep_avg/1024)*100/(1020000000/1024), |
177 | p->tgid, | 177 | p->tgid, p->pid, |
178 | p->pid, pid_alive(p) ? p->group_leader->real_parent->tgid : 0, | 178 | pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, |
179 | pid_alive(p) && p->ptrace ? p->parent->pid : 0, | 179 | pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, |
180 | p->uid, p->euid, p->suid, p->fsuid, | 180 | p->uid, p->euid, p->suid, p->fsuid, |
181 | p->gid, p->egid, p->sgid, p->fsgid); | 181 | p->gid, p->egid, p->sgid, p->fsgid); |
182 | read_unlock(&tasklist_lock); | 182 | |
183 | task_lock(p); | 183 | task_lock(p); |
184 | rcu_read_lock(); | ||
185 | if (p->files) | 184 | if (p->files) |
186 | fdt = files_fdtable(p->files); | 185 | fdt = files_fdtable(p->files); |
187 | buffer += sprintf(buffer, | 186 | buffer += sprintf(buffer, |
@@ -244,6 +243,7 @@ static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, | |||
244 | 243 | ||
245 | static inline char * task_sig(struct task_struct *p, char *buffer) | 244 | static inline char * task_sig(struct task_struct *p, char *buffer) |
246 | { | 245 | { |
246 | unsigned long flags; | ||
247 | sigset_t pending, shpending, blocked, ignored, caught; | 247 | sigset_t pending, shpending, blocked, ignored, caught; |
248 | int num_threads = 0; | 248 | int num_threads = 0; |
249 | unsigned long qsize = 0; | 249 | unsigned long qsize = 0; |
@@ -255,10 +255,8 @@ static inline char * task_sig(struct task_struct *p, char *buffer) | |||
255 | sigemptyset(&ignored); | 255 | sigemptyset(&ignored); |
256 | sigemptyset(&caught); | 256 | sigemptyset(&caught); |
257 | 257 | ||
258 | /* Gather all the data with the appropriate locks held */ | 258 | rcu_read_lock(); |
259 | read_lock(&tasklist_lock); | 259 | if (lock_task_sighand(p, &flags)) { |
260 | if (p->sighand) { | ||
261 | spin_lock_irq(&p->sighand->siglock); | ||
262 | pending = p->pending.signal; | 260 | pending = p->pending.signal; |
263 | shpending = p->signal->shared_pending.signal; | 261 | shpending = p->signal->shared_pending.signal; |
264 | blocked = p->blocked; | 262 | blocked = p->blocked; |
@@ -266,9 +264,9 @@ static inline char * task_sig(struct task_struct *p, char *buffer) | |||
266 | num_threads = atomic_read(&p->signal->count); | 264 | num_threads = atomic_read(&p->signal->count); |
267 | qsize = atomic_read(&p->user->sigpending); | 265 | qsize = atomic_read(&p->user->sigpending); |
268 | qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; | 266 | qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; |
269 | spin_unlock_irq(&p->sighand->siglock); | 267 | unlock_task_sighand(p, &flags); |
270 | } | 268 | } |
271 | read_unlock(&tasklist_lock); | 269 | rcu_read_unlock(); |
272 | 270 | ||
273 | buffer += sprintf(buffer, "Threads:\t%d\n", num_threads); | 271 | buffer += sprintf(buffer, "Threads:\t%d\n", num_threads); |
274 | buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim); | 272 | buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim); |
@@ -322,7 +320,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
322 | sigset_t sigign, sigcatch; | 320 | sigset_t sigign, sigcatch; |
323 | char state; | 321 | char state; |
324 | int res; | 322 | int res; |
325 | pid_t ppid, pgid = -1, sid = -1; | 323 | pid_t ppid = 0, pgid = -1, sid = -1; |
326 | int num_threads = 0; | 324 | int num_threads = 0; |
327 | struct mm_struct *mm; | 325 | struct mm_struct *mm; |
328 | unsigned long long start_time; | 326 | unsigned long long start_time; |
@@ -330,8 +328,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
330 | unsigned long min_flt = 0, maj_flt = 0; | 328 | unsigned long min_flt = 0, maj_flt = 0; |
331 | cputime_t cutime, cstime, utime, stime; | 329 | cputime_t cutime, cstime, utime, stime; |
332 | unsigned long rsslim = 0; | 330 | unsigned long rsslim = 0; |
333 | struct task_struct *t; | ||
334 | char tcomm[sizeof(task->comm)]; | 331 | char tcomm[sizeof(task->comm)]; |
332 | unsigned long flags; | ||
335 | 333 | ||
336 | state = *get_task_state(task); | 334 | state = *get_task_state(task); |
337 | vsize = eip = esp = 0; | 335 | vsize = eip = esp = 0; |
@@ -349,15 +347,33 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
349 | cutime = cstime = utime = stime = cputime_zero; | 347 | cutime = cstime = utime = stime = cputime_zero; |
350 | 348 | ||
351 | mutex_lock(&tty_mutex); | 349 | mutex_lock(&tty_mutex); |
352 | read_lock(&tasklist_lock); | 350 | rcu_read_lock(); |
353 | if (task->sighand) { | 351 | if (lock_task_sighand(task, &flags)) { |
354 | spin_lock_irq(&task->sighand->siglock); | 352 | struct signal_struct *sig = task->signal; |
355 | num_threads = atomic_read(&task->signal->count); | 353 | struct tty_struct *tty = sig->tty; |
354 | |||
355 | if (tty) { | ||
356 | /* | ||
357 | * sig->tty is not stable, but tty_mutex | ||
358 | * protects us from release_dev(tty) | ||
359 | */ | ||
360 | barrier(); | ||
361 | tty_pgrp = tty->pgrp; | ||
362 | tty_nr = new_encode_dev(tty_devnum(tty)); | ||
363 | } | ||
364 | |||
365 | num_threads = atomic_read(&sig->count); | ||
356 | collect_sigign_sigcatch(task, &sigign, &sigcatch); | 366 | collect_sigign_sigcatch(task, &sigign, &sigcatch); |
357 | 367 | ||
368 | cmin_flt = sig->cmin_flt; | ||
369 | cmaj_flt = sig->cmaj_flt; | ||
370 | cutime = sig->cutime; | ||
371 | cstime = sig->cstime; | ||
372 | rsslim = sig->rlim[RLIMIT_RSS].rlim_cur; | ||
373 | |||
358 | /* add up live thread stats at the group level */ | 374 | /* add up live thread stats at the group level */ |
359 | if (whole) { | 375 | if (whole) { |
360 | t = task; | 376 | struct task_struct *t = task; |
361 | do { | 377 | do { |
362 | min_flt += t->min_flt; | 378 | min_flt += t->min_flt; |
363 | maj_flt += t->maj_flt; | 379 | maj_flt += t->maj_flt; |
@@ -365,31 +381,20 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
365 | stime = cputime_add(stime, t->stime); | 381 | stime = cputime_add(stime, t->stime); |
366 | t = next_thread(t); | 382 | t = next_thread(t); |
367 | } while (t != task); | 383 | } while (t != task); |
368 | } | ||
369 | 384 | ||
370 | spin_unlock_irq(&task->sighand->siglock); | 385 | min_flt += sig->min_flt; |
371 | } | 386 | maj_flt += sig->maj_flt; |
372 | if (task->signal) { | 387 | utime = cputime_add(utime, sig->utime); |
373 | if (task->signal->tty) { | 388 | stime = cputime_add(stime, sig->stime); |
374 | tty_pgrp = task->signal->tty->pgrp; | ||
375 | tty_nr = new_encode_dev(tty_devnum(task->signal->tty)); | ||
376 | } | 389 | } |
390 | |||
391 | sid = sig->session; | ||
377 | pgid = process_group(task); | 392 | pgid = process_group(task); |
378 | sid = task->signal->session; | 393 | ppid = rcu_dereference(task->real_parent)->tgid; |
379 | cmin_flt = task->signal->cmin_flt; | 394 | |
380 | cmaj_flt = task->signal->cmaj_flt; | 395 | unlock_task_sighand(task, &flags); |
381 | cutime = task->signal->cutime; | ||
382 | cstime = task->signal->cstime; | ||
383 | rsslim = task->signal->rlim[RLIMIT_RSS].rlim_cur; | ||
384 | if (whole) { | ||
385 | min_flt += task->signal->min_flt; | ||
386 | maj_flt += task->signal->maj_flt; | ||
387 | utime = cputime_add(utime, task->signal->utime); | ||
388 | stime = cputime_add(stime, task->signal->stime); | ||
389 | } | ||
390 | } | 396 | } |
391 | ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; | 397 | rcu_read_unlock(); |
392 | read_unlock(&tasklist_lock); | ||
393 | mutex_unlock(&tty_mutex); | 398 | mutex_unlock(&tty_mutex); |
394 | 399 | ||
395 | if (!whole || num_threads<2) | 400 | if (!whole || num_threads<2) |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 89c20d9d50bf..82da55b5cffe 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -71,6 +71,7 @@ | |||
71 | #include <linux/cpuset.h> | 71 | #include <linux/cpuset.h> |
72 | #include <linux/audit.h> | 72 | #include <linux/audit.h> |
73 | #include <linux/poll.h> | 73 | #include <linux/poll.h> |
74 | #include <linux/nsproxy.h> | ||
74 | #include "internal.h" | 75 | #include "internal.h" |
75 | 76 | ||
76 | /* NOTE: | 77 | /* NOTE: |
@@ -83,262 +84,44 @@ | |||
83 | * in /proc for a task before it execs a suid executable. | 84 | * in /proc for a task before it execs a suid executable. |
84 | */ | 85 | */ |
85 | 86 | ||
86 | /* | ||
87 | * For hysterical raisins we keep the same inumbers as in the old procfs. | ||
88 | * Feel free to change the macro below - just keep the range distinct from | ||
89 | * inumbers of the rest of procfs (currently those are in 0x0000--0xffff). | ||
90 | * As soon as we'll get a separate superblock we will be able to forget | ||
91 | * about magical ranges too. | ||
92 | */ | ||
93 | |||
94 | #define fake_ino(pid,ino) (((pid)<<16)|(ino)) | ||
95 | |||
96 | enum pid_directory_inos { | ||
97 | PROC_TGID_INO = 2, | ||
98 | PROC_TGID_TASK, | ||
99 | PROC_TGID_STATUS, | ||
100 | PROC_TGID_MEM, | ||
101 | #ifdef CONFIG_SECCOMP | ||
102 | PROC_TGID_SECCOMP, | ||
103 | #endif | ||
104 | PROC_TGID_CWD, | ||
105 | PROC_TGID_ROOT, | ||
106 | PROC_TGID_EXE, | ||
107 | PROC_TGID_FD, | ||
108 | PROC_TGID_ENVIRON, | ||
109 | PROC_TGID_AUXV, | ||
110 | PROC_TGID_CMDLINE, | ||
111 | PROC_TGID_STAT, | ||
112 | PROC_TGID_STATM, | ||
113 | PROC_TGID_MAPS, | ||
114 | PROC_TGID_NUMA_MAPS, | ||
115 | PROC_TGID_MOUNTS, | ||
116 | PROC_TGID_MOUNTSTATS, | ||
117 | PROC_TGID_WCHAN, | ||
118 | #ifdef CONFIG_MMU | ||
119 | PROC_TGID_SMAPS, | ||
120 | #endif | ||
121 | #ifdef CONFIG_SCHEDSTATS | ||
122 | PROC_TGID_SCHEDSTAT, | ||
123 | #endif | ||
124 | #ifdef CONFIG_CPUSETS | ||
125 | PROC_TGID_CPUSET, | ||
126 | #endif | ||
127 | #ifdef CONFIG_SECURITY | ||
128 | PROC_TGID_ATTR, | ||
129 | PROC_TGID_ATTR_CURRENT, | ||
130 | PROC_TGID_ATTR_PREV, | ||
131 | PROC_TGID_ATTR_EXEC, | ||
132 | PROC_TGID_ATTR_FSCREATE, | ||
133 | PROC_TGID_ATTR_KEYCREATE, | ||
134 | PROC_TGID_ATTR_SOCKCREATE, | ||
135 | #endif | ||
136 | #ifdef CONFIG_AUDITSYSCALL | ||
137 | PROC_TGID_LOGINUID, | ||
138 | #endif | ||
139 | PROC_TGID_OOM_SCORE, | ||
140 | PROC_TGID_OOM_ADJUST, | ||
141 | PROC_TID_INO, | ||
142 | PROC_TID_STATUS, | ||
143 | PROC_TID_MEM, | ||
144 | #ifdef CONFIG_SECCOMP | ||
145 | PROC_TID_SECCOMP, | ||
146 | #endif | ||
147 | PROC_TID_CWD, | ||
148 | PROC_TID_ROOT, | ||
149 | PROC_TID_EXE, | ||
150 | PROC_TID_FD, | ||
151 | PROC_TID_ENVIRON, | ||
152 | PROC_TID_AUXV, | ||
153 | PROC_TID_CMDLINE, | ||
154 | PROC_TID_STAT, | ||
155 | PROC_TID_STATM, | ||
156 | PROC_TID_MAPS, | ||
157 | PROC_TID_NUMA_MAPS, | ||
158 | PROC_TID_MOUNTS, | ||
159 | PROC_TID_MOUNTSTATS, | ||
160 | PROC_TID_WCHAN, | ||
161 | #ifdef CONFIG_MMU | ||
162 | PROC_TID_SMAPS, | ||
163 | #endif | ||
164 | #ifdef CONFIG_SCHEDSTATS | ||
165 | PROC_TID_SCHEDSTAT, | ||
166 | #endif | ||
167 | #ifdef CONFIG_CPUSETS | ||
168 | PROC_TID_CPUSET, | ||
169 | #endif | ||
170 | #ifdef CONFIG_SECURITY | ||
171 | PROC_TID_ATTR, | ||
172 | PROC_TID_ATTR_CURRENT, | ||
173 | PROC_TID_ATTR_PREV, | ||
174 | PROC_TID_ATTR_EXEC, | ||
175 | PROC_TID_ATTR_FSCREATE, | ||
176 | PROC_TID_ATTR_KEYCREATE, | ||
177 | PROC_TID_ATTR_SOCKCREATE, | ||
178 | #endif | ||
179 | #ifdef CONFIG_AUDITSYSCALL | ||
180 | PROC_TID_LOGINUID, | ||
181 | #endif | ||
182 | PROC_TID_OOM_SCORE, | ||
183 | PROC_TID_OOM_ADJUST, | ||
184 | |||
185 | /* Add new entries before this */ | ||
186 | PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */ | ||
187 | }; | ||
188 | 87 | ||
189 | /* Worst case buffer size needed for holding an integer. */ | 88 | /* Worst case buffer size needed for holding an integer. */ |
190 | #define PROC_NUMBUF 10 | 89 | #define PROC_NUMBUF 10 |
191 | 90 | ||
192 | struct pid_entry { | 91 | struct pid_entry { |
193 | int type; | ||
194 | int len; | 92 | int len; |
195 | char *name; | 93 | char *name; |
196 | mode_t mode; | 94 | mode_t mode; |
95 | struct inode_operations *iop; | ||
96 | struct file_operations *fop; | ||
97 | union proc_op op; | ||
197 | }; | 98 | }; |
198 | 99 | ||
199 | #define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)} | 100 | #define NOD(NAME, MODE, IOP, FOP, OP) { \ |
200 | 101 | .len = sizeof(NAME) - 1, \ | |
201 | static struct pid_entry tgid_base_stuff[] = { | 102 | .name = (NAME), \ |
202 | E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO), | 103 | .mode = MODE, \ |
203 | E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), | 104 | .iop = IOP, \ |
204 | E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR), | 105 | .fop = FOP, \ |
205 | E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR), | 106 | .op = OP, \ |
206 | E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO), | ||
207 | E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), | ||
208 | E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO), | ||
209 | E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO), | ||
210 | E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO), | ||
211 | #ifdef CONFIG_NUMA | ||
212 | E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO), | ||
213 | #endif | ||
214 | E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), | ||
215 | #ifdef CONFIG_SECCOMP | ||
216 | E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), | ||
217 | #endif | ||
218 | E(PROC_TGID_CWD, "cwd", S_IFLNK|S_IRWXUGO), | ||
219 | E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), | ||
220 | E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), | ||
221 | E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), | ||
222 | E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR), | ||
223 | #ifdef CONFIG_MMU | ||
224 | E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), | ||
225 | #endif | ||
226 | #ifdef CONFIG_SECURITY | ||
227 | E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), | ||
228 | #endif | ||
229 | #ifdef CONFIG_KALLSYMS | ||
230 | E(PROC_TGID_WCHAN, "wchan", S_IFREG|S_IRUGO), | ||
231 | #endif | ||
232 | #ifdef CONFIG_SCHEDSTATS | ||
233 | E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO), | ||
234 | #endif | ||
235 | #ifdef CONFIG_CPUSETS | ||
236 | E(PROC_TGID_CPUSET, "cpuset", S_IFREG|S_IRUGO), | ||
237 | #endif | ||
238 | E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO), | ||
239 | E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR), | ||
240 | #ifdef CONFIG_AUDITSYSCALL | ||
241 | E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO), | ||
242 | #endif | ||
243 | {0,0,NULL,0} | ||
244 | }; | ||
245 | static struct pid_entry tid_base_stuff[] = { | ||
246 | E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), | ||
247 | E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR), | ||
248 | E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR), | ||
249 | E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO), | ||
250 | E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), | ||
251 | E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO), | ||
252 | E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO), | ||
253 | E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO), | ||
254 | #ifdef CONFIG_NUMA | ||
255 | E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO), | ||
256 | #endif | ||
257 | E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), | ||
258 | #ifdef CONFIG_SECCOMP | ||
259 | E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR), | ||
260 | #endif | ||
261 | E(PROC_TID_CWD, "cwd", S_IFLNK|S_IRWXUGO), | ||
262 | E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), | ||
263 | E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), | ||
264 | E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), | ||
265 | #ifdef CONFIG_MMU | ||
266 | E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), | ||
267 | #endif | ||
268 | #ifdef CONFIG_SECURITY | ||
269 | E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), | ||
270 | #endif | ||
271 | #ifdef CONFIG_KALLSYMS | ||
272 | E(PROC_TID_WCHAN, "wchan", S_IFREG|S_IRUGO), | ||
273 | #endif | ||
274 | #ifdef CONFIG_SCHEDSTATS | ||
275 | E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO), | ||
276 | #endif | ||
277 | #ifdef CONFIG_CPUSETS | ||
278 | E(PROC_TID_CPUSET, "cpuset", S_IFREG|S_IRUGO), | ||
279 | #endif | ||
280 | E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO), | ||
281 | E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR), | ||
282 | #ifdef CONFIG_AUDITSYSCALL | ||
283 | E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO), | ||
284 | #endif | ||
285 | {0,0,NULL,0} | ||
286 | }; | ||
287 | |||
288 | #ifdef CONFIG_SECURITY | ||
289 | static struct pid_entry tgid_attr_stuff[] = { | ||
290 | E(PROC_TGID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO), | ||
291 | E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), | ||
292 | E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), | ||
293 | E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
294 | E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
295 | E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
296 | {0,0,NULL,0} | ||
297 | }; | ||
298 | static struct pid_entry tid_attr_stuff[] = { | ||
299 | E(PROC_TID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO), | ||
300 | E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), | ||
301 | E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), | ||
302 | E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
303 | E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
304 | E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), | ||
305 | {0,0,NULL,0} | ||
306 | }; | ||
307 | #endif | ||
308 | |||
309 | #undef E | ||
310 | |||
311 | static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) | ||
312 | { | ||
313 | struct task_struct *task = get_proc_task(inode); | ||
314 | struct files_struct *files = NULL; | ||
315 | struct file *file; | ||
316 | int fd = proc_fd(inode); | ||
317 | |||
318 | if (task) { | ||
319 | files = get_files_struct(task); | ||
320 | put_task_struct(task); | ||
321 | } | ||
322 | if (files) { | ||
323 | /* | ||
324 | * We are not taking a ref to the file structure, so we must | ||
325 | * hold ->file_lock. | ||
326 | */ | ||
327 | spin_lock(&files->file_lock); | ||
328 | file = fcheck_files(files, fd); | ||
329 | if (file) { | ||
330 | *mnt = mntget(file->f_vfsmnt); | ||
331 | *dentry = dget(file->f_dentry); | ||
332 | spin_unlock(&files->file_lock); | ||
333 | put_files_struct(files); | ||
334 | return 0; | ||
335 | } | ||
336 | spin_unlock(&files->file_lock); | ||
337 | put_files_struct(files); | ||
338 | } | ||
339 | return -ENOENT; | ||
340 | } | 107 | } |
341 | 108 | ||
109 | #define DIR(NAME, MODE, OTYPE) \ | ||
110 | NOD(NAME, (S_IFDIR|(MODE)), \ | ||
111 | &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \ | ||
112 | {} ) | ||
113 | #define LNK(NAME, OTYPE) \ | ||
114 | NOD(NAME, (S_IFLNK|S_IRWXUGO), \ | ||
115 | &proc_pid_link_inode_operations, NULL, \ | ||
116 | { .proc_get_link = &proc_##OTYPE##_link } ) | ||
117 | #define REG(NAME, MODE, OTYPE) \ | ||
118 | NOD(NAME, (S_IFREG|(MODE)), NULL, \ | ||
119 | &proc_##OTYPE##_operations, {}) | ||
120 | #define INF(NAME, MODE, OTYPE) \ | ||
121 | NOD(NAME, (S_IFREG|(MODE)), \ | ||
122 | NULL, &proc_info_file_operations, \ | ||
123 | { .proc_read = &proc_##OTYPE } ) | ||
124 | |||
342 | static struct fs_struct *get_fs_struct(struct task_struct *task) | 125 | static struct fs_struct *get_fs_struct(struct task_struct *task) |
343 | { | 126 | { |
344 | struct fs_struct *fs; | 127 | struct fs_struct *fs; |
@@ -587,7 +370,7 @@ static int mounts_open(struct inode *inode, struct file *file) | |||
587 | 370 | ||
588 | if (task) { | 371 | if (task) { |
589 | task_lock(task); | 372 | task_lock(task); |
590 | namespace = task->namespace; | 373 | namespace = task->nsproxy->namespace; |
591 | if (namespace) | 374 | if (namespace) |
592 | get_namespace(namespace); | 375 | get_namespace(namespace); |
593 | task_unlock(task); | 376 | task_unlock(task); |
@@ -658,7 +441,7 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
658 | 441 | ||
659 | if (task) { | 442 | if (task) { |
660 | task_lock(task); | 443 | task_lock(task); |
661 | namespace = task->namespace; | 444 | namespace = task->nsproxy->namespace; |
662 | if (namespace) | 445 | if (namespace) |
663 | get_namespace(namespace); | 446 | get_namespace(namespace); |
664 | task_unlock(task); | 447 | task_unlock(task); |
@@ -1137,143 +920,6 @@ static struct inode_operations proc_pid_link_inode_operations = { | |||
1137 | .setattr = proc_setattr, | 920 | .setattr = proc_setattr, |
1138 | }; | 921 | }; |
1139 | 922 | ||
1140 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | ||
1141 | { | ||
1142 | struct dentry *dentry = filp->f_dentry; | ||
1143 | struct inode *inode = dentry->d_inode; | ||
1144 | struct task_struct *p = get_proc_task(inode); | ||
1145 | unsigned int fd, tid, ino; | ||
1146 | int retval; | ||
1147 | char buf[PROC_NUMBUF]; | ||
1148 | struct files_struct * files; | ||
1149 | struct fdtable *fdt; | ||
1150 | |||
1151 | retval = -ENOENT; | ||
1152 | if (!p) | ||
1153 | goto out_no_task; | ||
1154 | retval = 0; | ||
1155 | tid = p->pid; | ||
1156 | |||
1157 | fd = filp->f_pos; | ||
1158 | switch (fd) { | ||
1159 | case 0: | ||
1160 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
1161 | goto out; | ||
1162 | filp->f_pos++; | ||
1163 | case 1: | ||
1164 | ino = parent_ino(dentry); | ||
1165 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
1166 | goto out; | ||
1167 | filp->f_pos++; | ||
1168 | default: | ||
1169 | files = get_files_struct(p); | ||
1170 | if (!files) | ||
1171 | goto out; | ||
1172 | rcu_read_lock(); | ||
1173 | fdt = files_fdtable(files); | ||
1174 | for (fd = filp->f_pos-2; | ||
1175 | fd < fdt->max_fds; | ||
1176 | fd++, filp->f_pos++) { | ||
1177 | unsigned int i,j; | ||
1178 | |||
1179 | if (!fcheck_files(files, fd)) | ||
1180 | continue; | ||
1181 | rcu_read_unlock(); | ||
1182 | |||
1183 | j = PROC_NUMBUF; | ||
1184 | i = fd; | ||
1185 | do { | ||
1186 | j--; | ||
1187 | buf[j] = '0' + (i % 10); | ||
1188 | i /= 10; | ||
1189 | } while (i); | ||
1190 | |||
1191 | ino = fake_ino(tid, PROC_TID_FD_DIR + fd); | ||
1192 | if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) { | ||
1193 | rcu_read_lock(); | ||
1194 | break; | ||
1195 | } | ||
1196 | rcu_read_lock(); | ||
1197 | } | ||
1198 | rcu_read_unlock(); | ||
1199 | put_files_struct(files); | ||
1200 | } | ||
1201 | out: | ||
1202 | put_task_struct(p); | ||
1203 | out_no_task: | ||
1204 | return retval; | ||
1205 | } | ||
1206 | |||
1207 | static int proc_pident_readdir(struct file *filp, | ||
1208 | void *dirent, filldir_t filldir, | ||
1209 | struct pid_entry *ents, unsigned int nents) | ||
1210 | { | ||
1211 | int i; | ||
1212 | int pid; | ||
1213 | struct dentry *dentry = filp->f_dentry; | ||
1214 | struct inode *inode = dentry->d_inode; | ||
1215 | struct task_struct *task = get_proc_task(inode); | ||
1216 | struct pid_entry *p; | ||
1217 | ino_t ino; | ||
1218 | int ret; | ||
1219 | |||
1220 | ret = -ENOENT; | ||
1221 | if (!task) | ||
1222 | goto out; | ||
1223 | |||
1224 | ret = 0; | ||
1225 | pid = task->pid; | ||
1226 | put_task_struct(task); | ||
1227 | i = filp->f_pos; | ||
1228 | switch (i) { | ||
1229 | case 0: | ||
1230 | ino = inode->i_ino; | ||
1231 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
1232 | goto out; | ||
1233 | i++; | ||
1234 | filp->f_pos++; | ||
1235 | /* fall through */ | ||
1236 | case 1: | ||
1237 | ino = parent_ino(dentry); | ||
1238 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | ||
1239 | goto out; | ||
1240 | i++; | ||
1241 | filp->f_pos++; | ||
1242 | /* fall through */ | ||
1243 | default: | ||
1244 | i -= 2; | ||
1245 | if (i >= nents) { | ||
1246 | ret = 1; | ||
1247 | goto out; | ||
1248 | } | ||
1249 | p = ents + i; | ||
1250 | while (p->name) { | ||
1251 | if (filldir(dirent, p->name, p->len, filp->f_pos, | ||
1252 | fake_ino(pid, p->type), p->mode >> 12) < 0) | ||
1253 | goto out; | ||
1254 | filp->f_pos++; | ||
1255 | p++; | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1259 | ret = 1; | ||
1260 | out: | ||
1261 | return ret; | ||
1262 | } | ||
1263 | |||
1264 | static int proc_tgid_base_readdir(struct file * filp, | ||
1265 | void * dirent, filldir_t filldir) | ||
1266 | { | ||
1267 | return proc_pident_readdir(filp,dirent,filldir, | ||
1268 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); | ||
1269 | } | ||
1270 | |||
1271 | static int proc_tid_base_readdir(struct file * filp, | ||
1272 | void * dirent, filldir_t filldir) | ||
1273 | { | ||
1274 | return proc_pident_readdir(filp,dirent,filldir, | ||
1275 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); | ||
1276 | } | ||
1277 | 923 | ||
1278 | /* building an inode */ | 924 | /* building an inode */ |
1279 | 925 | ||
@@ -1293,13 +939,13 @@ static int task_dumpable(struct task_struct *task) | |||
1293 | } | 939 | } |
1294 | 940 | ||
1295 | 941 | ||
1296 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) | 942 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task) |
1297 | { | 943 | { |
1298 | struct inode * inode; | 944 | struct inode * inode; |
1299 | struct proc_inode *ei; | 945 | struct proc_inode *ei; |
1300 | 946 | ||
1301 | /* We need a new inode */ | 947 | /* We need a new inode */ |
1302 | 948 | ||
1303 | inode = new_inode(sb); | 949 | inode = new_inode(sb); |
1304 | if (!inode) | 950 | if (!inode) |
1305 | goto out; | 951 | goto out; |
@@ -1307,13 +953,12 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st | |||
1307 | /* Common stuff */ | 953 | /* Common stuff */ |
1308 | ei = PROC_I(inode); | 954 | ei = PROC_I(inode); |
1309 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 955 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
1310 | inode->i_ino = fake_ino(task->pid, ino); | ||
1311 | inode->i_op = &proc_def_inode_operations; | 956 | inode->i_op = &proc_def_inode_operations; |
1312 | 957 | ||
1313 | /* | 958 | /* |
1314 | * grab the reference to task. | 959 | * grab the reference to task. |
1315 | */ | 960 | */ |
1316 | ei->pid = get_pid(task->pids[PIDTYPE_PID].pid); | 961 | ei->pid = get_task_pid(task, PIDTYPE_PID); |
1317 | if (!ei->pid) | 962 | if (!ei->pid) |
1318 | goto out_unlock; | 963 | goto out_unlock; |
1319 | 964 | ||
@@ -1333,6 +978,27 @@ out_unlock: | |||
1333 | return NULL; | 978 | return NULL; |
1334 | } | 979 | } |
1335 | 980 | ||
981 | static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | ||
982 | { | ||
983 | struct inode *inode = dentry->d_inode; | ||
984 | struct task_struct *task; | ||
985 | generic_fillattr(inode, stat); | ||
986 | |||
987 | rcu_read_lock(); | ||
988 | stat->uid = 0; | ||
989 | stat->gid = 0; | ||
990 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | ||
991 | if (task) { | ||
992 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | ||
993 | task_dumpable(task)) { | ||
994 | stat->uid = task->euid; | ||
995 | stat->gid = task->egid; | ||
996 | } | ||
997 | } | ||
998 | rcu_read_unlock(); | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1336 | /* dentry stuff */ | 1002 | /* dentry stuff */ |
1337 | 1003 | ||
1338 | /* | 1004 | /* |
@@ -1372,25 +1038,130 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1372 | return 0; | 1038 | return 0; |
1373 | } | 1039 | } |
1374 | 1040 | ||
1375 | static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 1041 | static int pid_delete_dentry(struct dentry * dentry) |
1376 | { | 1042 | { |
1377 | struct inode *inode = dentry->d_inode; | 1043 | /* Is the task we represent dead? |
1378 | struct task_struct *task; | 1044 | * If so, then don't put the dentry on the lru list, |
1379 | generic_fillattr(inode, stat); | 1045 | * kill it immediately. |
1046 | */ | ||
1047 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; | ||
1048 | } | ||
1049 | |||
1050 | static struct dentry_operations pid_dentry_operations = | ||
1051 | { | ||
1052 | .d_revalidate = pid_revalidate, | ||
1053 | .d_delete = pid_delete_dentry, | ||
1054 | }; | ||
1055 | |||
1056 | /* Lookups */ | ||
1057 | |||
1058 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *); | ||
1059 | |||
1060 | /* | ||
1061 | * Fill a directory entry. | ||
1062 | * | ||
1063 | * If possible create the dcache entry and derive our inode number and | ||
1064 | * file type from dcache entry. | ||
1065 | * | ||
1066 | * Since all of the proc inode numbers are dynamically generated, the inode | ||
1067 | * numbers do not exist until the inode is cache. This means creating the | ||
1068 | * the dcache entry in readdir is necessary to keep the inode numbers | ||
1069 | * reported by readdir in sync with the inode numbers reported | ||
1070 | * by stat. | ||
1071 | */ | ||
1072 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1073 | char *name, int len, | ||
1074 | instantiate_t instantiate, struct task_struct *task, void *ptr) | ||
1075 | { | ||
1076 | struct dentry *child, *dir = filp->f_dentry; | ||
1077 | struct inode *inode; | ||
1078 | struct qstr qname; | ||
1079 | ino_t ino = 0; | ||
1080 | unsigned type = DT_UNKNOWN; | ||
1081 | |||
1082 | qname.name = name; | ||
1083 | qname.len = len; | ||
1084 | qname.hash = full_name_hash(name, len); | ||
1085 | |||
1086 | child = d_lookup(dir, &qname); | ||
1087 | if (!child) { | ||
1088 | struct dentry *new; | ||
1089 | new = d_alloc(dir, &qname); | ||
1090 | if (new) { | ||
1091 | child = instantiate(dir->d_inode, new, task, ptr); | ||
1092 | if (child) | ||
1093 | dput(new); | ||
1094 | else | ||
1095 | child = new; | ||
1096 | } | ||
1097 | } | ||
1098 | if (!child || IS_ERR(child) || !child->d_inode) | ||
1099 | goto end_instantiate; | ||
1100 | inode = child->d_inode; | ||
1101 | if (inode) { | ||
1102 | ino = inode->i_ino; | ||
1103 | type = inode->i_mode >> 12; | ||
1104 | } | ||
1105 | dput(child); | ||
1106 | end_instantiate: | ||
1107 | if (!ino) | ||
1108 | ino = find_inode_number(dir, &qname); | ||
1109 | if (!ino) | ||
1110 | ino = 1; | ||
1111 | return filldir(dirent, name, len, filp->f_pos, ino, type); | ||
1112 | } | ||
1113 | |||
1114 | static unsigned name_to_int(struct dentry *dentry) | ||
1115 | { | ||
1116 | const char *name = dentry->d_name.name; | ||
1117 | int len = dentry->d_name.len; | ||
1118 | unsigned n = 0; | ||
1119 | |||
1120 | if (len > 1 && *name == '0') | ||
1121 | goto out; | ||
1122 | while (len-- > 0) { | ||
1123 | unsigned c = *name++ - '0'; | ||
1124 | if (c > 9) | ||
1125 | goto out; | ||
1126 | if (n >= (~0U-9)/10) | ||
1127 | goto out; | ||
1128 | n *= 10; | ||
1129 | n += c; | ||
1130 | } | ||
1131 | return n; | ||
1132 | out: | ||
1133 | return ~0U; | ||
1134 | } | ||
1135 | |||
1136 | static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) | ||
1137 | { | ||
1138 | struct task_struct *task = get_proc_task(inode); | ||
1139 | struct files_struct *files = NULL; | ||
1140 | struct file *file; | ||
1141 | int fd = proc_fd(inode); | ||
1380 | 1142 | ||
1381 | rcu_read_lock(); | ||
1382 | stat->uid = 0; | ||
1383 | stat->gid = 0; | ||
1384 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | ||
1385 | if (task) { | 1143 | if (task) { |
1386 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | 1144 | files = get_files_struct(task); |
1387 | task_dumpable(task)) { | 1145 | put_task_struct(task); |
1388 | stat->uid = task->euid; | 1146 | } |
1389 | stat->gid = task->egid; | 1147 | if (files) { |
1148 | /* | ||
1149 | * We are not taking a ref to the file structure, so we must | ||
1150 | * hold ->file_lock. | ||
1151 | */ | ||
1152 | spin_lock(&files->file_lock); | ||
1153 | file = fcheck_files(files, fd); | ||
1154 | if (file) { | ||
1155 | *mnt = mntget(file->f_vfsmnt); | ||
1156 | *dentry = dget(file->f_dentry); | ||
1157 | spin_unlock(&files->file_lock); | ||
1158 | put_files_struct(files); | ||
1159 | return 0; | ||
1390 | } | 1160 | } |
1161 | spin_unlock(&files->file_lock); | ||
1162 | put_files_struct(files); | ||
1391 | } | 1163 | } |
1392 | rcu_read_unlock(); | 1164 | return -ENOENT; |
1393 | return 0; | ||
1394 | } | 1165 | } |
1395 | 1166 | ||
1396 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | 1167 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) |
@@ -1428,75 +1199,30 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1428 | return 0; | 1199 | return 0; |
1429 | } | 1200 | } |
1430 | 1201 | ||
1431 | static int pid_delete_dentry(struct dentry * dentry) | ||
1432 | { | ||
1433 | /* Is the task we represent dead? | ||
1434 | * If so, then don't put the dentry on the lru list, | ||
1435 | * kill it immediately. | ||
1436 | */ | ||
1437 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; | ||
1438 | } | ||
1439 | |||
1440 | static struct dentry_operations tid_fd_dentry_operations = | 1202 | static struct dentry_operations tid_fd_dentry_operations = |
1441 | { | 1203 | { |
1442 | .d_revalidate = tid_fd_revalidate, | 1204 | .d_revalidate = tid_fd_revalidate, |
1443 | .d_delete = pid_delete_dentry, | 1205 | .d_delete = pid_delete_dentry, |
1444 | }; | 1206 | }; |
1445 | 1207 | ||
1446 | static struct dentry_operations pid_dentry_operations = | 1208 | static struct dentry *proc_fd_instantiate(struct inode *dir, |
1447 | { | 1209 | struct dentry *dentry, struct task_struct *task, void *ptr) |
1448 | .d_revalidate = pid_revalidate, | ||
1449 | .d_delete = pid_delete_dentry, | ||
1450 | }; | ||
1451 | |||
1452 | /* Lookups */ | ||
1453 | |||
1454 | static unsigned name_to_int(struct dentry *dentry) | ||
1455 | { | ||
1456 | const char *name = dentry->d_name.name; | ||
1457 | int len = dentry->d_name.len; | ||
1458 | unsigned n = 0; | ||
1459 | |||
1460 | if (len > 1 && *name == '0') | ||
1461 | goto out; | ||
1462 | while (len-- > 0) { | ||
1463 | unsigned c = *name++ - '0'; | ||
1464 | if (c > 9) | ||
1465 | goto out; | ||
1466 | if (n >= (~0U-9)/10) | ||
1467 | goto out; | ||
1468 | n *= 10; | ||
1469 | n += c; | ||
1470 | } | ||
1471 | return n; | ||
1472 | out: | ||
1473 | return ~0U; | ||
1474 | } | ||
1475 | |||
1476 | /* SMP-safe */ | ||
1477 | static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | ||
1478 | { | 1210 | { |
1479 | struct task_struct *task = get_proc_task(dir); | 1211 | unsigned fd = *(unsigned *)ptr; |
1480 | unsigned fd = name_to_int(dentry); | 1212 | struct file *file; |
1481 | struct dentry *result = ERR_PTR(-ENOENT); | 1213 | struct files_struct *files; |
1482 | struct file * file; | 1214 | struct inode *inode; |
1483 | struct files_struct * files; | 1215 | struct proc_inode *ei; |
1484 | struct inode *inode; | 1216 | struct dentry *error = ERR_PTR(-ENOENT); |
1485 | struct proc_inode *ei; | ||
1486 | |||
1487 | if (!task) | ||
1488 | goto out_no_task; | ||
1489 | if (fd == ~0U) | ||
1490 | goto out; | ||
1491 | 1217 | ||
1492 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd); | 1218 | inode = proc_pid_make_inode(dir->i_sb, task); |
1493 | if (!inode) | 1219 | if (!inode) |
1494 | goto out; | 1220 | goto out; |
1495 | ei = PROC_I(inode); | 1221 | ei = PROC_I(inode); |
1496 | ei->fd = fd; | 1222 | ei->fd = fd; |
1497 | files = get_files_struct(task); | 1223 | files = get_files_struct(task); |
1498 | if (!files) | 1224 | if (!files) |
1499 | goto out_unlock; | 1225 | goto out_iput; |
1500 | inode->i_mode = S_IFLNK; | 1226 | inode->i_mode = S_IFLNK; |
1501 | 1227 | ||
1502 | /* | 1228 | /* |
@@ -1506,13 +1232,14 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1506 | spin_lock(&files->file_lock); | 1232 | spin_lock(&files->file_lock); |
1507 | file = fcheck_files(files, fd); | 1233 | file = fcheck_files(files, fd); |
1508 | if (!file) | 1234 | if (!file) |
1509 | goto out_unlock2; | 1235 | goto out_unlock; |
1510 | if (file->f_mode & 1) | 1236 | if (file->f_mode & 1) |
1511 | inode->i_mode |= S_IRUSR | S_IXUSR; | 1237 | inode->i_mode |= S_IRUSR | S_IXUSR; |
1512 | if (file->f_mode & 2) | 1238 | if (file->f_mode & 2) |
1513 | inode->i_mode |= S_IWUSR | S_IXUSR; | 1239 | inode->i_mode |= S_IWUSR | S_IXUSR; |
1514 | spin_unlock(&files->file_lock); | 1240 | spin_unlock(&files->file_lock); |
1515 | put_files_struct(files); | 1241 | put_files_struct(files); |
1242 | |||
1516 | inode->i_op = &proc_pid_link_inode_operations; | 1243 | inode->i_op = &proc_pid_link_inode_operations; |
1517 | inode->i_size = 64; | 1244 | inode->i_size = 64; |
1518 | ei->op.proc_get_link = proc_fd_link; | 1245 | ei->op.proc_get_link = proc_fd_link; |
@@ -1520,34 +1247,106 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1520 | d_add(dentry, inode); | 1247 | d_add(dentry, inode); |
1521 | /* Close the race of the process dying before we return the dentry */ | 1248 | /* Close the race of the process dying before we return the dentry */ |
1522 | if (tid_fd_revalidate(dentry, NULL)) | 1249 | if (tid_fd_revalidate(dentry, NULL)) |
1523 | result = NULL; | 1250 | error = NULL; |
1524 | out: | ||
1525 | put_task_struct(task); | ||
1526 | out_no_task: | ||
1527 | return result; | ||
1528 | 1251 | ||
1529 | out_unlock2: | 1252 | out: |
1253 | return error; | ||
1254 | out_unlock: | ||
1530 | spin_unlock(&files->file_lock); | 1255 | spin_unlock(&files->file_lock); |
1531 | put_files_struct(files); | 1256 | put_files_struct(files); |
1532 | out_unlock: | 1257 | out_iput: |
1533 | iput(inode); | 1258 | iput(inode); |
1534 | goto out; | 1259 | goto out; |
1535 | } | 1260 | } |
1536 | 1261 | ||
1537 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir); | 1262 | static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd) |
1538 | static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd); | 1263 | { |
1539 | static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | 1264 | struct task_struct *task = get_proc_task(dir); |
1265 | unsigned fd = name_to_int(dentry); | ||
1266 | struct dentry *result = ERR_PTR(-ENOENT); | ||
1267 | |||
1268 | if (!task) | ||
1269 | goto out_no_task; | ||
1270 | if (fd == ~0U) | ||
1271 | goto out; | ||
1272 | |||
1273 | result = proc_fd_instantiate(dir, dentry, task, &fd); | ||
1274 | out: | ||
1275 | put_task_struct(task); | ||
1276 | out_no_task: | ||
1277 | return result; | ||
1278 | } | ||
1279 | |||
1280 | static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1281 | struct task_struct *task, int fd) | ||
1282 | { | ||
1283 | char name[PROC_NUMBUF]; | ||
1284 | int len = snprintf(name, sizeof(name), "%d", fd); | ||
1285 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
1286 | proc_fd_instantiate, task, &fd); | ||
1287 | } | ||
1288 | |||
1289 | static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | ||
1290 | { | ||
1291 | struct dentry *dentry = filp->f_dentry; | ||
1292 | struct inode *inode = dentry->d_inode; | ||
1293 | struct task_struct *p = get_proc_task(inode); | ||
1294 | unsigned int fd, tid, ino; | ||
1295 | int retval; | ||
1296 | struct files_struct * files; | ||
1297 | struct fdtable *fdt; | ||
1298 | |||
1299 | retval = -ENOENT; | ||
1300 | if (!p) | ||
1301 | goto out_no_task; | ||
1302 | retval = 0; | ||
1303 | tid = p->pid; | ||
1304 | |||
1305 | fd = filp->f_pos; | ||
1306 | switch (fd) { | ||
1307 | case 0: | ||
1308 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | ||
1309 | goto out; | ||
1310 | filp->f_pos++; | ||
1311 | case 1: | ||
1312 | ino = parent_ino(dentry); | ||
1313 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
1314 | goto out; | ||
1315 | filp->f_pos++; | ||
1316 | default: | ||
1317 | files = get_files_struct(p); | ||
1318 | if (!files) | ||
1319 | goto out; | ||
1320 | rcu_read_lock(); | ||
1321 | fdt = files_fdtable(files); | ||
1322 | for (fd = filp->f_pos-2; | ||
1323 | fd < fdt->max_fds; | ||
1324 | fd++, filp->f_pos++) { | ||
1325 | |||
1326 | if (!fcheck_files(files, fd)) | ||
1327 | continue; | ||
1328 | rcu_read_unlock(); | ||
1329 | |||
1330 | if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) { | ||
1331 | rcu_read_lock(); | ||
1332 | break; | ||
1333 | } | ||
1334 | rcu_read_lock(); | ||
1335 | } | ||
1336 | rcu_read_unlock(); | ||
1337 | put_files_struct(files); | ||
1338 | } | ||
1339 | out: | ||
1340 | put_task_struct(p); | ||
1341 | out_no_task: | ||
1342 | return retval; | ||
1343 | } | ||
1540 | 1344 | ||
1541 | static struct file_operations proc_fd_operations = { | 1345 | static struct file_operations proc_fd_operations = { |
1542 | .read = generic_read_dir, | 1346 | .read = generic_read_dir, |
1543 | .readdir = proc_readfd, | 1347 | .readdir = proc_readfd, |
1544 | }; | 1348 | }; |
1545 | 1349 | ||
1546 | static struct file_operations proc_task_operations = { | ||
1547 | .read = generic_read_dir, | ||
1548 | .readdir = proc_task_readdir, | ||
1549 | }; | ||
1550 | |||
1551 | /* | 1350 | /* |
1552 | * proc directories can do almost nothing.. | 1351 | * proc directories can do almost nothing.. |
1553 | */ | 1352 | */ |
@@ -1556,11 +1355,137 @@ static struct inode_operations proc_fd_inode_operations = { | |||
1556 | .setattr = proc_setattr, | 1355 | .setattr = proc_setattr, |
1557 | }; | 1356 | }; |
1558 | 1357 | ||
1559 | static struct inode_operations proc_task_inode_operations = { | 1358 | static struct dentry *proc_pident_instantiate(struct inode *dir, |
1560 | .lookup = proc_task_lookup, | 1359 | struct dentry *dentry, struct task_struct *task, void *ptr) |
1561 | .getattr = proc_task_getattr, | 1360 | { |
1562 | .setattr = proc_setattr, | 1361 | struct pid_entry *p = ptr; |
1563 | }; | 1362 | struct inode *inode; |
1363 | struct proc_inode *ei; | ||
1364 | struct dentry *error = ERR_PTR(-EINVAL); | ||
1365 | |||
1366 | inode = proc_pid_make_inode(dir->i_sb, task); | ||
1367 | if (!inode) | ||
1368 | goto out; | ||
1369 | |||
1370 | ei = PROC_I(inode); | ||
1371 | inode->i_mode = p->mode; | ||
1372 | if (S_ISDIR(inode->i_mode)) | ||
1373 | inode->i_nlink = 2; /* Use getattr to fix if necessary */ | ||
1374 | if (p->iop) | ||
1375 | inode->i_op = p->iop; | ||
1376 | if (p->fop) | ||
1377 | inode->i_fop = p->fop; | ||
1378 | ei->op = p->op; | ||
1379 | dentry->d_op = &pid_dentry_operations; | ||
1380 | d_add(dentry, inode); | ||
1381 | /* Close the race of the process dying before we return the dentry */ | ||
1382 | if (pid_revalidate(dentry, NULL)) | ||
1383 | error = NULL; | ||
1384 | out: | ||
1385 | return error; | ||
1386 | } | ||
1387 | |||
1388 | static struct dentry *proc_pident_lookup(struct inode *dir, | ||
1389 | struct dentry *dentry, | ||
1390 | struct pid_entry *ents, | ||
1391 | unsigned int nents) | ||
1392 | { | ||
1393 | struct inode *inode; | ||
1394 | struct dentry *error; | ||
1395 | struct task_struct *task = get_proc_task(dir); | ||
1396 | struct pid_entry *p, *last; | ||
1397 | |||
1398 | error = ERR_PTR(-ENOENT); | ||
1399 | inode = NULL; | ||
1400 | |||
1401 | if (!task) | ||
1402 | goto out_no_task; | ||
1403 | |||
1404 | /* | ||
1405 | * Yes, it does not scale. And it should not. Don't add | ||
1406 | * new entries into /proc/<tgid>/ without very good reasons. | ||
1407 | */ | ||
1408 | last = &ents[nents - 1]; | ||
1409 | for (p = ents; p <= last; p++) { | ||
1410 | if (p->len != dentry->d_name.len) | ||
1411 | continue; | ||
1412 | if (!memcmp(dentry->d_name.name, p->name, p->len)) | ||
1413 | break; | ||
1414 | } | ||
1415 | if (p > last) | ||
1416 | goto out; | ||
1417 | |||
1418 | error = proc_pident_instantiate(dir, dentry, task, p); | ||
1419 | out: | ||
1420 | put_task_struct(task); | ||
1421 | out_no_task: | ||
1422 | return error; | ||
1423 | } | ||
1424 | |||
1425 | static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
1426 | struct task_struct *task, struct pid_entry *p) | ||
1427 | { | ||
1428 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, | ||
1429 | proc_pident_instantiate, task, p); | ||
1430 | } | ||
1431 | |||
1432 | static int proc_pident_readdir(struct file *filp, | ||
1433 | void *dirent, filldir_t filldir, | ||
1434 | struct pid_entry *ents, unsigned int nents) | ||
1435 | { | ||
1436 | int i; | ||
1437 | int pid; | ||
1438 | struct dentry *dentry = filp->f_dentry; | ||
1439 | struct inode *inode = dentry->d_inode; | ||
1440 | struct task_struct *task = get_proc_task(inode); | ||
1441 | struct pid_entry *p, *last; | ||
1442 | ino_t ino; | ||
1443 | int ret; | ||
1444 | |||
1445 | ret = -ENOENT; | ||
1446 | if (!task) | ||
1447 | goto out_no_task; | ||
1448 | |||
1449 | ret = 0; | ||
1450 | pid = task->pid; | ||
1451 | i = filp->f_pos; | ||
1452 | switch (i) { | ||
1453 | case 0: | ||
1454 | ino = inode->i_ino; | ||
1455 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
1456 | goto out; | ||
1457 | i++; | ||
1458 | filp->f_pos++; | ||
1459 | /* fall through */ | ||
1460 | case 1: | ||
1461 | ino = parent_ino(dentry); | ||
1462 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | ||
1463 | goto out; | ||
1464 | i++; | ||
1465 | filp->f_pos++; | ||
1466 | /* fall through */ | ||
1467 | default: | ||
1468 | i -= 2; | ||
1469 | if (i >= nents) { | ||
1470 | ret = 1; | ||
1471 | goto out; | ||
1472 | } | ||
1473 | p = ents + i; | ||
1474 | last = &ents[nents - 1]; | ||
1475 | while (p <= last) { | ||
1476 | if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0) | ||
1477 | goto out; | ||
1478 | filp->f_pos++; | ||
1479 | p++; | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | ret = 1; | ||
1484 | out: | ||
1485 | put_task_struct(task); | ||
1486 | out_no_task: | ||
1487 | return ret; | ||
1488 | } | ||
1564 | 1489 | ||
1565 | #ifdef CONFIG_SECURITY | 1490 | #ifdef CONFIG_SECURITY |
1566 | static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, | 1491 | static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, |
@@ -1581,8 +1506,8 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, | |||
1581 | if (!(page = __get_free_page(GFP_KERNEL))) | 1506 | if (!(page = __get_free_page(GFP_KERNEL))) |
1582 | goto out; | 1507 | goto out; |
1583 | 1508 | ||
1584 | length = security_getprocattr(task, | 1509 | length = security_getprocattr(task, |
1585 | (char*)file->f_dentry->d_name.name, | 1510 | (char*)file->f_dentry->d_name.name, |
1586 | (void*)page, count); | 1511 | (void*)page, count); |
1587 | if (length >= 0) | 1512 | if (length >= 0) |
1588 | length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); | 1513 | length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); |
@@ -1595,17 +1520,17 @@ out_no_task: | |||
1595 | 1520 | ||
1596 | static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, | 1521 | static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, |
1597 | size_t count, loff_t *ppos) | 1522 | size_t count, loff_t *ppos) |
1598 | { | 1523 | { |
1599 | struct inode * inode = file->f_dentry->d_inode; | 1524 | struct inode * inode = file->f_dentry->d_inode; |
1600 | char *page; | 1525 | char *page; |
1601 | ssize_t length; | 1526 | ssize_t length; |
1602 | struct task_struct *task = get_proc_task(inode); | 1527 | struct task_struct *task = get_proc_task(inode); |
1603 | 1528 | ||
1604 | length = -ESRCH; | 1529 | length = -ESRCH; |
1605 | if (!task) | 1530 | if (!task) |
1606 | goto out_no_task; | 1531 | goto out_no_task; |
1607 | if (count > PAGE_SIZE) | 1532 | if (count > PAGE_SIZE) |
1608 | count = PAGE_SIZE; | 1533 | count = PAGE_SIZE; |
1609 | 1534 | ||
1610 | /* No partial writes. */ | 1535 | /* No partial writes. */ |
1611 | length = -EINVAL; | 1536 | length = -EINVAL; |
@@ -1613,16 +1538,16 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, | |||
1613 | goto out; | 1538 | goto out; |
1614 | 1539 | ||
1615 | length = -ENOMEM; | 1540 | length = -ENOMEM; |
1616 | page = (char*)__get_free_page(GFP_USER); | 1541 | page = (char*)__get_free_page(GFP_USER); |
1617 | if (!page) | 1542 | if (!page) |
1618 | goto out; | 1543 | goto out; |
1619 | 1544 | ||
1620 | length = -EFAULT; | 1545 | length = -EFAULT; |
1621 | if (copy_from_user(page, buf, count)) | 1546 | if (copy_from_user(page, buf, count)) |
1622 | goto out_free; | 1547 | goto out_free; |
1623 | 1548 | ||
1624 | length = security_setprocattr(task, | 1549 | length = security_setprocattr(task, |
1625 | (char*)file->f_dentry->d_name.name, | 1550 | (char*)file->f_dentry->d_name.name, |
1626 | (void*)page, count); | 1551 | (void*)page, count); |
1627 | out_free: | 1552 | out_free: |
1628 | free_page((unsigned long) page); | 1553 | free_page((unsigned long) page); |
@@ -1630,330 +1555,263 @@ out: | |||
1630 | put_task_struct(task); | 1555 | put_task_struct(task); |
1631 | out_no_task: | 1556 | out_no_task: |
1632 | return length; | 1557 | return length; |
1633 | } | 1558 | } |
1634 | 1559 | ||
1635 | static struct file_operations proc_pid_attr_operations = { | 1560 | static struct file_operations proc_pid_attr_operations = { |
1636 | .read = proc_pid_attr_read, | 1561 | .read = proc_pid_attr_read, |
1637 | .write = proc_pid_attr_write, | 1562 | .write = proc_pid_attr_write, |
1638 | }; | 1563 | }; |
1639 | 1564 | ||
1640 | static struct file_operations proc_tid_attr_operations; | 1565 | static struct pid_entry attr_dir_stuff[] = { |
1641 | static struct inode_operations proc_tid_attr_inode_operations; | 1566 | REG("current", S_IRUGO|S_IWUGO, pid_attr), |
1642 | static struct file_operations proc_tgid_attr_operations; | 1567 | REG("prev", S_IRUGO, pid_attr), |
1643 | static struct inode_operations proc_tgid_attr_inode_operations; | 1568 | REG("exec", S_IRUGO|S_IWUGO, pid_attr), |
1569 | REG("fscreate", S_IRUGO|S_IWUGO, pid_attr), | ||
1570 | REG("keycreate", S_IRUGO|S_IWUGO, pid_attr), | ||
1571 | REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr), | ||
1572 | }; | ||
1573 | |||
1574 | static int proc_attr_dir_readdir(struct file * filp, | ||
1575 | void * dirent, filldir_t filldir) | ||
1576 | { | ||
1577 | return proc_pident_readdir(filp,dirent,filldir, | ||
1578 | attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); | ||
1579 | } | ||
1580 | |||
1581 | static struct file_operations proc_attr_dir_operations = { | ||
1582 | .read = generic_read_dir, | ||
1583 | .readdir = proc_attr_dir_readdir, | ||
1584 | }; | ||
1585 | |||
1586 | static struct dentry *proc_attr_dir_lookup(struct inode *dir, | ||
1587 | struct dentry *dentry, struct nameidata *nd) | ||
1588 | { | ||
1589 | return proc_pident_lookup(dir, dentry, | ||
1590 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); | ||
1591 | } | ||
1592 | |||
1593 | static struct inode_operations proc_attr_dir_inode_operations = { | ||
1594 | .lookup = proc_attr_dir_lookup, | ||
1595 | .getattr = pid_getattr, | ||
1596 | .setattr = proc_setattr, | ||
1597 | }; | ||
1598 | |||
1644 | #endif | 1599 | #endif |
1645 | 1600 | ||
1646 | /* SMP-safe */ | 1601 | /* |
1647 | static struct dentry *proc_pident_lookup(struct inode *dir, | 1602 | * /proc/self: |
1648 | struct dentry *dentry, | 1603 | */ |
1649 | struct pid_entry *ents) | 1604 | static int proc_self_readlink(struct dentry *dentry, char __user *buffer, |
1605 | int buflen) | ||
1606 | { | ||
1607 | char tmp[PROC_NUMBUF]; | ||
1608 | sprintf(tmp, "%d", current->tgid); | ||
1609 | return vfs_readlink(dentry,buffer,buflen,tmp); | ||
1610 | } | ||
1611 | |||
1612 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
1650 | { | 1613 | { |
1614 | char tmp[PROC_NUMBUF]; | ||
1615 | sprintf(tmp, "%d", current->tgid); | ||
1616 | return ERR_PTR(vfs_follow_link(nd,tmp)); | ||
1617 | } | ||
1618 | |||
1619 | static struct inode_operations proc_self_inode_operations = { | ||
1620 | .readlink = proc_self_readlink, | ||
1621 | .follow_link = proc_self_follow_link, | ||
1622 | }; | ||
1623 | |||
1624 | /* | ||
1625 | * proc base | ||
1626 | * | ||
1627 | * These are the directory entries in the root directory of /proc | ||
1628 | * that properly belong to the /proc filesystem, as they describe | ||
1629 | * describe something that is process related. | ||
1630 | */ | ||
1631 | static struct pid_entry proc_base_stuff[] = { | ||
1632 | NOD("self", S_IFLNK|S_IRWXUGO, | ||
1633 | &proc_self_inode_operations, NULL, {}), | ||
1634 | }; | ||
1635 | |||
1636 | /* | ||
1637 | * Exceptional case: normally we are not allowed to unhash a busy | ||
1638 | * directory. In this case, however, we can do it - no aliasing problems | ||
1639 | * due to the way we treat inodes. | ||
1640 | */ | ||
1641 | static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
1642 | { | ||
1643 | struct inode *inode = dentry->d_inode; | ||
1644 | struct task_struct *task = get_proc_task(inode); | ||
1645 | if (task) { | ||
1646 | put_task_struct(task); | ||
1647 | return 1; | ||
1648 | } | ||
1649 | d_drop(dentry); | ||
1650 | return 0; | ||
1651 | } | ||
1652 | |||
1653 | static struct dentry_operations proc_base_dentry_operations = | ||
1654 | { | ||
1655 | .d_revalidate = proc_base_revalidate, | ||
1656 | .d_delete = pid_delete_dentry, | ||
1657 | }; | ||
1658 | |||
1659 | static struct dentry *proc_base_instantiate(struct inode *dir, | ||
1660 | struct dentry *dentry, struct task_struct *task, void *ptr) | ||
1661 | { | ||
1662 | struct pid_entry *p = ptr; | ||
1651 | struct inode *inode; | 1663 | struct inode *inode; |
1664 | struct proc_inode *ei; | ||
1665 | struct dentry *error = ERR_PTR(-EINVAL); | ||
1666 | |||
1667 | /* Allocate the inode */ | ||
1668 | error = ERR_PTR(-ENOMEM); | ||
1669 | inode = new_inode(dir->i_sb); | ||
1670 | if (!inode) | ||
1671 | goto out; | ||
1672 | |||
1673 | /* Initialize the inode */ | ||
1674 | ei = PROC_I(inode); | ||
1675 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
1676 | |||
1677 | /* | ||
1678 | * grab the reference to the task. | ||
1679 | */ | ||
1680 | ei->pid = get_task_pid(task, PIDTYPE_PID); | ||
1681 | if (!ei->pid) | ||
1682 | goto out_iput; | ||
1683 | |||
1684 | inode->i_uid = 0; | ||
1685 | inode->i_gid = 0; | ||
1686 | inode->i_mode = p->mode; | ||
1687 | if (S_ISDIR(inode->i_mode)) | ||
1688 | inode->i_nlink = 2; | ||
1689 | if (S_ISLNK(inode->i_mode)) | ||
1690 | inode->i_size = 64; | ||
1691 | if (p->iop) | ||
1692 | inode->i_op = p->iop; | ||
1693 | if (p->fop) | ||
1694 | inode->i_fop = p->fop; | ||
1695 | ei->op = p->op; | ||
1696 | dentry->d_op = &proc_base_dentry_operations; | ||
1697 | d_add(dentry, inode); | ||
1698 | error = NULL; | ||
1699 | out: | ||
1700 | return error; | ||
1701 | out_iput: | ||
1702 | iput(inode); | ||
1703 | goto out; | ||
1704 | } | ||
1705 | |||
1706 | static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) | ||
1707 | { | ||
1652 | struct dentry *error; | 1708 | struct dentry *error; |
1653 | struct task_struct *task = get_proc_task(dir); | 1709 | struct task_struct *task = get_proc_task(dir); |
1654 | struct pid_entry *p; | 1710 | struct pid_entry *p, *last; |
1655 | struct proc_inode *ei; | ||
1656 | 1711 | ||
1657 | error = ERR_PTR(-ENOENT); | 1712 | error = ERR_PTR(-ENOENT); |
1658 | inode = NULL; | ||
1659 | 1713 | ||
1660 | if (!task) | 1714 | if (!task) |
1661 | goto out_no_task; | 1715 | goto out_no_task; |
1662 | 1716 | ||
1663 | for (p = ents; p->name; p++) { | 1717 | /* Lookup the directory entry */ |
1718 | last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1]; | ||
1719 | for (p = proc_base_stuff; p <= last; p++) { | ||
1664 | if (p->len != dentry->d_name.len) | 1720 | if (p->len != dentry->d_name.len) |
1665 | continue; | 1721 | continue; |
1666 | if (!memcmp(dentry->d_name.name, p->name, p->len)) | 1722 | if (!memcmp(dentry->d_name.name, p->name, p->len)) |
1667 | break; | 1723 | break; |
1668 | } | 1724 | } |
1669 | if (!p->name) | 1725 | if (p > last) |
1670 | goto out; | 1726 | goto out; |
1671 | 1727 | ||
1672 | error = ERR_PTR(-EINVAL); | 1728 | error = proc_base_instantiate(dir, dentry, task, p); |
1673 | inode = proc_pid_make_inode(dir->i_sb, task, p->type); | ||
1674 | if (!inode) | ||
1675 | goto out; | ||
1676 | 1729 | ||
1677 | ei = PROC_I(inode); | 1730 | out: |
1678 | inode->i_mode = p->mode; | 1731 | put_task_struct(task); |
1679 | /* | 1732 | out_no_task: |
1680 | * Yes, it does not scale. And it should not. Don't add | 1733 | return error; |
1681 | * new entries into /proc/<tgid>/ without very good reasons. | 1734 | } |
1682 | */ | 1735 | |
1683 | switch(p->type) { | 1736 | static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
1684 | case PROC_TGID_TASK: | 1737 | struct task_struct *task, struct pid_entry *p) |
1685 | inode->i_nlink = 2; | 1738 | { |
1686 | inode->i_op = &proc_task_inode_operations; | 1739 | return proc_fill_cache(filp, dirent, filldir, p->name, p->len, |
1687 | inode->i_fop = &proc_task_operations; | 1740 | proc_base_instantiate, task, p); |
1688 | break; | 1741 | } |
1689 | case PROC_TID_FD: | 1742 | |
1690 | case PROC_TGID_FD: | 1743 | /* |
1691 | inode->i_nlink = 2; | 1744 | * Thread groups |
1692 | inode->i_op = &proc_fd_inode_operations; | 1745 | */ |
1693 | inode->i_fop = &proc_fd_operations; | 1746 | static struct file_operations proc_task_operations; |
1694 | break; | 1747 | static struct inode_operations proc_task_inode_operations; |
1695 | case PROC_TID_EXE: | 1748 | |
1696 | case PROC_TGID_EXE: | 1749 | static struct pid_entry tgid_base_stuff[] = { |
1697 | inode->i_op = &proc_pid_link_inode_operations; | 1750 | DIR("task", S_IRUGO|S_IXUGO, task), |
1698 | ei->op.proc_get_link = proc_exe_link; | 1751 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
1699 | break; | 1752 | INF("environ", S_IRUSR, pid_environ), |
1700 | case PROC_TID_CWD: | 1753 | INF("auxv", S_IRUSR, pid_auxv), |
1701 | case PROC_TGID_CWD: | 1754 | INF("status", S_IRUGO, pid_status), |
1702 | inode->i_op = &proc_pid_link_inode_operations; | 1755 | INF("cmdline", S_IRUGO, pid_cmdline), |
1703 | ei->op.proc_get_link = proc_cwd_link; | 1756 | INF("stat", S_IRUGO, tgid_stat), |
1704 | break; | 1757 | INF("statm", S_IRUGO, pid_statm), |
1705 | case PROC_TID_ROOT: | 1758 | REG("maps", S_IRUGO, maps), |
1706 | case PROC_TGID_ROOT: | ||
1707 | inode->i_op = &proc_pid_link_inode_operations; | ||
1708 | ei->op.proc_get_link = proc_root_link; | ||
1709 | break; | ||
1710 | case PROC_TID_ENVIRON: | ||
1711 | case PROC_TGID_ENVIRON: | ||
1712 | inode->i_fop = &proc_info_file_operations; | ||
1713 | ei->op.proc_read = proc_pid_environ; | ||
1714 | break; | ||
1715 | case PROC_TID_AUXV: | ||
1716 | case PROC_TGID_AUXV: | ||
1717 | inode->i_fop = &proc_info_file_operations; | ||
1718 | ei->op.proc_read = proc_pid_auxv; | ||
1719 | break; | ||
1720 | case PROC_TID_STATUS: | ||
1721 | case PROC_TGID_STATUS: | ||
1722 | inode->i_fop = &proc_info_file_operations; | ||
1723 | ei->op.proc_read = proc_pid_status; | ||
1724 | break; | ||
1725 | case PROC_TID_STAT: | ||
1726 | inode->i_fop = &proc_info_file_operations; | ||
1727 | ei->op.proc_read = proc_tid_stat; | ||
1728 | break; | ||
1729 | case PROC_TGID_STAT: | ||
1730 | inode->i_fop = &proc_info_file_operations; | ||
1731 | ei->op.proc_read = proc_tgid_stat; | ||
1732 | break; | ||
1733 | case PROC_TID_CMDLINE: | ||
1734 | case PROC_TGID_CMDLINE: | ||
1735 | inode->i_fop = &proc_info_file_operations; | ||
1736 | ei->op.proc_read = proc_pid_cmdline; | ||
1737 | break; | ||
1738 | case PROC_TID_STATM: | ||
1739 | case PROC_TGID_STATM: | ||
1740 | inode->i_fop = &proc_info_file_operations; | ||
1741 | ei->op.proc_read = proc_pid_statm; | ||
1742 | break; | ||
1743 | case PROC_TID_MAPS: | ||
1744 | case PROC_TGID_MAPS: | ||
1745 | inode->i_fop = &proc_maps_operations; | ||
1746 | break; | ||
1747 | #ifdef CONFIG_NUMA | 1759 | #ifdef CONFIG_NUMA |
1748 | case PROC_TID_NUMA_MAPS: | 1760 | REG("numa_maps", S_IRUGO, numa_maps), |
1749 | case PROC_TGID_NUMA_MAPS: | ||
1750 | inode->i_fop = &proc_numa_maps_operations; | ||
1751 | break; | ||
1752 | #endif | 1761 | #endif |
1753 | case PROC_TID_MEM: | 1762 | REG("mem", S_IRUSR|S_IWUSR, mem), |
1754 | case PROC_TGID_MEM: | ||
1755 | inode->i_fop = &proc_mem_operations; | ||
1756 | break; | ||
1757 | #ifdef CONFIG_SECCOMP | 1763 | #ifdef CONFIG_SECCOMP |
1758 | case PROC_TID_SECCOMP: | 1764 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), |
1759 | case PROC_TGID_SECCOMP: | 1765 | #endif |
1760 | inode->i_fop = &proc_seccomp_operations; | 1766 | LNK("cwd", cwd), |
1761 | break; | 1767 | LNK("root", root), |
1762 | #endif /* CONFIG_SECCOMP */ | 1768 | LNK("exe", exe), |
1763 | case PROC_TID_MOUNTS: | 1769 | REG("mounts", S_IRUGO, mounts), |
1764 | case PROC_TGID_MOUNTS: | 1770 | REG("mountstats", S_IRUSR, mountstats), |
1765 | inode->i_fop = &proc_mounts_operations; | ||
1766 | break; | ||
1767 | #ifdef CONFIG_MMU | 1771 | #ifdef CONFIG_MMU |
1768 | case PROC_TID_SMAPS: | 1772 | REG("smaps", S_IRUGO, smaps), |
1769 | case PROC_TGID_SMAPS: | ||
1770 | inode->i_fop = &proc_smaps_operations; | ||
1771 | break; | ||
1772 | #endif | 1773 | #endif |
1773 | case PROC_TID_MOUNTSTATS: | ||
1774 | case PROC_TGID_MOUNTSTATS: | ||
1775 | inode->i_fop = &proc_mountstats_operations; | ||
1776 | break; | ||
1777 | #ifdef CONFIG_SECURITY | 1774 | #ifdef CONFIG_SECURITY |
1778 | case PROC_TID_ATTR: | 1775 | DIR("attr", S_IRUGO|S_IXUGO, attr_dir), |
1779 | inode->i_nlink = 2; | ||
1780 | inode->i_op = &proc_tid_attr_inode_operations; | ||
1781 | inode->i_fop = &proc_tid_attr_operations; | ||
1782 | break; | ||
1783 | case PROC_TGID_ATTR: | ||
1784 | inode->i_nlink = 2; | ||
1785 | inode->i_op = &proc_tgid_attr_inode_operations; | ||
1786 | inode->i_fop = &proc_tgid_attr_operations; | ||
1787 | break; | ||
1788 | case PROC_TID_ATTR_CURRENT: | ||
1789 | case PROC_TGID_ATTR_CURRENT: | ||
1790 | case PROC_TID_ATTR_PREV: | ||
1791 | case PROC_TGID_ATTR_PREV: | ||
1792 | case PROC_TID_ATTR_EXEC: | ||
1793 | case PROC_TGID_ATTR_EXEC: | ||
1794 | case PROC_TID_ATTR_FSCREATE: | ||
1795 | case PROC_TGID_ATTR_FSCREATE: | ||
1796 | case PROC_TID_ATTR_KEYCREATE: | ||
1797 | case PROC_TGID_ATTR_KEYCREATE: | ||
1798 | case PROC_TID_ATTR_SOCKCREATE: | ||
1799 | case PROC_TGID_ATTR_SOCKCREATE: | ||
1800 | inode->i_fop = &proc_pid_attr_operations; | ||
1801 | break; | ||
1802 | #endif | 1776 | #endif |
1803 | #ifdef CONFIG_KALLSYMS | 1777 | #ifdef CONFIG_KALLSYMS |
1804 | case PROC_TID_WCHAN: | 1778 | INF("wchan", S_IRUGO, pid_wchan), |
1805 | case PROC_TGID_WCHAN: | ||
1806 | inode->i_fop = &proc_info_file_operations; | ||
1807 | ei->op.proc_read = proc_pid_wchan; | ||
1808 | break; | ||
1809 | #endif | 1779 | #endif |
1810 | #ifdef CONFIG_SCHEDSTATS | 1780 | #ifdef CONFIG_SCHEDSTATS |
1811 | case PROC_TID_SCHEDSTAT: | 1781 | INF("schedstat", S_IRUGO, pid_schedstat), |
1812 | case PROC_TGID_SCHEDSTAT: | ||
1813 | inode->i_fop = &proc_info_file_operations; | ||
1814 | ei->op.proc_read = proc_pid_schedstat; | ||
1815 | break; | ||
1816 | #endif | 1782 | #endif |
1817 | #ifdef CONFIG_CPUSETS | 1783 | #ifdef CONFIG_CPUSETS |
1818 | case PROC_TID_CPUSET: | 1784 | REG("cpuset", S_IRUGO, cpuset), |
1819 | case PROC_TGID_CPUSET: | ||
1820 | inode->i_fop = &proc_cpuset_operations; | ||
1821 | break; | ||
1822 | #endif | 1785 | #endif |
1823 | case PROC_TID_OOM_SCORE: | 1786 | INF("oom_score", S_IRUGO, oom_score), |
1824 | case PROC_TGID_OOM_SCORE: | 1787 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
1825 | inode->i_fop = &proc_info_file_operations; | ||
1826 | ei->op.proc_read = proc_oom_score; | ||
1827 | break; | ||
1828 | case PROC_TID_OOM_ADJUST: | ||
1829 | case PROC_TGID_OOM_ADJUST: | ||
1830 | inode->i_fop = &proc_oom_adjust_operations; | ||
1831 | break; | ||
1832 | #ifdef CONFIG_AUDITSYSCALL | 1788 | #ifdef CONFIG_AUDITSYSCALL |
1833 | case PROC_TID_LOGINUID: | 1789 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
1834 | case PROC_TGID_LOGINUID: | ||
1835 | inode->i_fop = &proc_loginuid_operations; | ||
1836 | break; | ||
1837 | #endif | 1790 | #endif |
1838 | default: | ||
1839 | printk("procfs: impossible type (%d)",p->type); | ||
1840 | iput(inode); | ||
1841 | error = ERR_PTR(-EINVAL); | ||
1842 | goto out; | ||
1843 | } | ||
1844 | dentry->d_op = &pid_dentry_operations; | ||
1845 | d_add(dentry, inode); | ||
1846 | /* Close the race of the process dying before we return the dentry */ | ||
1847 | if (pid_revalidate(dentry, NULL)) | ||
1848 | error = NULL; | ||
1849 | out: | ||
1850 | put_task_struct(task); | ||
1851 | out_no_task: | ||
1852 | return error; | ||
1853 | } | ||
1854 | |||
1855 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | ||
1856 | return proc_pident_lookup(dir, dentry, tgid_base_stuff); | ||
1857 | } | ||
1858 | |||
1859 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | ||
1860 | return proc_pident_lookup(dir, dentry, tid_base_stuff); | ||
1861 | } | ||
1862 | |||
1863 | static struct file_operations proc_tgid_base_operations = { | ||
1864 | .read = generic_read_dir, | ||
1865 | .readdir = proc_tgid_base_readdir, | ||
1866 | }; | 1791 | }; |
1867 | 1792 | ||
1868 | static struct file_operations proc_tid_base_operations = { | 1793 | static int proc_tgid_base_readdir(struct file * filp, |
1869 | .read = generic_read_dir, | ||
1870 | .readdir = proc_tid_base_readdir, | ||
1871 | }; | ||
1872 | |||
1873 | static struct inode_operations proc_tgid_base_inode_operations = { | ||
1874 | .lookup = proc_tgid_base_lookup, | ||
1875 | .getattr = pid_getattr, | ||
1876 | .setattr = proc_setattr, | ||
1877 | }; | ||
1878 | |||
1879 | static struct inode_operations proc_tid_base_inode_operations = { | ||
1880 | .lookup = proc_tid_base_lookup, | ||
1881 | .getattr = pid_getattr, | ||
1882 | .setattr = proc_setattr, | ||
1883 | }; | ||
1884 | |||
1885 | #ifdef CONFIG_SECURITY | ||
1886 | static int proc_tgid_attr_readdir(struct file * filp, | ||
1887 | void * dirent, filldir_t filldir) | ||
1888 | { | ||
1889 | return proc_pident_readdir(filp,dirent,filldir, | ||
1890 | tgid_attr_stuff,ARRAY_SIZE(tgid_attr_stuff)); | ||
1891 | } | ||
1892 | |||
1893 | static int proc_tid_attr_readdir(struct file * filp, | ||
1894 | void * dirent, filldir_t filldir) | 1794 | void * dirent, filldir_t filldir) |
1895 | { | 1795 | { |
1896 | return proc_pident_readdir(filp,dirent,filldir, | 1796 | return proc_pident_readdir(filp,dirent,filldir, |
1897 | tid_attr_stuff,ARRAY_SIZE(tid_attr_stuff)); | 1797 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); |
1898 | } | 1798 | } |
1899 | 1799 | ||
1900 | static struct file_operations proc_tgid_attr_operations = { | 1800 | static struct file_operations proc_tgid_base_operations = { |
1901 | .read = generic_read_dir, | ||
1902 | .readdir = proc_tgid_attr_readdir, | ||
1903 | }; | ||
1904 | |||
1905 | static struct file_operations proc_tid_attr_operations = { | ||
1906 | .read = generic_read_dir, | 1801 | .read = generic_read_dir, |
1907 | .readdir = proc_tid_attr_readdir, | 1802 | .readdir = proc_tgid_base_readdir, |
1908 | }; | 1803 | }; |
1909 | 1804 | ||
1910 | static struct dentry *proc_tgid_attr_lookup(struct inode *dir, | 1805 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ |
1911 | struct dentry *dentry, struct nameidata *nd) | 1806 | return proc_pident_lookup(dir, dentry, |
1912 | { | 1807 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); |
1913 | return proc_pident_lookup(dir, dentry, tgid_attr_stuff); | ||
1914 | } | ||
1915 | |||
1916 | static struct dentry *proc_tid_attr_lookup(struct inode *dir, | ||
1917 | struct dentry *dentry, struct nameidata *nd) | ||
1918 | { | ||
1919 | return proc_pident_lookup(dir, dentry, tid_attr_stuff); | ||
1920 | } | 1808 | } |
1921 | 1809 | ||
1922 | static struct inode_operations proc_tgid_attr_inode_operations = { | 1810 | static struct inode_operations proc_tgid_base_inode_operations = { |
1923 | .lookup = proc_tgid_attr_lookup, | 1811 | .lookup = proc_tgid_base_lookup, |
1924 | .getattr = pid_getattr, | ||
1925 | .setattr = proc_setattr, | ||
1926 | }; | ||
1927 | |||
1928 | static struct inode_operations proc_tid_attr_inode_operations = { | ||
1929 | .lookup = proc_tid_attr_lookup, | ||
1930 | .getattr = pid_getattr, | 1812 | .getattr = pid_getattr, |
1931 | .setattr = proc_setattr, | 1813 | .setattr = proc_setattr, |
1932 | }; | 1814 | }; |
1933 | #endif | ||
1934 | |||
1935 | /* | ||
1936 | * /proc/self: | ||
1937 | */ | ||
1938 | static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | ||
1939 | int buflen) | ||
1940 | { | ||
1941 | char tmp[PROC_NUMBUF]; | ||
1942 | sprintf(tmp, "%d", current->tgid); | ||
1943 | return vfs_readlink(dentry,buffer,buflen,tmp); | ||
1944 | } | ||
1945 | |||
1946 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
1947 | { | ||
1948 | char tmp[PROC_NUMBUF]; | ||
1949 | sprintf(tmp, "%d", current->tgid); | ||
1950 | return ERR_PTR(vfs_follow_link(nd,tmp)); | ||
1951 | } | ||
1952 | |||
1953 | static struct inode_operations proc_self_inode_operations = { | ||
1954 | .readlink = proc_self_readlink, | ||
1955 | .follow_link = proc_self_follow_link, | ||
1956 | }; | ||
1957 | 1815 | ||
1958 | /** | 1816 | /** |
1959 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. | 1817 | * proc_flush_task - Remove dcache entries for @task from the /proc dcache. |
@@ -2022,54 +1880,23 @@ out: | |||
2022 | return; | 1880 | return; |
2023 | } | 1881 | } |
2024 | 1882 | ||
2025 | /* SMP-safe */ | 1883 | struct dentry *proc_pid_instantiate(struct inode *dir, |
2026 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 1884 | struct dentry * dentry, struct task_struct *task, void *ptr) |
2027 | { | 1885 | { |
2028 | struct dentry *result = ERR_PTR(-ENOENT); | 1886 | struct dentry *error = ERR_PTR(-ENOENT); |
2029 | struct task_struct *task; | ||
2030 | struct inode *inode; | 1887 | struct inode *inode; |
2031 | struct proc_inode *ei; | ||
2032 | unsigned tgid; | ||
2033 | |||
2034 | if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) { | ||
2035 | inode = new_inode(dir->i_sb); | ||
2036 | if (!inode) | ||
2037 | return ERR_PTR(-ENOMEM); | ||
2038 | ei = PROC_I(inode); | ||
2039 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
2040 | inode->i_ino = fake_ino(0, PROC_TGID_INO); | ||
2041 | ei->pde = NULL; | ||
2042 | inode->i_mode = S_IFLNK|S_IRWXUGO; | ||
2043 | inode->i_uid = inode->i_gid = 0; | ||
2044 | inode->i_size = 64; | ||
2045 | inode->i_op = &proc_self_inode_operations; | ||
2046 | d_add(dentry, inode); | ||
2047 | return NULL; | ||
2048 | } | ||
2049 | tgid = name_to_int(dentry); | ||
2050 | if (tgid == ~0U) | ||
2051 | goto out; | ||
2052 | 1888 | ||
2053 | rcu_read_lock(); | 1889 | inode = proc_pid_make_inode(dir->i_sb, task); |
2054 | task = find_task_by_pid(tgid); | ||
2055 | if (task) | ||
2056 | get_task_struct(task); | ||
2057 | rcu_read_unlock(); | ||
2058 | if (!task) | ||
2059 | goto out; | ||
2060 | |||
2061 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); | ||
2062 | if (!inode) | 1890 | if (!inode) |
2063 | goto out_put_task; | 1891 | goto out; |
2064 | 1892 | ||
2065 | inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; | 1893 | inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; |
2066 | inode->i_op = &proc_tgid_base_inode_operations; | 1894 | inode->i_op = &proc_tgid_base_inode_operations; |
2067 | inode->i_fop = &proc_tgid_base_operations; | 1895 | inode->i_fop = &proc_tgid_base_operations; |
2068 | inode->i_flags|=S_IMMUTABLE; | 1896 | inode->i_flags|=S_IMMUTABLE; |
2069 | #ifdef CONFIG_SECURITY | ||
2070 | inode->i_nlink = 5; | ||
2071 | #else | ||
2072 | inode->i_nlink = 4; | 1897 | inode->i_nlink = 4; |
1898 | #ifdef CONFIG_SECURITY | ||
1899 | inode->i_nlink += 1; | ||
2073 | #endif | 1900 | #endif |
2074 | 1901 | ||
2075 | dentry->d_op = &pid_dentry_operations; | 1902 | dentry->d_op = &pid_dentry_operations; |
@@ -2077,179 +1904,251 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2077 | d_add(dentry, inode); | 1904 | d_add(dentry, inode); |
2078 | /* Close the race of the process dying before we return the dentry */ | 1905 | /* Close the race of the process dying before we return the dentry */ |
2079 | if (pid_revalidate(dentry, NULL)) | 1906 | if (pid_revalidate(dentry, NULL)) |
2080 | result = NULL; | 1907 | error = NULL; |
2081 | |||
2082 | out_put_task: | ||
2083 | put_task_struct(task); | ||
2084 | out: | 1908 | out: |
2085 | return result; | 1909 | return error; |
2086 | } | 1910 | } |
2087 | 1911 | ||
2088 | /* SMP-safe */ | 1912 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
2089 | static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | ||
2090 | { | 1913 | { |
2091 | struct dentry *result = ERR_PTR(-ENOENT); | 1914 | struct dentry *result = ERR_PTR(-ENOENT); |
2092 | struct task_struct *task; | 1915 | struct task_struct *task; |
2093 | struct task_struct *leader = get_proc_task(dir); | 1916 | unsigned tgid; |
2094 | struct inode *inode; | ||
2095 | unsigned tid; | ||
2096 | 1917 | ||
2097 | if (!leader) | 1918 | result = proc_base_lookup(dir, dentry); |
2098 | goto out_no_task; | 1919 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) |
1920 | goto out; | ||
2099 | 1921 | ||
2100 | tid = name_to_int(dentry); | 1922 | tgid = name_to_int(dentry); |
2101 | if (tid == ~0U) | 1923 | if (tgid == ~0U) |
2102 | goto out; | 1924 | goto out; |
2103 | 1925 | ||
2104 | rcu_read_lock(); | 1926 | rcu_read_lock(); |
2105 | task = find_task_by_pid(tid); | 1927 | task = find_task_by_pid(tgid); |
2106 | if (task) | 1928 | if (task) |
2107 | get_task_struct(task); | 1929 | get_task_struct(task); |
2108 | rcu_read_unlock(); | 1930 | rcu_read_unlock(); |
2109 | if (!task) | 1931 | if (!task) |
2110 | goto out; | 1932 | goto out; |
2111 | if (leader->tgid != task->tgid) | ||
2112 | goto out_drop_task; | ||
2113 | |||
2114 | inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO); | ||
2115 | |||
2116 | |||
2117 | if (!inode) | ||
2118 | goto out_drop_task; | ||
2119 | inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; | ||
2120 | inode->i_op = &proc_tid_base_inode_operations; | ||
2121 | inode->i_fop = &proc_tid_base_operations; | ||
2122 | inode->i_flags|=S_IMMUTABLE; | ||
2123 | #ifdef CONFIG_SECURITY | ||
2124 | inode->i_nlink = 4; | ||
2125 | #else | ||
2126 | inode->i_nlink = 3; | ||
2127 | #endif | ||
2128 | |||
2129 | dentry->d_op = &pid_dentry_operations; | ||
2130 | |||
2131 | d_add(dentry, inode); | ||
2132 | /* Close the race of the process dying before we return the dentry */ | ||
2133 | if (pid_revalidate(dentry, NULL)) | ||
2134 | result = NULL; | ||
2135 | 1933 | ||
2136 | out_drop_task: | 1934 | result = proc_pid_instantiate(dir, dentry, task, NULL); |
2137 | put_task_struct(task); | 1935 | put_task_struct(task); |
2138 | out: | 1936 | out: |
2139 | put_task_struct(leader); | ||
2140 | out_no_task: | ||
2141 | return result; | 1937 | return result; |
2142 | } | 1938 | } |
2143 | 1939 | ||
2144 | /* | 1940 | /* |
2145 | * Find the first tgid to return to user space. | 1941 | * Find the first task with tgid >= tgid |
2146 | * | ||
2147 | * Usually this is just whatever follows &init_task, but if the users | ||
2148 | * buffer was too small to hold the full list or there was a seek into | ||
2149 | * the middle of the directory we have more work to do. | ||
2150 | * | ||
2151 | * In the case of a short read we start with find_task_by_pid. | ||
2152 | * | 1942 | * |
2153 | * In the case of a seek we start with &init_task and walk nr | ||
2154 | * threads past it. | ||
2155 | */ | 1943 | */ |
2156 | static struct task_struct *first_tgid(int tgid, unsigned int nr) | 1944 | static struct task_struct *next_tgid(unsigned int tgid) |
2157 | { | 1945 | { |
2158 | struct task_struct *pos; | 1946 | struct task_struct *task; |
2159 | rcu_read_lock(); | 1947 | struct pid *pid; |
2160 | if (tgid && nr) { | ||
2161 | pos = find_task_by_pid(tgid); | ||
2162 | if (pos && thread_group_leader(pos)) | ||
2163 | goto found; | ||
2164 | } | ||
2165 | /* If nr exceeds the number of processes get out quickly */ | ||
2166 | pos = NULL; | ||
2167 | if (nr && nr >= nr_processes()) | ||
2168 | goto done; | ||
2169 | 1948 | ||
2170 | /* If we haven't found our starting place yet start with | 1949 | rcu_read_lock(); |
2171 | * the init_task and walk nr tasks forward. | 1950 | retry: |
2172 | */ | 1951 | task = NULL; |
2173 | for (pos = next_task(&init_task); nr > 0; --nr) { | 1952 | pid = find_ge_pid(tgid); |
2174 | pos = next_task(pos); | 1953 | if (pid) { |
2175 | if (pos == &init_task) { | 1954 | tgid = pid->nr + 1; |
2176 | pos = NULL; | 1955 | task = pid_task(pid, PIDTYPE_PID); |
2177 | goto done; | 1956 | /* What we to know is if the pid we have find is the |
2178 | } | 1957 | * pid of a thread_group_leader. Testing for task |
1958 | * being a thread_group_leader is the obvious thing | ||
1959 | * todo but there is a window when it fails, due to | ||
1960 | * the pid transfer logic in de_thread. | ||
1961 | * | ||
1962 | * So we perform the straight forward test of seeing | ||
1963 | * if the pid we have found is the pid of a thread | ||
1964 | * group leader, and don't worry if the task we have | ||
1965 | * found doesn't happen to be a thread group leader. | ||
1966 | * As we don't care in the case of readdir. | ||
1967 | */ | ||
1968 | if (!task || !has_group_leader_pid(task)) | ||
1969 | goto retry; | ||
1970 | get_task_struct(task); | ||
2179 | } | 1971 | } |
2180 | found: | ||
2181 | get_task_struct(pos); | ||
2182 | done: | ||
2183 | rcu_read_unlock(); | 1972 | rcu_read_unlock(); |
2184 | return pos; | 1973 | return task; |
2185 | } | 1974 | } |
2186 | 1975 | ||
2187 | /* | 1976 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) |
2188 | * Find the next task in the task list. | 1977 | |
2189 | * Return NULL if we loop or there is any error. | 1978 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2190 | * | 1979 | struct task_struct *task, int tgid) |
2191 | * The reference to the input task_struct is released. | ||
2192 | */ | ||
2193 | static struct task_struct *next_tgid(struct task_struct *start) | ||
2194 | { | 1980 | { |
2195 | struct task_struct *pos; | 1981 | char name[PROC_NUMBUF]; |
2196 | rcu_read_lock(); | 1982 | int len = snprintf(name, sizeof(name), "%d", tgid); |
2197 | pos = start; | 1983 | return proc_fill_cache(filp, dirent, filldir, name, len, |
2198 | if (pid_alive(start)) | 1984 | proc_pid_instantiate, task, NULL); |
2199 | pos = next_task(start); | ||
2200 | if (pid_alive(pos) && (pos != &init_task)) { | ||
2201 | get_task_struct(pos); | ||
2202 | goto done; | ||
2203 | } | ||
2204 | pos = NULL; | ||
2205 | done: | ||
2206 | rcu_read_unlock(); | ||
2207 | put_task_struct(start); | ||
2208 | return pos; | ||
2209 | } | 1985 | } |
2210 | 1986 | ||
2211 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 1987 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2212 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1988 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2213 | { | 1989 | { |
2214 | char buf[PROC_NUMBUF]; | ||
2215 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 1990 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
1991 | struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode); | ||
2216 | struct task_struct *task; | 1992 | struct task_struct *task; |
2217 | int tgid; | 1993 | int tgid; |
2218 | 1994 | ||
2219 | if (!nr) { | 1995 | if (!reaper) |
2220 | ino_t ino = fake_ino(0,PROC_TGID_INO); | 1996 | goto out_no_task; |
2221 | if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0) | 1997 | |
2222 | return 0; | 1998 | for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) { |
2223 | filp->f_pos++; | 1999 | struct pid_entry *p = &proc_base_stuff[nr]; |
2224 | nr++; | 2000 | if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0) |
2001 | goto out; | ||
2225 | } | 2002 | } |
2226 | nr -= 1; | ||
2227 | 2003 | ||
2228 | /* f_version caches the tgid value that the last readdir call couldn't | 2004 | tgid = filp->f_pos - TGID_OFFSET; |
2229 | * return. lseek aka telldir automagically resets f_version to 0. | 2005 | for (task = next_tgid(tgid); |
2230 | */ | ||
2231 | tgid = filp->f_version; | ||
2232 | filp->f_version = 0; | ||
2233 | for (task = first_tgid(tgid, nr); | ||
2234 | task; | 2006 | task; |
2235 | task = next_tgid(task), filp->f_pos++) { | 2007 | put_task_struct(task), task = next_tgid(tgid + 1)) { |
2236 | int len; | ||
2237 | ino_t ino; | ||
2238 | tgid = task->pid; | 2008 | tgid = task->pid; |
2239 | len = snprintf(buf, sizeof(buf), "%d", tgid); | 2009 | filp->f_pos = tgid + TGID_OFFSET; |
2240 | ino = fake_ino(tgid, PROC_TGID_INO); | 2010 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2241 | if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) { | ||
2242 | /* returning this tgid failed, save it as the first | ||
2243 | * pid for the next readir call */ | ||
2244 | filp->f_version = tgid; | ||
2245 | put_task_struct(task); | 2011 | put_task_struct(task); |
2246 | break; | 2012 | goto out; |
2247 | } | 2013 | } |
2248 | } | 2014 | } |
2015 | filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET; | ||
2016 | out: | ||
2017 | put_task_struct(reaper); | ||
2018 | out_no_task: | ||
2249 | return 0; | 2019 | return 0; |
2250 | } | 2020 | } |
2251 | 2021 | ||
2252 | /* | 2022 | /* |
2023 | * Tasks | ||
2024 | */ | ||
2025 | static struct pid_entry tid_base_stuff[] = { | ||
2026 | DIR("fd", S_IRUSR|S_IXUSR, fd), | ||
2027 | INF("environ", S_IRUSR, pid_environ), | ||
2028 | INF("auxv", S_IRUSR, pid_auxv), | ||
2029 | INF("status", S_IRUGO, pid_status), | ||
2030 | INF("cmdline", S_IRUGO, pid_cmdline), | ||
2031 | INF("stat", S_IRUGO, tid_stat), | ||
2032 | INF("statm", S_IRUGO, pid_statm), | ||
2033 | REG("maps", S_IRUGO, maps), | ||
2034 | #ifdef CONFIG_NUMA | ||
2035 | REG("numa_maps", S_IRUGO, numa_maps), | ||
2036 | #endif | ||
2037 | REG("mem", S_IRUSR|S_IWUSR, mem), | ||
2038 | #ifdef CONFIG_SECCOMP | ||
2039 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), | ||
2040 | #endif | ||
2041 | LNK("cwd", cwd), | ||
2042 | LNK("root", root), | ||
2043 | LNK("exe", exe), | ||
2044 | REG("mounts", S_IRUGO, mounts), | ||
2045 | #ifdef CONFIG_MMU | ||
2046 | REG("smaps", S_IRUGO, smaps), | ||
2047 | #endif | ||
2048 | #ifdef CONFIG_SECURITY | ||
2049 | DIR("attr", S_IRUGO|S_IXUGO, attr_dir), | ||
2050 | #endif | ||
2051 | #ifdef CONFIG_KALLSYMS | ||
2052 | INF("wchan", S_IRUGO, pid_wchan), | ||
2053 | #endif | ||
2054 | #ifdef CONFIG_SCHEDSTATS | ||
2055 | INF("schedstat", S_IRUGO, pid_schedstat), | ||
2056 | #endif | ||
2057 | #ifdef CONFIG_CPUSETS | ||
2058 | REG("cpuset", S_IRUGO, cpuset), | ||
2059 | #endif | ||
2060 | INF("oom_score", S_IRUGO, oom_score), | ||
2061 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | ||
2062 | #ifdef CONFIG_AUDITSYSCALL | ||
2063 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), | ||
2064 | #endif | ||
2065 | }; | ||
2066 | |||
2067 | static int proc_tid_base_readdir(struct file * filp, | ||
2068 | void * dirent, filldir_t filldir) | ||
2069 | { | ||
2070 | return proc_pident_readdir(filp,dirent,filldir, | ||
2071 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); | ||
2072 | } | ||
2073 | |||
2074 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | ||
2075 | return proc_pident_lookup(dir, dentry, | ||
2076 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); | ||
2077 | } | ||
2078 | |||
2079 | static struct file_operations proc_tid_base_operations = { | ||
2080 | .read = generic_read_dir, | ||
2081 | .readdir = proc_tid_base_readdir, | ||
2082 | }; | ||
2083 | |||
2084 | static struct inode_operations proc_tid_base_inode_operations = { | ||
2085 | .lookup = proc_tid_base_lookup, | ||
2086 | .getattr = pid_getattr, | ||
2087 | .setattr = proc_setattr, | ||
2088 | }; | ||
2089 | |||
2090 | static struct dentry *proc_task_instantiate(struct inode *dir, | ||
2091 | struct dentry *dentry, struct task_struct *task, void *ptr) | ||
2092 | { | ||
2093 | struct dentry *error = ERR_PTR(-ENOENT); | ||
2094 | struct inode *inode; | ||
2095 | inode = proc_pid_make_inode(dir->i_sb, task); | ||
2096 | |||
2097 | if (!inode) | ||
2098 | goto out; | ||
2099 | inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; | ||
2100 | inode->i_op = &proc_tid_base_inode_operations; | ||
2101 | inode->i_fop = &proc_tid_base_operations; | ||
2102 | inode->i_flags|=S_IMMUTABLE; | ||
2103 | inode->i_nlink = 3; | ||
2104 | #ifdef CONFIG_SECURITY | ||
2105 | inode->i_nlink += 1; | ||
2106 | #endif | ||
2107 | |||
2108 | dentry->d_op = &pid_dentry_operations; | ||
2109 | |||
2110 | d_add(dentry, inode); | ||
2111 | /* Close the race of the process dying before we return the dentry */ | ||
2112 | if (pid_revalidate(dentry, NULL)) | ||
2113 | error = NULL; | ||
2114 | out: | ||
2115 | return error; | ||
2116 | } | ||
2117 | |||
2118 | static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | ||
2119 | { | ||
2120 | struct dentry *result = ERR_PTR(-ENOENT); | ||
2121 | struct task_struct *task; | ||
2122 | struct task_struct *leader = get_proc_task(dir); | ||
2123 | unsigned tid; | ||
2124 | |||
2125 | if (!leader) | ||
2126 | goto out_no_task; | ||
2127 | |||
2128 | tid = name_to_int(dentry); | ||
2129 | if (tid == ~0U) | ||
2130 | goto out; | ||
2131 | |||
2132 | rcu_read_lock(); | ||
2133 | task = find_task_by_pid(tid); | ||
2134 | if (task) | ||
2135 | get_task_struct(task); | ||
2136 | rcu_read_unlock(); | ||
2137 | if (!task) | ||
2138 | goto out; | ||
2139 | if (leader->tgid != task->tgid) | ||
2140 | goto out_drop_task; | ||
2141 | |||
2142 | result = proc_task_instantiate(dir, dentry, task, NULL); | ||
2143 | out_drop_task: | ||
2144 | put_task_struct(task); | ||
2145 | out: | ||
2146 | put_task_struct(leader); | ||
2147 | out_no_task: | ||
2148 | return result; | ||
2149 | } | ||
2150 | |||
2151 | /* | ||
2253 | * Find the first tid of a thread group to return to user space. | 2152 | * Find the first tid of a thread group to return to user space. |
2254 | * | 2153 | * |
2255 | * Usually this is just the thread group leader, but if the users | 2154 | * Usually this is just the thread group leader, but if the users |
@@ -2318,10 +2217,18 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
2318 | return pos; | 2217 | return pos; |
2319 | } | 2218 | } |
2320 | 2219 | ||
2220 | static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||
2221 | struct task_struct *task, int tid) | ||
2222 | { | ||
2223 | char name[PROC_NUMBUF]; | ||
2224 | int len = snprintf(name, sizeof(name), "%d", tid); | ||
2225 | return proc_fill_cache(filp, dirent, filldir, name, len, | ||
2226 | proc_task_instantiate, task, NULL); | ||
2227 | } | ||
2228 | |||
2321 | /* for the /proc/TGID/task/ directories */ | 2229 | /* for the /proc/TGID/task/ directories */ |
2322 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) | 2230 | static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2323 | { | 2231 | { |
2324 | char buf[PROC_NUMBUF]; | ||
2325 | struct dentry *dentry = filp->f_dentry; | 2232 | struct dentry *dentry = filp->f_dentry; |
2326 | struct inode *inode = dentry->d_inode; | 2233 | struct inode *inode = dentry->d_inode; |
2327 | struct task_struct *leader = get_proc_task(inode); | 2234 | struct task_struct *leader = get_proc_task(inode); |
@@ -2358,11 +2265,8 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2358 | for (task = first_tid(leader, tid, pos - 2); | 2265 | for (task = first_tid(leader, tid, pos - 2); |
2359 | task; | 2266 | task; |
2360 | task = next_tid(task), pos++) { | 2267 | task = next_tid(task), pos++) { |
2361 | int len; | ||
2362 | tid = task->pid; | 2268 | tid = task->pid; |
2363 | len = snprintf(buf, sizeof(buf), "%d", tid); | 2269 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2364 | ino = fake_ino(tid, PROC_TID_INO); | ||
2365 | if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) { | ||
2366 | /* returning this tgid failed, save it as the first | 2270 | /* returning this tgid failed, save it as the first |
2367 | * pid for the next readir call */ | 2271 | * pid for the next readir call */ |
2368 | filp->f_version = tid; | 2272 | filp->f_version = tid; |
@@ -2392,3 +2296,14 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct | |||
2392 | 2296 | ||
2393 | return 0; | 2297 | return 0; |
2394 | } | 2298 | } |
2299 | |||
2300 | static struct inode_operations proc_task_inode_operations = { | ||
2301 | .lookup = proc_task_lookup, | ||
2302 | .getattr = proc_task_getattr, | ||
2303 | .setattr = proc_setattr, | ||
2304 | }; | ||
2305 | |||
2306 | static struct file_operations proc_task_operations = { | ||
2307 | .read = generic_read_dir, | ||
2308 | .readdir = proc_task_readdir, | ||
2309 | }; | ||
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 66bc425f2f3d..8d88e58ed5cc 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/sysrq.h> | 45 | #include <linux/sysrq.h> |
46 | #include <linux/vmalloc.h> | 46 | #include <linux/vmalloc.h> |
47 | #include <linux/crash_dump.h> | 47 | #include <linux/crash_dump.h> |
48 | #include <linux/pspace.h> | ||
48 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
49 | #include <asm/pgtable.h> | 50 | #include <asm/pgtable.h> |
50 | #include <asm/io.h> | 51 | #include <asm/io.h> |
@@ -91,7 +92,7 @@ static int loadavg_read_proc(char *page, char **start, off_t off, | |||
91 | LOAD_INT(a), LOAD_FRAC(a), | 92 | LOAD_INT(a), LOAD_FRAC(a), |
92 | LOAD_INT(b), LOAD_FRAC(b), | 93 | LOAD_INT(b), LOAD_FRAC(b), |
93 | LOAD_INT(c), LOAD_FRAC(c), | 94 | LOAD_INT(c), LOAD_FRAC(c), |
94 | nr_running(), nr_threads, last_pid); | 95 | nr_running(), nr_threads, init_pspace.last_pid); |
95 | return proc_calc_metrics(page, start, off, count, eof, len); | 96 | return proc_calc_metrics(page, start, off, count, eof, len); |
96 | } | 97 | } |
97 | 98 | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index 8901c65caca8..ffe66c38488b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
18 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
19 | #include <linux/mount.h> | ||
19 | 20 | ||
20 | #include "internal.h" | 21 | #include "internal.h" |
21 | 22 | ||
@@ -28,6 +29,17 @@ struct proc_dir_entry *proc_sys_root; | |||
28 | static int proc_get_sb(struct file_system_type *fs_type, | 29 | static int proc_get_sb(struct file_system_type *fs_type, |
29 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 30 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
30 | { | 31 | { |
32 | if (proc_mnt) { | ||
33 | /* Seed the root directory with a pid so it doesn't need | ||
34 | * to be special in base.c. I would do this earlier but | ||
35 | * the only task alive when /proc is mounted the first time | ||
36 | * is the init_task and it doesn't have any pids. | ||
37 | */ | ||
38 | struct proc_inode *ei; | ||
39 | ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); | ||
40 | if (!ei->pid) | ||
41 | ei->pid = find_get_pid(1); | ||
42 | } | ||
31 | return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); | 43 | return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); |
32 | } | 44 | } |
33 | 45 | ||