locks: skip posix unlock when there are no posix locks
Subsystems (2)
PATCH v2 1/1 locks: skip posix unlock when there are no posix locks
When i_flock contains only flocks, the posix unlock is unnecessary, but called anyway. On gfs2, ocfs2, and possibly others with f_op->lock, the posix unlock can be costly, so only do it if posix locks exist.
--- fs/locks.c | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-)
fs/locks.c +16 -1
@@ -1982,15 +1982,30 @@ out:void locks_remove_posix (struct file *filp,fl_owner_t owner) {struct file_lock lock; +struct file_lock **before; +struct inode *inode;/* * If there are no locks held on this file, we don't need to call * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ -if (!filp->f_path.dentry->d_inode->i_flock) + inode = filp->f_path.dentry->d_inode; + +if (!inode->i_flock)return ; +lock_flocks (); +for_each_lock (inode, before) { +struct file_lock *fl = *before; +if (IS_POSIX (fl)) + goto do_unlock; + } +unlock_flocks (); +return ; + +do_unlock: +unlock_flocks (); lock.fl_type =F_UNLCK ; lock.fl_flags =FL_POSIX |FL_CLOSE ; lock.fl_start =0 ;
Signature · 1 line
1.7.6
Quoted 36 lines · David Teigland
When
i_flockcontains only flocks, the posix unlock is unnecessary, but called anyway. On gfs2, ocfs2, and possibly others withf_op->lock, the posix unlock can be costly, so only do it if posix locks exist.Signed-off-by David Teigland <[email protected]>--- fs/locks.c | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-)fs/locks.c +9
-1@@ -1982,15 +1982,30 @@ out:void locks_remove_posix (struct file *filp,fl_owner_t owner) {struct file_lock lock; +struct file_lock **before; +struct inode *inode;/* * If there are no locks held on this file, we don't need to call * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ -if (!filp->f_path.dentry->d_inode->i_flock) + inode = filp->f_path.dentry->d_inode; + +if (!inode->i_flock)return ; +lock_flocks (); +for_each_lock (inode, before) { +struct file_lock *fl = *before; +if (IS_POSIX (fl))
fs/locks.c out: · line 2011
Quoted 10 lines
fs/locks.c +7
-0+ goto do_unlock; + } +unlock_flocks (); +return ; + +do_unlock: +unlock_flocks (); lock.fl_type =F_UNLCK ; lock.fl_flags =FL_POSIX |FL_CLOSE ; lock.fl_start =0 ;
This assumes that all locks are mirrored in inode->i_flock, which may not be the case if the filesystem implements its own f_op->lock(). The right place for this optimisation would be in your filesystem callback.
Cheers
Trond
Signature · 6 lines
Trond Myklebust Linux NFS client maintainer NetApp [email protected] www.netapp.com
Quoted 27 lines · Trond Myklebust
Quoted 27 lines
void
locks_remove_posix(struct file *filp, fl_owner_t owner){fs/locks.c +15
-1struct file_lock lock; +struct file_lock **before; +struct inode *inode;/* * If there are no locks held on this file, we don't need to call * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ -if (!filp->f_path.dentry->d_inode->i_flock) + inode = filp->f_path.dentry->d_inode; + +if (!inode->i_flock)return ; +lock_flocks (); +for_each_lock (inode, before) { +struct file_lock *fl = *before; +if (IS_POSIX (fl)) + goto do_unlock; + } +unlock_flocks (); +return ; + +do_unlock:
Quoted 8 lines
fs/locks.c out: · line 2011
Quoted 4 lines
fs/locks.c +1
-0+unlock_flocks (); lock.fl_type =F_UNLCK ; lock.fl_flags =FL_POSIX |FL_CLOSE ; lock.fl_start =0 ;This assumes that all locks are mirrored in
inode->i_flock, which may not be the case if the filesystem implements its ownf_op->lock(). The right place for this optimisation would be in your filesystem callback.
I suppose if i_flock is being faked at the same time to avoid the null check. I once looked at not doing lock mirroring in vfs and couldn't for reasons I don't remember... may the null i_flock check was the only reason, not sure.
Dave