patch for 2.1.87 fs/locks.c

Bill Hawes (whawes@star.net)
Wed, 18 Feb 1998 12:50:20 -0500


This is a multi-part message in MIME format.
--------------3D7A153AAA98B468F72D3D8A
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached minor patch for fs/locks.c is needed to enable some changes to
protect files from being closed by clone tasks. The patch splits the current
locks_remove_locks() functionality into two parts, one for POSIX locks and one
for flock, since the two types of locks need to be removed under different
conditions. The locks_remove_posix() is called from close_fp(), while the
locks_remove_flock() routine is called from fput() when f_count is going to 0.

With these changes in place, file structures used by clone tasks can be
protected from being closed by doing an fget() and fput(), and the appropriate
lock removal code will be called when needed.

The patch also makes a minor change to should slightly improve performance --
when removing the lock, we don't need to copy the lock structure if the fs
doesn't implement a lock f_op (as most don't.)

If these changes look reasonable, I'll go ahead and forward it to Linus.

Regards,
Bill
--------------3D7A153AAA98B468F72D3D8A
Content-Type: text/plain; charset=us-ascii; name="locks_87-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="locks_87-patch"

--- linux-2.1.87/include/linux/fs.h.old Tue Feb 17 11:10:48 1998
+++ linux-2.1.87/include/linux/fs.h Wed Feb 18 12:17:26 1998
@@ -446,7 +446,10 @@

extern int fcntl_getlk(unsigned int fd, struct flock *l);
extern int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l);
-extern void locks_remove_locks(struct task_struct *task, struct file *filp);
+
+/* fs/locks.c */
+extern void locks_remove_posix(struct task_struct *, struct file *);
+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 *, unsigned int);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
--- linux-2.1.87/include/linux/file.h.old Mon Jul 14 00:20:10 1997
+++ linux-2.1.87/include/linux/file.h Wed Feb 18 12:29:43 1998
@@ -29,6 +29,7 @@
int error = 0;

if (!count) {
+ locks_remove_flock(file);
error = __fput(file);
file->f_count = 0;
remove_filp(file);
--- linux-2.1.87/fs/locks.c.old Fri Dec 5 18:32:36 1997
+++ linux-2.1.87/fs/locks.c Wed Feb 18 12:25:22 1998
@@ -441,30 +441,32 @@
return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW));
}

-/* This function is called when the file is closed.
+/*
+ * This function is called when the file is being removed
+ * from the task's fd array.
*/
-void locks_remove_locks(struct task_struct *task, struct file *filp)
+void locks_remove_posix(struct task_struct *task, struct file *filp)
{
+ struct inode * inode = filp->f_dentry->d_inode;
struct file_lock file_lock, *fl;
struct file_lock **before;
- struct inode * inode;

- /* For POSIX locks we free all locks on this file for the given task.
- * For FLOCK we only free locks on this *open* file if it is the last
- * close on that file.
+ /*
+ * For POSIX locks we free all locks on this file for the given task.
*/
- inode = filp->f_dentry->d_inode;
repeat:
before = &inode->i_flock;
while ((fl = *before) != NULL) {
- if (((fl->fl_flags & FL_POSIX) && (fl->fl_owner == task)) ||
- ((fl->fl_flags & FL_FLOCK) && (fl->fl_file == filp) &&
- (filp->f_count == 1))) {
- file_lock = *fl;
- locks_delete_lock(before, 0);
- if (filp->f_op->lock) {
+ if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == task) {
+ int (*lock)(struct file *, int, struct file_lock *);
+ lock = filp->f_op->lock;
+ if (lock) {
+ file_lock = *fl;
file_lock.fl_type = F_UNLCK;
- filp->f_op->lock(filp, F_SETLK, &file_lock);
+ }
+ locks_delete_lock(before, 0);
+ if (lock) {
+ lock(filp, F_SETLK, &file_lock);
/* List may have changed: */
goto repeat;
}
@@ -472,8 +474,37 @@
}
before = &fl->fl_next;
}
+}

- return;
+/*
+ * This function is called on the last close of an open file.
+ */
+void locks_remove_flock(struct file *filp)
+{
+ struct inode * inode = filp->f_dentry->d_inode;
+ struct file_lock file_lock, *fl;
+ struct file_lock **before;
+
+repeat:
+ before = &inode->i_flock;
+ while ((fl = *before) != NULL) {
+ if ((fl->fl_flags & FL_FLOCK) && fl->fl_file == filp) {
+ int (*lock)(struct file *, int, struct file_lock *);
+ lock = filp->f_op->lock;
+ if (lock) {
+ file_lock = *fl;
+ file_lock.fl_type = F_UNLCK;
+ }
+ locks_delete_lock(before, 0);
+ if (lock) {
+ lock(filp, F_SETLK, &file_lock);
+ /* List may have changed: */
+ goto repeat;
+ }
+ continue;
+ }
+ before = &fl->fl_next;
+ }
}

struct file_lock *
--- linux-2.1.87/fs/open.c.old Sat Jan 24 10:13:16 1998
+++ linux-2.1.87/fs/open.c Wed Feb 18 12:21:03 1998
@@ -745,17 +745,14 @@

int close_fp(struct file *filp)
{
- struct dentry *dentry;
- struct inode *inode;
+ struct dentry *dentry = filp->f_dentry;

if (filp->f_count == 0) {
printk("VFS: Close: file count is 0\n");
return 0;
}
- dentry = filp->f_dentry;
- inode = dentry->d_inode;
- if (inode)
- locks_remove_locks(current, filp);
+ if (dentry->d_inode)
+ locks_remove_posix(current, filp);
return fput(filp);
}

--------------3D7A153AAA98B468F72D3D8A--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu