aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-01 17:41:15 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2007-10-09 18:32:46 -0400
commit7f8ada98d9edd83d6ebd01e431e15b024a4a3dc4 (patch)
tree1231947efa06478714eeabac3bdbffc663f453c7
parent094f2825218fec1b240cb8537d2d0a10edf5ddc9 (diff)
Rework /proc/locks via seq_files and seq_list helpers
Currently /proc/locks is shown with a proc_read function, but its behavior is rather complex as it has to manually handle current offset and buffer length. On the other hand, files that show objects from lists can be easily reimplemented using the sequential files and the seq_list_XXX() helpers. This saves (as usually) 16 lines of code and more than 200 from the .text section. [akpm@linux-foundation.org: no externs in C] [akpm@linux-foundation.org: warning fixes] Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r--fs/locks.c122
-rw-r--r--fs/proc/proc_misc.c19
-rw-r--r--include/linux/fs.h1
3 files changed, 62 insertions, 80 deletions
diff --git a/fs/locks.c b/fs/locks.c
index c17bc00b1e8d..7f9a3ea47418 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2066,134 +2066,114 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
2066 2066
2067EXPORT_SYMBOL_GPL(vfs_cancel_lock); 2067EXPORT_SYMBOL_GPL(vfs_cancel_lock);
2068 2068
2069static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) 2069#ifdef CONFIG_PROC_FS
2070#include <linux/seq_file.h>
2071
2072static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2073 int id, char *pfx)
2070{ 2074{
2071 struct inode *inode = NULL; 2075 struct inode *inode = NULL;
2072 2076
2073 if (fl->fl_file != NULL) 2077 if (fl->fl_file != NULL)
2074 inode = fl->fl_file->f_path.dentry->d_inode; 2078 inode = fl->fl_file->f_path.dentry->d_inode;
2075 2079
2076 out += sprintf(out, "%d:%s ", id, pfx); 2080 seq_printf(f, "%d:%s ", id, pfx);
2077 if (IS_POSIX(fl)) { 2081 if (IS_POSIX(fl)) {
2078 out += sprintf(out, "%6s %s ", 2082 seq_printf(f, "%6s %s ",
2079 (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", 2083 (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
2080 (inode == NULL) ? "*NOINODE*" : 2084 (inode == NULL) ? "*NOINODE*" :
2081 mandatory_lock(inode) ? "MANDATORY" : "ADVISORY "); 2085 mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
2082 } else if (IS_FLOCK(fl)) { 2086 } else if (IS_FLOCK(fl)) {
2083 if (fl->fl_type & LOCK_MAND) { 2087 if (fl->fl_type & LOCK_MAND) {
2084 out += sprintf(out, "FLOCK MSNFS "); 2088 seq_printf(f, "FLOCK MSNFS ");
2085 } else { 2089 } else {
2086 out += sprintf(out, "FLOCK ADVISORY "); 2090 seq_printf(f, "FLOCK ADVISORY ");
2087 } 2091 }
2088 } else if (IS_LEASE(fl)) { 2092 } else if (IS_LEASE(fl)) {
2089 out += sprintf(out, "LEASE "); 2093 seq_printf(f, "LEASE ");
2090 if (fl->fl_type & F_INPROGRESS) 2094 if (fl->fl_type & F_INPROGRESS)
2091 out += sprintf(out, "BREAKING "); 2095 seq_printf(f, "BREAKING ");
2092 else if (fl->fl_file) 2096 else if (fl->fl_file)
2093 out += sprintf(out, "ACTIVE "); 2097 seq_printf(f, "ACTIVE ");
2094 else 2098 else
2095 out += sprintf(out, "BREAKER "); 2099 seq_printf(f, "BREAKER ");
2096 } else { 2100 } else {
2097 out += sprintf(out, "UNKNOWN UNKNOWN "); 2101 seq_printf(f, "UNKNOWN UNKNOWN ");
2098 } 2102 }
2099 if (fl->fl_type & LOCK_MAND) { 2103 if (fl->fl_type & LOCK_MAND) {
2100 out += sprintf(out, "%s ", 2104 seq_printf(f, "%s ",
2101 (fl->fl_type & LOCK_READ) 2105 (fl->fl_type & LOCK_READ)
2102 ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ " 2106 ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ "
2103 : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE "); 2107 : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
2104 } else { 2108 } else {
2105 out += sprintf(out, "%s ", 2109 seq_printf(f, "%s ",
2106 (fl->fl_type & F_INPROGRESS) 2110 (fl->fl_type & F_INPROGRESS)
2107 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " 2111 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
2108 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); 2112 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
2109 } 2113 }
2110 if (inode) { 2114 if (inode) {
2111#ifdef WE_CAN_BREAK_LSLK_NOW 2115#ifdef WE_CAN_BREAK_LSLK_NOW
2112 out += sprintf(out, "%d %s:%ld ", fl->fl_pid, 2116 seq_printf(f, "%d %s:%ld ", fl->fl_pid,
2113 inode->i_sb->s_id, inode->i_ino); 2117 inode->i_sb->s_id, inode->i_ino);
2114#else 2118#else
2115 /* userspace relies on this representation of dev_t ;-( */ 2119 /* userspace relies on this representation of dev_t ;-( */
2116 out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid, 2120 seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
2117 MAJOR(inode->i_sb->s_dev), 2121 MAJOR(inode->i_sb->s_dev),
2118 MINOR(inode->i_sb->s_dev), inode->i_ino); 2122 MINOR(inode->i_sb->s_dev), inode->i_ino);
2119#endif 2123#endif
2120 } else { 2124 } else {
2121 out += sprintf(out, "%d <none>:0 ", fl->fl_pid); 2125 seq_printf(f, "%d <none>:0 ", fl->fl_pid);
2122 } 2126 }
2123 if (IS_POSIX(fl)) { 2127 if (IS_POSIX(fl)) {
2124 if (fl->fl_end == OFFSET_MAX) 2128 if (fl->fl_end == OFFSET_MAX)
2125 out += sprintf(out, "%Ld EOF\n", fl->fl_start); 2129 seq_printf(f, "%Ld EOF\n", fl->fl_start);
2126 else 2130 else
2127 out += sprintf(out, "%Ld %Ld\n", fl->fl_start, 2131 seq_printf(f, "%Ld %Ld\n", fl->fl_start, fl->fl_end);
2128 fl->fl_end);
2129 } else { 2132 } else {
2130 out += sprintf(out, "0 EOF\n"); 2133 seq_printf(f, "0 EOF\n");
2131 } 2134 }
2132} 2135}
2133 2136
2134static void move_lock_status(char **p, off_t* pos, off_t offset) 2137static int locks_show(struct seq_file *f, void *v)
2135{ 2138{
2136 int len; 2139 struct file_lock *fl, *bfl;
2137 len = strlen(*p);
2138 if(*pos >= offset) {
2139 /* the complete line is valid */
2140 *p += len;
2141 *pos += len;
2142 return;
2143 }
2144 if(*pos+len > offset) {
2145 /* use the second part of the line */
2146 int i = offset-*pos;
2147 memmove(*p,*p+i,len-i);
2148 *p += len-i;
2149 *pos += len;
2150 return;
2151 }
2152 /* discard the complete line */
2153 *pos += len;
2154}
2155 2140
2156/** 2141 fl = list_entry(v, struct file_lock, fl_link);
2157 * get_locks_status - reports lock usage in /proc/locks
2158 * @buffer: address in userspace to write into
2159 * @start: ?
2160 * @offset: how far we are through the buffer
2161 * @length: how much to read
2162 */
2163 2142
2164int get_locks_status(char *buffer, char **start, off_t offset, int length) 2143 lock_get_status(f, fl, (long)f->private, "");
2165{
2166 struct file_lock *fl;
2167 char *q = buffer;
2168 off_t pos = 0;
2169 int i = 0;
2170 2144
2171 lock_kernel(); 2145 list_for_each_entry(bfl, &fl->fl_block, fl_block)
2172 list_for_each_entry(fl, &file_lock_list, fl_link) { 2146 lock_get_status(f, bfl, (long)f->private, " ->");
2173 struct file_lock *bfl;
2174 2147
2175 lock_get_status(q, fl, ++i, ""); 2148 f->private++;
2176 move_lock_status(&q, &pos, offset); 2149 return 0;
2150}
2177 2151
2178 if(pos >= offset+length) 2152static void *locks_start(struct seq_file *f, loff_t *pos)
2179 goto done; 2153{
2154 lock_kernel();
2155 f->private = (void *)1;
2156 return seq_list_start(&file_lock_list, *pos);
2157}
2180 2158
2181 list_for_each_entry(bfl, &fl->fl_block, fl_block) { 2159static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
2182 lock_get_status(q, bfl, i, " ->"); 2160{
2183 move_lock_status(&q, &pos, offset); 2161 return seq_list_next(v, &file_lock_list, pos);
2162}
2184 2163
2185 if(pos >= offset+length) 2164static void locks_stop(struct seq_file *f, void *v)
2186 goto done; 2165{
2187 }
2188 }
2189done:
2190 unlock_kernel(); 2166 unlock_kernel();
2191 *start = buffer;
2192 if(q-buffer < length)
2193 return (q-buffer);
2194 return length;
2195} 2167}
2196 2168
2169struct seq_operations locks_seq_operations = {
2170 .start = locks_start,
2171 .next = locks_next,
2172 .stop = locks_stop,
2173 .show = locks_show,
2174};
2175#endif
2176
2197/** 2177/**
2198 * lock_may_read - checks that the region is free of locks 2178 * lock_may_read - checks that the region is free of locks
2199 * @inode: the inode that is being read 2179 * @inode: the inode that is being read
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index bee251cb87c8..c9d6d5f400ad 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -66,7 +66,6 @@ extern int get_stram_list(char *);
66extern int get_filesystem_list(char *); 66extern int get_filesystem_list(char *);
67extern int get_exec_domain_list(char *); 67extern int get_exec_domain_list(char *);
68extern int get_dma_list(char *); 68extern int get_dma_list(char *);
69extern int get_locks_status (char *, char **, off_t, int);
70 69
71static int proc_calc_metrics(char *page, char **start, off_t off, 70static int proc_calc_metrics(char *page, char **start, off_t off,
72 int count, int *eof, int len) 71 int count, int *eof, int len)
@@ -617,16 +616,18 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
617 return proc_calc_metrics(page, start, off, count, eof, len); 616 return proc_calc_metrics(page, start, off, count, eof, len);
618} 617}
619 618
620static int locks_read_proc(char *page, char **start, off_t off, 619static int locks_open(struct inode *inode, struct file *filp)
621 int count, int *eof, void *data)
622{ 620{
623 int len = get_locks_status(page, start, off, count); 621 return seq_open(filp, &locks_seq_operations);
624
625 if (len < count)
626 *eof = 1;
627 return len;
628} 622}
629 623
624static const struct file_operations proc_locks_operations = {
625 .open = locks_open,
626 .read = seq_read,
627 .llseek = seq_lseek,
628 .release = seq_release,
629};
630
630static int execdomains_read_proc(char *page, char **start, off_t off, 631static int execdomains_read_proc(char *page, char **start, off_t off,
631 int count, int *eof, void *data) 632 int count, int *eof, void *data)
632{ 633{
@@ -684,7 +685,6 @@ void __init proc_misc_init(void)
684#endif 685#endif
685 {"filesystems", filesystems_read_proc}, 686 {"filesystems", filesystems_read_proc},
686 {"cmdline", cmdline_read_proc}, 687 {"cmdline", cmdline_read_proc},
687 {"locks", locks_read_proc},
688 {"execdomains", execdomains_read_proc}, 688 {"execdomains", execdomains_read_proc},
689 {NULL,} 689 {NULL,}
690 }; 690 };
@@ -702,6 +702,7 @@ void __init proc_misc_init(void)
702 entry->proc_fops = &proc_kmsg_operations; 702 entry->proc_fops = &proc_kmsg_operations;
703 } 703 }
704#endif 704#endif
705 create_seq_entry("locks", 0, &proc_locks_operations);
705 create_seq_entry("devices", 0, &proc_devinfo_operations); 706 create_seq_entry("devices", 0, &proc_devinfo_operations);
706 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); 707 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
707#ifdef CONFIG_BLOCK 708#ifdef CONFIG_BLOCK
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f5075e0e7301..4f1e8cebea78 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -883,6 +883,7 @@ extern int vfs_setlease(struct file *, long, struct file_lock **);
883extern int lease_modify(struct file_lock **, int); 883extern int lease_modify(struct file_lock **, int);
884extern int lock_may_read(struct inode *, loff_t start, unsigned long count); 884extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
885extern int lock_may_write(struct inode *, loff_t start, unsigned long count); 885extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
886extern struct seq_operations locks_seq_operations;
886 887
887struct fasync_struct { 888struct fasync_struct {
888 int magic; 889 int magic;