summaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
commitd8d9b8f76f22b7a16a83e261e64f89ee611f49df (patch)
tree3067bc130b80d52808e6390c9fc7fc087ec1e33c /fs/locks.c
parent19c9bba94152148523ba0f7ef7cffe3d45656b11 (diff)
Initial revision
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c108
1 files changed, 77 insertions, 31 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 3aa530897..8ca8aa183 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -100,6 +100,9 @@
*
* Some adaptations for NFS support.
* Olaf Kirch (okir@monad.swb.de), Dec 1996,
+ *
+ * Fixed /proc/locks interface so that we can't overrun the buffer we are handed.
+ * Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997.
*/
#include <linux/malloc.h>
@@ -132,7 +135,7 @@ static int posix_locks_deadlock(struct file_lock *caller,
static struct file_lock *locks_alloc_lock(struct file_lock *fl);
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, char *p, int id, char *pfx);
+static char *lock_get_status(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);
@@ -227,6 +230,7 @@ void
posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
{
locks_insert_block(blocker, waiter);
+ return;
}
void
@@ -234,6 +238,7 @@ posix_unblock_lock(struct file_lock *waiter)
{
if (waiter->fl_prevblock)
locks_delete_block(waiter->fl_prevblock, waiter);
+ return;
}
/* Wake up processes blocked waiting for blocker.
@@ -269,20 +274,20 @@ asmlinkage int sys_flock(unsigned int fd, unsigned int cmd)
{
struct file_lock file_lock;
struct file *filp;
- int err;
+ int error;
lock_kernel();
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
- err = -EBADF;
+ error = -EBADF;
else if (!flock_make_lock(filp, &file_lock, cmd))
- err = -EINVAL;
+ error = -EINVAL;
else if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3))
- err = -EBADF;
+ error = -EBADF;
else
- err = flock_lock_file(filp, &file_lock,
- (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
+ error = flock_lock_file(filp, &file_lock,
+ (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
unlock_kernel();
- return err;
+ return (error);
}
/* Report the first existing lock that would conflict with l.
@@ -298,7 +303,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
return (-EBADF);
if (copy_from_user(&flock, l, sizeof(flock)))
- return -EFAULT;
+ return (-EFAULT);
if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
return (-EINVAL);
@@ -308,9 +313,9 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
if (filp->f_op->lock) {
error = filp->f_op->lock(filp->f_inode, filp,
- F_GETLK, &file_lock);
+ F_GETLK, &file_lock);
if (error < 0)
- return error;
+ return (error);
fl = &file_lock;
} else {
fl = posix_test_lock(filp, &file_lock);
@@ -323,12 +328,12 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
fl->fl_end - fl->fl_start + 1;
flock.l_whence = 0;
flock.l_type = fl->fl_type;
- return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0;
+ return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0);
} else {
flock.l_type = F_UNLCK;
}
- return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0;
+ return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0);
}
/* Apply the lock described by l to an open file descriptor.
@@ -361,12 +366,11 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
do {
if (vma->vm_flags & VM_MAYSHARE)
return (-EAGAIN);
- vma = vma->vm_next_share;
- } while (vma != inode->i_mmap);
+ } while ((vma = vma->vm_next_share) != NULL);
}
if (copy_from_user(&flock, l, sizeof(flock)))
- return -EFAULT;
+ return (-EFAULT);
if (!posix_make_lock(filp, &file_lock, &flock))
return (-EINVAL);
@@ -399,13 +403,13 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
break;
#endif
default:
- return -EINVAL;
+ return (-EINVAL);
}
if (filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp->f_inode, filp, cmd, &file_lock);
if (error < 0)
- return error;
+ return (error);
}
return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW));
@@ -457,7 +461,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
break;
}
- return cfl;
+ return (cfl);
}
int locks_verify_locked(struct inode *inode)
@@ -1044,16 +1048,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait)
}
-static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx)
+static char *lock_get_status(struct file_lock *fl, int id, char *pfx)
{
+ static char temp[129];
+ char *p = temp;
struct inode *inode;
inode = fl->fl_file->f_inode;
p += sprintf(p, "%d:%s ", id, pfx);
if (fl->fl_flags & FL_POSIX) {
- p += sprintf(p, "%s %s ",
- (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX",
+ p += sprintf(p, "%6s %s ",
+ (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
(IS_MANDLOCK(inode) &&
(inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
"MANDATORY" : "ADVISORY ");
@@ -1066,28 +1072,68 @@ static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx)
fl->fl_pid,
kdevname(inode->i_dev), inode->i_ino, fl->fl_start,
fl->fl_end);
- p += sprintf(p, "%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 (p);
+ sprintf(p, "%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);
}
-int get_locks_status(char *buf)
+static inline int copy_lock_status(char *p, char **q, off_t pos, int len,
+ off_t offset, int length)
+{
+ int 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;
+ }
+
+ return (1);
+}
+
+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;
int i;
+ int len;
+ off_t pos = 0;
- p = buf;
for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) {
- p = lock_get_status(fl, p, i, "");
+ p = lock_get_status(fl, i, "");
+ len = strlen(p);
+ pos += len;
+ if (!copy_lock_status(p, &q, pos, len, offset, length))
+ goto done;
if ((bfl = fl->fl_nextblock) == NULL)
continue;
do {
- p = lock_get_status(bfl, p, i, " ->");
+ p = lock_get_status(bfl, i, " ->");
+ len = strlen(p);
+ pos += len;
+ if (!copy_lock_status(p, &q, pos, len, offset, length))
+ goto done;
} while ((bfl = bfl->fl_nextblock) != fl);
}
- return (p - buf);
+done:
+ if (q != buffer)
+ *start = buffer;
+ return (q - buffer);
}
+
+