aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-31 07:53:43 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-31 07:53:43 -0400
commit7bee946358c3cb957d4aa648fc5ab3cad0b232d0 (patch)
tree693061ebde2abc35ecc846e5084630d7225aaaff /fs/proc
parentd820ac4c2fa881079e6b689d2098adce337558ae (diff)
parent15f7176eb1cccec0a332541285ee752b935c1c85 (diff)
Merge branch 'linus' into locking-for-linus
Conflicts: lib/Kconfig.debug
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c72
-rw-r--r--fs/proc/generic.c65
-rw-r--r--fs/proc/inode-alloc.txt14
-rw-r--r--fs/proc/inode.c21
-rw-r--r--fs/proc/internal.h1
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/proc/proc_tty.c1
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/proc/task_mmu.c8
-rw-r--r--fs/proc/uptime.c38
10 files changed, 111 insertions, 116 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 0c9de19a1633..e0afd326b688 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -146,15 +146,22 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
146 return count; 146 return count;
147} 147}
148 148
149static struct fs_struct *get_fs_struct(struct task_struct *task) 149static int get_fs_path(struct task_struct *task, struct path *path, bool root)
150{ 150{
151 struct fs_struct *fs; 151 struct fs_struct *fs;
152 int result = -ENOENT;
153
152 task_lock(task); 154 task_lock(task);
153 fs = task->fs; 155 fs = task->fs;
154 if(fs) 156 if (fs) {
155 atomic_inc(&fs->count); 157 read_lock(&fs->lock);
158 *path = root ? fs->root : fs->pwd;
159 path_get(path);
160 read_unlock(&fs->lock);
161 result = 0;
162 }
156 task_unlock(task); 163 task_unlock(task);
157 return fs; 164 return result;
158} 165}
159 166
160static int get_nr_threads(struct task_struct *tsk) 167static int get_nr_threads(struct task_struct *tsk)
@@ -172,42 +179,24 @@ static int get_nr_threads(struct task_struct *tsk)
172static int proc_cwd_link(struct inode *inode, struct path *path) 179static int proc_cwd_link(struct inode *inode, struct path *path)
173{ 180{
174 struct task_struct *task = get_proc_task(inode); 181 struct task_struct *task = get_proc_task(inode);
175 struct fs_struct *fs = NULL;
176 int result = -ENOENT; 182 int result = -ENOENT;
177 183
178 if (task) { 184 if (task) {
179 fs = get_fs_struct(task); 185 result = get_fs_path(task, path, 0);
180 put_task_struct(task); 186 put_task_struct(task);
181 } 187 }
182 if (fs) {
183 read_lock(&fs->lock);
184 *path = fs->pwd;
185 path_get(&fs->pwd);
186 read_unlock(&fs->lock);
187 result = 0;
188 put_fs_struct(fs);
189 }
190 return result; 188 return result;
191} 189}
192 190
193static int proc_root_link(struct inode *inode, struct path *path) 191static int proc_root_link(struct inode *inode, struct path *path)
194{ 192{
195 struct task_struct *task = get_proc_task(inode); 193 struct task_struct *task = get_proc_task(inode);
196 struct fs_struct *fs = NULL;
197 int result = -ENOENT; 194 int result = -ENOENT;
198 195
199 if (task) { 196 if (task) {
200 fs = get_fs_struct(task); 197 result = get_fs_path(task, path, 1);
201 put_task_struct(task); 198 put_task_struct(task);
202 } 199 }
203 if (fs) {
204 read_lock(&fs->lock);
205 *path = fs->root;
206 path_get(&fs->root);
207 read_unlock(&fs->lock);
208 result = 0;
209 put_fs_struct(fs);
210 }
211 return result; 200 return result;
212} 201}
213 202
@@ -596,7 +585,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
596 struct task_struct *task = get_proc_task(inode); 585 struct task_struct *task = get_proc_task(inode);
597 struct nsproxy *nsp; 586 struct nsproxy *nsp;
598 struct mnt_namespace *ns = NULL; 587 struct mnt_namespace *ns = NULL;
599 struct fs_struct *fs = NULL;
600 struct path root; 588 struct path root;
601 struct proc_mounts *p; 589 struct proc_mounts *p;
602 int ret = -EINVAL; 590 int ret = -EINVAL;
@@ -610,22 +598,16 @@ static int mounts_open_common(struct inode *inode, struct file *file,
610 get_mnt_ns(ns); 598 get_mnt_ns(ns);
611 } 599 }
612 rcu_read_unlock(); 600 rcu_read_unlock();
613 if (ns) 601 if (ns && get_fs_path(task, &root, 1) == 0)
614 fs = get_fs_struct(task); 602 ret = 0;
615 put_task_struct(task); 603 put_task_struct(task);
616 } 604 }
617 605
618 if (!ns) 606 if (!ns)
619 goto err; 607 goto err;
620 if (!fs) 608 if (ret)
621 goto err_put_ns; 609 goto err_put_ns;
622 610
623 read_lock(&fs->lock);
624 root = fs->root;
625 path_get(&root);
626 read_unlock(&fs->lock);
627 put_fs_struct(fs);
628
629 ret = -ENOMEM; 611 ret = -ENOMEM;
630 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); 612 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
631 if (!p) 613 if (!p)
@@ -1545,7 +1527,7 @@ static int pid_delete_dentry(struct dentry * dentry)
1545 return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; 1527 return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
1546} 1528}
1547 1529
1548static struct dentry_operations pid_dentry_operations = 1530static const struct dentry_operations pid_dentry_operations =
1549{ 1531{
1550 .d_revalidate = pid_revalidate, 1532 .d_revalidate = pid_revalidate,
1551 .d_delete = pid_delete_dentry, 1533 .d_delete = pid_delete_dentry,
@@ -1717,7 +1699,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1717 return 0; 1699 return 0;
1718} 1700}
1719 1701
1720static struct dentry_operations tid_fd_dentry_operations = 1702static const struct dentry_operations tid_fd_dentry_operations =
1721{ 1703{
1722 .d_revalidate = tid_fd_revalidate, 1704 .d_revalidate = tid_fd_revalidate,
1723 .d_delete = pid_delete_dentry, 1705 .d_delete = pid_delete_dentry,
@@ -2339,7 +2321,7 @@ static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
2339 return 0; 2321 return 0;
2340} 2322}
2341 2323
2342static struct dentry_operations proc_base_dentry_operations = 2324static const struct dentry_operations proc_base_dentry_operations =
2343{ 2325{
2344 .d_revalidate = proc_base_revalidate, 2326 .d_revalidate = proc_base_revalidate,
2345 .d_delete = pid_delete_dentry, 2327 .d_delete = pid_delete_dentry,
@@ -3066,7 +3048,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3066 int retval = -ENOENT; 3048 int retval = -ENOENT;
3067 ino_t ino; 3049 ino_t ino;
3068 int tid; 3050 int tid;
3069 unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */
3070 struct pid_namespace *ns; 3051 struct pid_namespace *ns;
3071 3052
3072 task = get_proc_task(inode); 3053 task = get_proc_task(inode);
@@ -3083,18 +3064,18 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3083 goto out_no_task; 3064 goto out_no_task;
3084 retval = 0; 3065 retval = 0;
3085 3066
3086 switch (pos) { 3067 switch ((unsigned long)filp->f_pos) {
3087 case 0: 3068 case 0:
3088 ino = inode->i_ino; 3069 ino = inode->i_ino;
3089 if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0) 3070 if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
3090 goto out; 3071 goto out;
3091 pos++; 3072 filp->f_pos++;
3092 /* fall through */ 3073 /* fall through */
3093 case 1: 3074 case 1:
3094 ino = parent_ino(dentry); 3075 ino = parent_ino(dentry);
3095 if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0) 3076 if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0)
3096 goto out; 3077 goto out;
3097 pos++; 3078 filp->f_pos++;
3098 /* fall through */ 3079 /* fall through */
3099 } 3080 }
3100 3081
@@ -3104,9 +3085,9 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3104 ns = filp->f_dentry->d_sb->s_fs_info; 3085 ns = filp->f_dentry->d_sb->s_fs_info;
3105 tid = (int)filp->f_version; 3086 tid = (int)filp->f_version;
3106 filp->f_version = 0; 3087 filp->f_version = 0;
3107 for (task = first_tid(leader, tid, pos - 2, ns); 3088 for (task = first_tid(leader, tid, filp->f_pos - 2, ns);
3108 task; 3089 task;
3109 task = next_tid(task), pos++) { 3090 task = next_tid(task), filp->f_pos++) {
3110 tid = task_pid_nr_ns(task, ns); 3091 tid = task_pid_nr_ns(task, ns);
3111 if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { 3092 if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
3112 /* returning this tgid failed, save it as the first 3093 /* returning this tgid failed, save it as the first
@@ -3117,7 +3098,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
3117 } 3098 }
3118 } 3099 }
3119out: 3100out:
3120 filp->f_pos = pos;
3121 put_task_struct(leader); 3101 put_task_struct(leader);
3122out_no_task: 3102out_no_task:
3123 return retval; 3103 return retval;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index db7fa5cab988..fa678abc9db1 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -37,7 +37,7 @@ static int proc_match(int len, const char *name, struct proc_dir_entry *de)
37#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024) 37#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
38 38
39static ssize_t 39static ssize_t
40proc_file_read(struct file *file, char __user *buf, size_t nbytes, 40__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
41 loff_t *ppos) 41 loff_t *ppos)
42{ 42{
43 struct inode * inode = file->f_path.dentry->d_inode; 43 struct inode * inode = file->f_path.dentry->d_inode;
@@ -183,19 +183,47 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
183} 183}
184 184
185static ssize_t 185static ssize_t
186proc_file_read(struct file *file, char __user *buf, size_t nbytes,
187 loff_t *ppos)
188{
189 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
190 ssize_t rv = -EIO;
191
192 spin_lock(&pde->pde_unload_lock);
193 if (!pde->proc_fops) {
194 spin_unlock(&pde->pde_unload_lock);
195 return rv;
196 }
197 pde->pde_users++;
198 spin_unlock(&pde->pde_unload_lock);
199
200 rv = __proc_file_read(file, buf, nbytes, ppos);
201
202 pde_users_dec(pde);
203 return rv;
204}
205
206static ssize_t
186proc_file_write(struct file *file, const char __user *buffer, 207proc_file_write(struct file *file, const char __user *buffer,
187 size_t count, loff_t *ppos) 208 size_t count, loff_t *ppos)
188{ 209{
189 struct inode *inode = file->f_path.dentry->d_inode; 210 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
190 struct proc_dir_entry * dp; 211 ssize_t rv = -EIO;
191 212
192 dp = PDE(inode); 213 if (pde->write_proc) {
193 214 spin_lock(&pde->pde_unload_lock);
194 if (!dp->write_proc) 215 if (!pde->proc_fops) {
195 return -EIO; 216 spin_unlock(&pde->pde_unload_lock);
217 return rv;
218 }
219 pde->pde_users++;
220 spin_unlock(&pde->pde_unload_lock);
196 221
197 /* FIXME: does this routine need ppos? probably... */ 222 /* FIXME: does this routine need ppos? probably... */
198 return dp->write_proc(file, buffer, count, dp->data); 223 rv = pde->write_proc(file, buffer, count, pde->data);
224 pde_users_dec(pde);
225 }
226 return rv;
199} 227}
200 228
201 229
@@ -307,6 +335,21 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
307/* 335/*
308 * Return an inode number between PROC_DYNAMIC_FIRST and 336 * Return an inode number between PROC_DYNAMIC_FIRST and
309 * 0xffffffff, or zero on failure. 337 * 0xffffffff, or zero on failure.
338 *
339 * Current inode allocations in the proc-fs (hex-numbers):
340 *
341 * 00000000 reserved
342 * 00000001-00000fff static entries (goners)
343 * 001 root-ino
344 *
345 * 00001000-00001fff unused
346 * 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff
347 * 80000000-efffffff unused
348 * f0000000-ffffffff dynamic entries
349 *
350 * Goal:
351 * Once we split the thing into several virtual filesystems,
352 * we will get rid of magical ranges (and this comment, BTW).
310 */ 353 */
311static unsigned int get_inode_number(void) 354static unsigned int get_inode_number(void)
312{ 355{
@@ -363,7 +406,7 @@ static int proc_delete_dentry(struct dentry * dentry)
363 return 1; 406 return 1;
364} 407}
365 408
366static struct dentry_operations proc_dentry_operations = 409static const struct dentry_operations proc_dentry_operations =
367{ 410{
368 .d_delete = proc_delete_dentry, 411 .d_delete = proc_delete_dentry,
369}; 412};
diff --git a/fs/proc/inode-alloc.txt b/fs/proc/inode-alloc.txt
deleted file mode 100644
index 77212f938c2c..000000000000
--- a/fs/proc/inode-alloc.txt
+++ /dev/null
@@ -1,14 +0,0 @@
1Current inode allocations in the proc-fs (hex-numbers):
2
3 00000000 reserved
4 00000001-00000fff static entries (goners)
5 001 root-ino
6
7 00001000-00001fff unused
8 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff
9 80000000-efffffff unused
10 f0000000-ffffffff dynamic entries
11
12Goal:
13 a) once we'll split the thing into several virtual filesystems we
14 will get rid of magical ranges (and this file, BTW).
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d8bb5c671f42..d78ade305541 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -58,11 +58,8 @@ static void proc_delete_inode(struct inode *inode)
58 58
59 /* Let go of any associated proc directory entry */ 59 /* Let go of any associated proc directory entry */
60 de = PROC_I(inode)->pde; 60 de = PROC_I(inode)->pde;
61 if (de) { 61 if (de)
62 if (de->owner)
63 module_put(de->owner);
64 de_put(de); 62 de_put(de);
65 }
66 if (PROC_I(inode)->sysctl) 63 if (PROC_I(inode)->sysctl)
67 sysctl_head_put(PROC_I(inode)->sysctl); 64 sysctl_head_put(PROC_I(inode)->sysctl);
68 clear_inode(inode); 65 clear_inode(inode);
@@ -127,7 +124,7 @@ static void __pde_users_dec(struct proc_dir_entry *pde)
127 complete(pde->pde_unload_completion); 124 complete(pde->pde_unload_completion);
128} 125}
129 126
130static void pde_users_dec(struct proc_dir_entry *pde) 127void pde_users_dec(struct proc_dir_entry *pde)
131{ 128{
132 spin_lock(&pde->pde_unload_lock); 129 spin_lock(&pde->pde_unload_lock);
133 __pde_users_dec(pde); 130 __pde_users_dec(pde);
@@ -449,12 +446,9 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
449{ 446{
450 struct inode * inode; 447 struct inode * inode;
451 448
452 if (!try_module_get(de->owner))
453 goto out_mod;
454
455 inode = iget_locked(sb, ino); 449 inode = iget_locked(sb, ino);
456 if (!inode) 450 if (!inode)
457 goto out_ino; 451 return NULL;
458 if (inode->i_state & I_NEW) { 452 if (inode->i_state & I_NEW) {
459 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 453 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
460 PROC_I(inode)->fd = 0; 454 PROC_I(inode)->fd = 0;
@@ -485,16 +479,9 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
485 } 479 }
486 } 480 }
487 unlock_new_inode(inode); 481 unlock_new_inode(inode);
488 } else { 482 } else
489 module_put(de->owner);
490 de_put(de); 483 de_put(de);
491 }
492 return inode; 484 return inode;
493
494out_ino:
495 module_put(de->owner);
496out_mod:
497 return NULL;
498} 485}
499 486
500int proc_fill_super(struct super_block *s) 487int proc_fill_super(struct super_block *s)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index cd53ff838498..f6db9618a888 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -91,3 +91,4 @@ struct pde_opener {
91 int (*release)(struct inode *, struct file *); 91 int (*release)(struct inode *, struct file *);
92 struct list_head lh; 92 struct list_head lh;
93}; 93};
94void pde_users_dec(struct proc_dir_entry *pde);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 94fcfff6863a..9b1e4e9a16bf 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -7,7 +7,7 @@
7#include <linux/security.h> 7#include <linux/security.h>
8#include "internal.h" 8#include "internal.h"
9 9
10static struct dentry_operations proc_sys_dentry_operations; 10static const struct dentry_operations proc_sys_dentry_operations;
11static const struct file_operations proc_sys_file_operations; 11static const struct file_operations proc_sys_file_operations;
12static const struct inode_operations proc_sys_inode_operations; 12static const struct inode_operations proc_sys_inode_operations;
13static const struct file_operations proc_sys_dir_file_operations; 13static const struct file_operations proc_sys_dir_file_operations;
@@ -396,7 +396,7 @@ static int proc_sys_compare(struct dentry *dir, struct qstr *qstr,
396 return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl); 396 return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl);
397} 397}
398 398
399static struct dentry_operations proc_sys_dentry_operations = { 399static const struct dentry_operations proc_sys_dentry_operations = {
400 .d_revalidate = proc_sys_revalidate, 400 .d_revalidate = proc_sys_revalidate,
401 .d_delete = proc_sys_delete, 401 .d_delete = proc_sys_delete,
402 .d_compare = proc_sys_compare, 402 .d_compare = proc_sys_compare,
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index d153946d6d15..4a9e0f65ae60 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -152,7 +152,6 @@ void proc_tty_register_driver(struct tty_driver *driver)
152 if (!ent) 152 if (!ent)
153 return; 153 return;
154 ent->read_proc = driver->ops->read_proc; 154 ent->read_proc = driver->ops->read_proc;
155 ent->owner = driver->owner;
156 ent->data = driver; 155 ent->data = driver;
157 156
158 driver->proc_entry = ent; 157 driver->proc_entry = ent;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index f6299a25594e..1e15a2b176e8 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -83,7 +83,8 @@ static int proc_get_sb(struct file_system_type *fs_type,
83 ns->proc_mnt = mnt; 83 ns->proc_mnt = mnt;
84 } 84 }
85 85
86 return simple_set_mnt(mnt, sb); 86 simple_set_mnt(mnt, sb);
87 return 0;
87} 88}
88 89
89static void proc_kill_sb(struct super_block *sb) 90static void proc_kill_sb(struct super_block *sb)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 94063840832a..b0ae0be4801f 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -693,8 +693,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
693 goto out_pages; 693 goto out_pages;
694 } 694 }
695 695
696 pm.out = (u64 *)buf; 696 pm.out = (u64 __user *)buf;
697 pm.end = (u64 *)(buf + count); 697 pm.end = (u64 __user *)(buf + count);
698 698
699 pagemap_walk.pmd_entry = pagemap_pte_range; 699 pagemap_walk.pmd_entry = pagemap_pte_range;
700 pagemap_walk.pte_hole = pagemap_pte_hole; 700 pagemap_walk.pte_hole = pagemap_pte_hole;
@@ -720,9 +720,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
720 if (ret == PM_END_OF_BUFFER) 720 if (ret == PM_END_OF_BUFFER)
721 ret = 0; 721 ret = 0;
722 /* don't need mmap_sem for these, but this looks cleaner */ 722 /* don't need mmap_sem for these, but this looks cleaner */
723 *ppos += (char *)pm.out - buf; 723 *ppos += (char __user *)pm.out - buf;
724 if (!ret) 724 if (!ret)
725 ret = (char *)pm.out - buf; 725 ret = (char __user *)pm.out - buf;
726 726
727out_pages: 727out_pages:
728 for (; pagecount; pagecount--) { 728 for (; pagecount; pagecount--) {
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
index df26aa88fa47..0c10a0b3f146 100644
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -1,45 +1,43 @@
1#include <linux/fs.h>
1#include <linux/init.h> 2#include <linux/init.h>
2#include <linux/proc_fs.h> 3#include <linux/proc_fs.h>
3#include <linux/sched.h> 4#include <linux/sched.h>
5#include <linux/seq_file.h>
4#include <linux/time.h> 6#include <linux/time.h>
5#include <asm/cputime.h> 7#include <asm/cputime.h>
6 8
7static int proc_calc_metrics(char *page, char **start, off_t off, 9static int uptime_proc_show(struct seq_file *m, void *v)
8 int count, int *eof, int len)
9{
10 if (len <= off + count)
11 *eof = 1;
12 *start = page + off;
13 len -= off;
14 if (len > count)
15 len = count;
16 if (len < 0)
17 len = 0;
18 return len;
19}
20
21static int uptime_read_proc(char *page, char **start, off_t off, int count,
22 int *eof, void *data)
23{ 10{
24 struct timespec uptime; 11 struct timespec uptime;
25 struct timespec idle; 12 struct timespec idle;
26 int len;
27 cputime_t idletime = cputime_add(init_task.utime, init_task.stime); 13 cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
28 14
29 do_posix_clock_monotonic_gettime(&uptime); 15 do_posix_clock_monotonic_gettime(&uptime);
30 monotonic_to_bootbased(&uptime); 16 monotonic_to_bootbased(&uptime);
31 cputime_to_timespec(idletime, &idle); 17 cputime_to_timespec(idletime, &idle);
32 len = sprintf(page, "%lu.%02lu %lu.%02lu\n", 18 seq_printf(m, "%lu.%02lu %lu.%02lu\n",
33 (unsigned long) uptime.tv_sec, 19 (unsigned long) uptime.tv_sec,
34 (uptime.tv_nsec / (NSEC_PER_SEC / 100)), 20 (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
35 (unsigned long) idle.tv_sec, 21 (unsigned long) idle.tv_sec,
36 (idle.tv_nsec / (NSEC_PER_SEC / 100))); 22 (idle.tv_nsec / (NSEC_PER_SEC / 100)));
37 return proc_calc_metrics(page, start, off, count, eof, len); 23 return 0;
38} 24}
39 25
26static int uptime_proc_open(struct inode *inode, struct file *file)
27{
28 return single_open(file, uptime_proc_show, NULL);
29}
30
31static const struct file_operations uptime_proc_fops = {
32 .open = uptime_proc_open,
33 .read = seq_read,
34 .llseek = seq_lseek,
35 .release = single_release,
36};
37
40static int __init proc_uptime_init(void) 38static int __init proc_uptime_init(void)
41{ 39{
42 create_proc_read_entry("uptime", 0, NULL, uptime_read_proc, NULL); 40 proc_create("uptime", 0, NULL, &uptime_proc_fops);
43 return 0; 41 return 0;
44} 42}
45module_init(proc_uptime_init); 43module_init(proc_uptime_init);