diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-01 17:41:15 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-10-09 18:32:46 -0400 |
commit | 7f8ada98d9edd83d6ebd01e431e15b024a4a3dc4 (patch) | |
tree | 1231947efa06478714eeabac3bdbffc663f453c7 /fs/locks.c | |
parent | 094f2825218fec1b240cb8537d2d0a10edf5ddc9 (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>
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 122 |
1 files changed, 51 insertions, 71 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 | ||
2067 | EXPORT_SYMBOL_GPL(vfs_cancel_lock); | 2067 | EXPORT_SYMBOL_GPL(vfs_cancel_lock); |
2068 | 2068 | ||
2069 | static 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 | |||
2072 | static 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 | ||
2134 | static void move_lock_status(char **p, off_t* pos, off_t offset) | 2137 | static 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 | ||
2164 | int 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) | 2152 | static 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) { | 2159 | static 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) | 2164 | static void locks_stop(struct seq_file *f, void *v) |
2186 | goto done; | 2165 | { |
2187 | } | ||
2188 | } | ||
2189 | done: | ||
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 | ||
2169 | struct 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 |