* [PATCH] 2.5.59: ftruncate/truncate oopses with mandatory locking
@ 2003-01-23 0:55 Faik Uygur
2003-01-23 22:04 ` Robert Williamson
0 siblings, 1 reply; 2+ messages in thread
From: Faik Uygur @ 2003-01-23 0:55 UTC (permalink / raw)
To: linux-kernel; +Cc: torvalds, robbiew
This patch fixes the truncate/ftruncate oopses with mandatory locking
enabled. The problem with ftruncate is that the local variable fl is
not initialized properly in locks_mandatory_area that it misbehaves at
various places like locks_insert_block. And the problem with truncate
is that the filp variable is NULL at posix_lock_file. The NULL value
comes from do_sys_truncate.
The bug report and details can be found at,
http://bugme.osdl.org/show_bug.cgi?id=280
diff -uNr linux-2.5.59-vanilla/fs/lockd/svclock.c linux-2.5.59/fs/lockd/svclock.c
--- linux-2.5.59-vanilla/fs/lockd/svclock.c Thu Nov 28 00:35:55 2002
+++ linux-2.5.59/fs/lockd/svclock.c Thu Jan 23 00:41:45 2003
@@ -315,7 +315,7 @@
again:
if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
if (block)
nlmsvc_delete_block(block, 0);
@@ -419,7 +419,7 @@
nlmsvc_cancel_blocked(file, lock);
lock->fl.fl_type = F_UNLCK;
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
}
@@ -523,7 +523,7 @@
* following yields an error, this is most probably due to low
* memory. Retry the lock in a few seconds.
*/
- if ((error = posix_lock_file(&file->f_file, &lock->fl)) < 0) {
+ if ((error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl)) < 0) {
printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
-error, __FUNCTION__);
nlmsvc_insert_block(block, 10 * HZ);
diff -uNr linux-2.5.59-vanilla/fs/lockd/svcsubs.c linux-2.5.59/fs/lockd/svcsubs.c
--- linux-2.5.59-vanilla/fs/lockd/svcsubs.c Thu Nov 28 00:36:14 2002
+++ linux-2.5.59/fs/lockd/svcsubs.c Thu Jan 23 01:01:51 2003
@@ -176,7 +176,7 @@
lock.fl_type = F_UNLCK;
lock.fl_start = 0;
lock.fl_end = OFFSET_MAX;
- if (posix_lock_file(&file->f_file, &lock) < 0) {
+ if (posix_lock_file(file->f_file.f_dentry->d_inode, &lock) < 0) {
printk("lockd: unlock failure in %s:%d\n",
__FILE__, __LINE__);
return 1;
diff -uNr linux-2.5.59-vanilla/fs/locks.c linux-2.5.59/fs/locks.c
--- linux-2.5.59-vanilla/fs/locks.c Thu Jan 23 00:02:16 2003
+++ linux-2.5.59/fs/locks.c Thu Jan 23 01:58:16 2003
@@ -678,6 +678,10 @@
struct file_lock fl;
int error;
+ INIT_LIST_HEAD(&fl.fl_link);
+ INIT_LIST_HEAD(&fl.fl_block);
+ init_waitqueue_head(&fl.fl_wait);
+
fl.fl_owner = current->files;
fl.fl_pid = current->tgid;
fl.fl_file = filp;
@@ -685,9 +689,14 @@
fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
fl.fl_start = offset;
fl.fl_end = offset + count - 1;
+ fl.fl_next = NULL;
+ fl.fl_notify = NULL;
+ fl.fl_insert = NULL;
+ fl.fl_remove = NULL;
+ fl.fl_fasync = NULL;
for (;;) {
- error = posix_lock_file(filp, &fl);
+ error = posix_lock_file(inode, &fl);
if (error != -EAGAIN)
break;
error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
@@ -772,9 +781,8 @@
/**
* posix_lock_file:
- * @filp: The file to apply the lock to
- * @caller: The lock to be applied
- * @wait: 1 to retry automatically, 0 to return -EAGAIN
+ * @inode: The inode of file to apply the lock to
+ * @request: The lock to be applied
*
* Add a POSIX style lock to a file.
* We merge adjacent locks whenever possible. POSIX locks are sorted by owner
@@ -788,14 +796,13 @@
* To all purists: Yes, I use a few goto's. Just pass on to the next function.
*/
-int posix_lock_file(struct file *filp, struct file_lock *request)
+int posix_lock_file(struct inode *inode, struct file_lock *request)
{
struct file_lock *fl;
struct file_lock *new_fl, *new_fl2;
struct file_lock *left = NULL;
struct file_lock *right = NULL;
struct file_lock **before;
- struct inode * inode = filp->f_dentry->d_inode;
int error, added = 0;
/*
@@ -1460,7 +1467,7 @@
}
for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1600,7 +1607,7 @@
}
for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK64))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1650,7 +1657,7 @@
/* Ignore any error -- we must remove the locks anyway */
}
- posix_lock_file(filp, &lock);
+ posix_lock_file(filp->f_dentry->d_inode, &lock);
}
/*
@@ -1717,7 +1724,7 @@
} else {
unlock_kernel();
waiter->fl_type = F_UNLCK;
- posix_lock_file(filp, waiter);
+ posix_lock_file(filp->f_dentry->d_inode, waiter);
}
}
diff -uNr linux-2.5.59-vanilla/include/linux/fs.h linux-2.5.59/include/linux/fs.h
--- linux-2.5.59-vanilla/include/linux/fs.h Thu Jan 23 00:02:44 2003
+++ linux-2.5.59/include/linux/fs.h Thu Jan 23 00:48:25 2003
@@ -568,7 +568,7 @@
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
-extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_lock_file(struct inode *, struct file_lock *);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
extern void posix_unblock_lock(struct file *, struct file_lock *);
extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] 2.5.59: ftruncate/truncate oopses with mandatory locking
2003-01-23 0:55 [PATCH] 2.5.59: ftruncate/truncate oopses with mandatory locking Faik Uygur
@ 2003-01-23 22:04 ` Robert Williamson
0 siblings, 0 replies; 2+ messages in thread
From: Robert Williamson @ 2003-01-23 22:04 UTC (permalink / raw)
To: Faik Uygur; +Cc: linux-kernel, torvalds
[-- Attachment #1: Type: text/plain, Size: 1081 bytes --]
>This patch fixes the truncate/ftruncate oopses with mandatory locking
>enabled. The problem with ftruncate is that the local variable fl is
>not initialized properly in locks_mandatory_area that it misbehaves at
>various places like locks_insert_block. And the problem with truncate
>is that the filp variable is NULL at posix_lock_file. The NULL value
>comes from do_sys_truncate.
>
locks_mandatory_area needed a bit more tweaking to allow correct error
handling, as well as
adherence to the O_NONBLOCK flag if/when used. Merged the original patch
with my updates,
and updated the bug report.
>The bug report and details can be found at,
>http://bugme.osdl.org/show_bug.cgi?id=280
- Robbie
Robert V. Williamson <robbiew@us.ibm.com>
Linux Test Project
IBM Linux Technology Center
Phone: (512) 838-9295 T/L: 678-9295
Fax: (512) 838-4603
Web: http://ltp.sourceforge.net
IRC: #ltp on freenode.irc.net
====================
"Only two things are infinite, the universe and human stupidity, and I'm
not sure about the former." -Albert Einstein
(See attached file: bug280.patch)
[-- Attachment #2: bug280.patch --]
[-- Type: application/octet-stream, Size: 5891 bytes --]
--- linux-2.5.59-orig/fs/lockd/svclock.c Thu Jan 16 20:21:49 2003
+++ linux-2.5.59-new/fs/lockd/svclock.c Thu Jan 23 16:32:16 2003
@@ -315,7 +315,7 @@
again:
if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
if (block)
nlmsvc_delete_block(block, 0);
@@ -419,7 +419,7 @@
nlmsvc_cancel_blocked(file, lock);
lock->fl.fl_type = F_UNLCK;
- error = posix_lock_file(&file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl);
return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
}
@@ -523,7 +523,7 @@
* following yields an error, this is most probably due to low
* memory. Retry the lock in a few seconds.
*/
- if ((error = posix_lock_file(&file->f_file, &lock->fl)) < 0) {
+ if ((error = posix_lock_file(file->f_file.f_dentry->d_inode, &lock->fl)) < 0) {
printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
-error, __FUNCTION__);
nlmsvc_insert_block(block, 10 * HZ);
--- linux-2.5.59-orig/fs/lockd/svcsubs.c Thu Jan 16 20:22:21 2003
+++ linux-2.5.59-new/fs/lockd/svcsubs.c Thu Jan 23 16:32:16 2003
@@ -176,7 +176,7 @@
lock.fl_type = F_UNLCK;
lock.fl_start = 0;
lock.fl_end = OFFSET_MAX;
- if (posix_lock_file(&file->f_file, &lock) < 0) {
+ if (posix_lock_file(file->f_file.f_dentry->d_inode, &lock) < 0) {
printk("lockd: unlock failure in %s:%d\n",
__FILE__, __LINE__);
return 1;
--- linux-2.5.59-orig/fs/locks.c Thu Jan 16 20:22:44 2003
+++ linux-2.5.59-new/fs/locks.c Thu Jan 23 16:32:19 2003
@@ -678,27 +678,52 @@
struct file_lock fl;
int error;
+ INIT_LIST_HEAD(&fl.fl_link);
+ INIT_LIST_HEAD(&fl.fl_block);
+ init_waitqueue_head(&fl.fl_wait);
+
fl.fl_owner = current->files;
fl.fl_pid = current->tgid;
fl.fl_file = filp;
- fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP;
+
+ /* If the O_NONBLOCK flag is used don't sleep while */
+ /* the lock is present -RW */
+ if ((filp != NULL) && (filp->f_flags & O_NONBLOCK))
+ fl.fl_flags = FL_POSIX | FL_ACCESS;
+ else
+ fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP;
+
fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
fl.fl_start = offset;
fl.fl_end = offset + count - 1;
+ fl.fl_next = NULL;
+ fl.fl_notify = NULL;
+ fl.fl_insert = NULL;
+ fl.fl_remove = NULL;
+ fl.fl_fasync = NULL;
for (;;) {
- error = posix_lock_file(filp, &fl);
- if (error != -EAGAIN)
+ error = posix_lock_file(inode, &fl);
+
+ /* If the returned error is EAGAIN, filp is */
+ /* not NULL, and O_NONBLOCK was specified */
+ /* then return the EAGAIN error -RW */
+ if ((error == -EAGAIN) && (filp != NULL) && (filp->f_flags & O_NONBLOCK))
break;
+
+ /* posix_lock_file may return EDEADLK, so */
+ /* we should pass it on if this occurs -RW */
+ if (error == -EDEADLK)
+ break;
+
error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
- if (!error) {
- /*
- * If we've been sleeping someone might have
- * changed the permissions behind our back.
- */
- if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
- continue;
- }
+
+ /*
+ * If we've been sleeping someone might have
+ * changed the permissions behind our back.
+ */
+ if ((!error) && ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID))
+ break;
lock_kernel();
locks_delete_block(&fl);
@@ -772,9 +797,8 @@
/**
* posix_lock_file:
- * @filp: The file to apply the lock to
- * @caller: The lock to be applied
- * @wait: 1 to retry automatically, 0 to return -EAGAIN
+ * @inode: The inode of file to apply the lock to
+ * @request: The lock to be applied
*
* Add a POSIX style lock to a file.
* We merge adjacent locks whenever possible. POSIX locks are sorted by owner
@@ -788,14 +812,13 @@
* To all purists: Yes, I use a few goto's. Just pass on to the next function.
*/
-int posix_lock_file(struct file *filp, struct file_lock *request)
+int posix_lock_file(struct inode *inode, struct file_lock *request)
{
struct file_lock *fl;
struct file_lock *new_fl, *new_fl2;
struct file_lock *left = NULL;
struct file_lock *right = NULL;
struct file_lock **before;
- struct inode * inode = filp->f_dentry->d_inode;
int error, added = 0;
/*
@@ -1460,7 +1483,7 @@
}
for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1600,7 +1623,7 @@
}
for (;;) {
- error = posix_lock_file(filp, file_lock);
+ error = posix_lock_file(inode, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK64))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1650,7 +1673,7 @@
/* Ignore any error -- we must remove the locks anyway */
}
- posix_lock_file(filp, &lock);
+ posix_lock_file(filp->f_dentry->d_inode, &lock);
}
/*
@@ -1717,7 +1740,7 @@
} else {
unlock_kernel();
waiter->fl_type = F_UNLCK;
- posix_lock_file(filp, waiter);
+ posix_lock_file(filp->f_dentry->d_inode, waiter);
}
}
--- linux-2.5.59-orig/include/linux/fs.h Thu Jan 16 20:21:47 2003
+++ linux-2.5.59-new/include/linux/fs.h Thu Jan 23 16:31:56 2003
@@ -568,7 +568,7 @@
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
-extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_lock_file(struct inode *, struct file_lock *);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
extern void posix_unblock_lock(struct file *, struct file_lock *);
extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-01-23 21:55 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-01-23 0:55 [PATCH] 2.5.59: ftruncate/truncate oopses with mandatory locking Faik Uygur
2003-01-23 22:04 ` Robert Williamson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).