Messages in this thread Patch in this message | | | Date | Wed, 18 Feb 1998 12:50:20 -0500 | From | Bill Hawes <> | Subject | patch for 2.1.87 fs/locks.c |
| |
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--- 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); } | |