X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Flocks.c;h=749a0dc7cd4b674cdd974ec8ee02e271923d5401;hb=9d6a8c5c213e34c475e72b245a8eb709258e968c;hp=52a81005dab4b8878bba2a3f1586bc346890cc5b;hpb=706b75ddbe36d20d071424f9867385c319b67f8d;p=linux-2.6 diff --git a/fs/locks.c b/fs/locks.c index 52a81005da..749a0dc7cd 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -666,11 +666,11 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w } int -posix_test_lock(struct file *filp, struct file_lock *fl, - struct file_lock *conflock) +posix_test_lock(struct file *filp, struct file_lock *fl) { struct file_lock *cfl; + fl->fl_type = F_UNLCK; lock_kernel(); for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { if (!IS_POSIX(cfl)) @@ -679,7 +679,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl, break; } if (cfl) { - __locks_copy_lock(conflock, cfl); + __locks_copy_lock(fl, cfl); unlock_kernel(); return 1; } @@ -1611,12 +1611,44 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) return error; } +static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) +{ + flock->l_pid = fl->fl_pid; +#if BITS_PER_LONG == 32 + /* + * Make sure we can represent the posix lock via + * legacy 32bit flock. + */ + if (fl->fl_start > OFFT_OFFSET_MAX) + return -EOVERFLOW; + if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX) + return -EOVERFLOW; +#endif + flock->l_start = fl->fl_start; + flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : + fl->fl_end - fl->fl_start + 1; + flock->l_whence = 0; + return 0; +} + +#if BITS_PER_LONG == 32 +static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) +{ + flock->l_pid = fl->fl_pid; + flock->l_start = fl->fl_start; + flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : + fl->fl_end - fl->fl_start + 1; + flock->l_whence = 0; + flock->l_type = fl->fl_type; +} +#endif + /* Report the first existing lock that would conflict with l. * This implements the F_GETLK command of fcntl(). */ int fcntl_getlk(struct file *filp, struct flock __user *l) { - struct file_lock *fl, cfl, file_lock; + struct file_lock file_lock; struct flock flock; int error; @@ -1633,36 +1665,16 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) if (filp->f_op && filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); if (error < 0) goto out; - else - fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); - } else { - fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL); - } + } else + posix_test_lock(filp, &file_lock); - flock.l_type = F_UNLCK; - if (fl != NULL) { - flock.l_pid = fl->fl_pid; -#if BITS_PER_LONG == 32 - /* - * Make sure we can represent the posix lock via - * legacy 32bit flock. - */ - error = -EOVERFLOW; - if (fl->fl_start > OFFT_OFFSET_MAX) - goto out; - if ((fl->fl_end != OFFSET_MAX) - && (fl->fl_end > OFFT_OFFSET_MAX)) + flock.l_type = file_lock.fl_type; + if (file_lock.fl_type != F_UNLCK) { + error = posix_lock_to_flock(&flock, &file_lock); + if (error) goto out; -#endif - flock.l_start = fl->fl_start; - flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : - fl->fl_end - fl->fl_start + 1; - flock.l_whence = 0; - flock.l_type = fl->fl_type; } error = -EFAULT; if (!copy_to_user(l, &flock, sizeof(flock))) @@ -1738,7 +1750,7 @@ again: else { for (;;) { error = posix_lock_file(filp, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK)) + if (error != -EAGAIN || cmd == F_SETLK) break; error = wait_event_interruptible(file_lock->fl_wait, !file_lock->fl_next); @@ -1770,7 +1782,7 @@ out: */ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) { - struct file_lock *fl, cfl, file_lock; + struct file_lock file_lock; struct flock64 flock; int error; @@ -1787,25 +1799,15 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) if (filp->f_op && filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); if (error < 0) goto out; - else - fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); - } else { - fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL); - } + } else + posix_test_lock(filp, &file_lock); - flock.l_type = F_UNLCK; - if (fl != NULL) { - flock.l_pid = fl->fl_pid; - flock.l_start = fl->fl_start; - flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : - fl->fl_end - fl->fl_start + 1; - flock.l_whence = 0; - flock.l_type = fl->fl_type; - } + flock.l_type = file_lock.fl_type; + if (file_lock.fl_type != F_UNLCK) + posix_lock_to_flock64(&flock, &file_lock); + error = -EFAULT; if (!copy_to_user(l, &flock, sizeof(flock))) error = 0; @@ -1881,7 +1883,7 @@ again: else { for (;;) { error = posix_lock_file(filp, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK64)) + if (error != -EAGAIN || cmd == F_SETLK64) break; error = wait_event_interruptible(file_lock->fl_wait, !file_lock->fl_next);