[PATCH] /proc/locks bugfix

From: Manfred Spraul (manfreds@colorfullife.com)
Date: Fri Apr 21 2000 - 04:52:54 EST


Hi Linus,

I found 2 bugs in the proc interface of /proc/locks:

* lock_kernel() was missing.
* the code ignored the requested length. read(fd,buf,1) returned the
complete info (1.6 kB).

Could you add the attached patch to the next kernel?

--
	Manfred

// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 3 // SUBLEVEL = 99 // EXTRAVERSION = -pre5 --- 2.3/fs/proc/proc_misc.c Wed Mar 8 00:46:37 2000 +++ build-2.3/fs/proc/proc_misc.c Fri Apr 21 11:21:06 2000 @@ -30,6 +30,7 @@ #include <linux/signal.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -469,7 +470,10 @@ static int locks_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = get_locks_status(page, start, off, count); + int len; + lock_kernel(); + len = get_locks_status(page, start, off, count); + unlock_kernel(); if (len < count) *eof = 1; return len; } --- 2.3/fs/locks.c Wed Apr 12 15:00:28 2000 +++ build-2.3/fs/locks.c Fri Apr 21 11:50:26 2000 @@ -130,7 +130,7 @@ struct file_lock *); static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl); static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait); -static char *lock_get_status(struct file_lock *fl, int id, char *pfx); +static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx); static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter); static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter); @@ -1179,90 +1179,85 @@ return; } - -static char *lock_get_status(struct file_lock *fl, int id, char *pfx) +static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) { - static char temp[155]; - char *p = temp; struct inode *inode; inode = fl->fl_file->f_dentry->d_inode; - p += sprintf(p, "%d:%s ", id, pfx); + out += sprintf(out, "%d:%s ", id, pfx); if (fl->fl_flags & FL_POSIX) { - p += sprintf(p, "%6s %s ", + out += sprintf(out, "%6s %s ", (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", (IS_MANDLOCK(inode) && (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ? "MANDATORY" : "ADVISORY "); } else { - p += sprintf(p, "FLOCK ADVISORY "); + out += sprintf(out, "FLOCK ADVISORY "); } - p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); - p += sprintf(p, "%d %s:%ld %Ld %Ld ", + out += sprintf(out, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); + out += sprintf(out, "%d %s:%ld %Ld %Ld ", fl->fl_pid, kdevname(inode->i_dev), inode->i_ino, (long long)fl->fl_start, (long long)fl->fl_end); - sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n", + sprintf(out, "%08lx %08lx %08lx %08lx %08lx\n", (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, (long)fl->fl_next, (long)fl->fl_nextblock); - return (temp); } -static inline int copy_lock_status(char *p, char **q, off_t pos, int len, - off_t offset, int length) +static void move_lock_status(char **p, off_t* pos, off_t offset) { - off_t i; - - i = pos - offset; - if (i > 0) { - if (i >= length) { - i = len + length - i; - memcpy(*q, p, i); - *q += i; - return (0); - } - if (i < len) { - p += len - i; - } - else - i = len; - memcpy(*q, p, i); - *q += i; + int len; + len = strlen(*p); + if(*pos >= offset) { + /* the complete line is valid */ + *p += len; + *pos += len; + return; } - - return (1); + if(*pos+len > offset) { + /* use the second part of the line */ + int i = offset-*pos; + memmove(*p,*p+i,len-i); + *p += len-i; + *pos += len; + return; + } + /* discard the complete line */ + *pos += len; } int get_locks_status(char *buffer, char **start, off_t offset, int length) { struct file_lock *fl; struct file_lock *bfl; - char *p; char *q = buffer; - off_t i, len, pos = 0; + off_t pos = 0; + int i; for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) { - p = lock_get_status(fl, i, ""); - len = strlen(p); - pos += len; - if (!copy_lock_status(p, &q, pos, len, offset, length)) + lock_get_status(q, fl, i, ""); + move_lock_status(&q, &pos, offset); + + if(pos >= offset+length) goto done; + if ((bfl = fl->fl_nextblock) == NULL) continue; do { - p = lock_get_status(bfl, i, " ->"); - len = strlen(p); - pos += len; - if (!copy_lock_status(p, &q, pos, len, offset, length)) + lock_get_status(q, bfl, i, " ->"); + move_lock_status(&q, &pos, offset); + + if(pos >= offset+length) goto done; } while ((bfl = bfl->fl_nextblock) != fl); } done: - if (q != buffer) - *start = buffer; - return (q - buffer); + *start = buffer; + if(q-buffer < length) + return (q-buffer); + return length; }

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Apr 23 2000 - 21:00:18 EST