Commit 00c569b5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'locks-v4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux

Pull file locking updates from Jeff Layton:
 "The main change in this set is Neil Brown's work to reduce the
  thundering herd problem when a heavily-contended file lock is
  released.

  Previously we'd always wake up all waiters when this occurred. With
  this set, we'll now we only wake up waiters that were blocked on the
  range being released"

* tag 'locks-v4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux:
  locks: Use inode_is_open_for_write
  fs/locks: remove unnecessary white space.
  fs/locks: merge posix_unblock_lock() and locks_delete_block()
  fs/locks: create a tree of dependent requests.
  fs/locks: change all *_conflict() functions to return bool.
  fs/locks: always delete_block after waiting.
  fs/locks: allow a lock request to block other requests.
  fs/locks: use properly initialized file_lock when unlocking.
  ocfs2: properly initial file_lock used for unlock.
  gfs2: properly initial file_lock used for unlock.
  NFS: use locks_copy_lock() to copy locks.
  fs/locks: split out __locks_wake_up_blocks().
  fs/locks: rename some lists and pointers.
parents f6b1495f 052b8cfa
...@@ -1103,10 +1103,10 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) ...@@ -1103,10 +1103,10 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
rc = posix_lock_file(file, flock, NULL); rc = posix_lock_file(file, flock, NULL);
up_write(&cinode->lock_sem); up_write(&cinode->lock_sem);
if (rc == FILE_LOCK_DEFERRED) { if (rc == FILE_LOCK_DEFERRED) {
rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); rc = wait_event_interruptible(flock->fl_wait, !flock->fl_blocker);
if (!rc) if (!rc)
goto try_again; goto try_again;
posix_unblock_lock(flock); locks_delete_block(flock);
} }
return rc; return rc;
} }
......
...@@ -1199,13 +1199,13 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) ...@@ -1199,13 +1199,13 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
mutex_lock(&fp->f_fl_mutex); mutex_lock(&fp->f_fl_mutex);
if (gfs2_holder_initialized(fl_gh)) { if (gfs2_holder_initialized(fl_gh)) {
struct file_lock request;
if (fl_gh->gh_state == state) if (fl_gh->gh_state == state)
goto out; goto out;
locks_lock_file_wait(file, locks_init_lock(&request);
&(struct file_lock) { request.fl_type = F_UNLCK;
.fl_type = F_UNLCK, request.fl_flags = FL_FLOCK;
.fl_flags = FL_FLOCK locks_lock_file_wait(file, &request);
});
gfs2_glock_dq(fl_gh); gfs2_glock_dq(fl_gh);
gfs2_holder_reinit(state, flags, fl_gh); gfs2_holder_reinit(state, flags, fl_gh);
} else { } else {
......
...@@ -276,7 +276,7 @@ static int nlmsvc_unlink_block(struct nlm_block *block) ...@@ -276,7 +276,7 @@ static int nlmsvc_unlink_block(struct nlm_block *block)
dprintk("lockd: unlinking block %p...\n", block); dprintk("lockd: unlinking block %p...\n", block);
/* Remove block from list */ /* Remove block from list */
status = posix_unblock_lock(&block->b_call->a_args.lock.fl); status = locks_delete_block(&block->b_call->a_args.lock.fl);
nlmsvc_remove_block(block); nlmsvc_remove_block(block);
return status; return status;
} }
......
This diff is collapsed.
...@@ -6311,7 +6311,8 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, ...@@ -6311,7 +6311,8 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
/* Ensure we don't close file until we're done freeing locks! */ /* Ensure we don't close file until we're done freeing locks! */
p->ctx = get_nfs_open_context(ctx); p->ctx = get_nfs_open_context(ctx);
p->l_ctx = nfs_get_lock_context(ctx); p->l_ctx = nfs_get_lock_context(ctx);
memcpy(&p->fl, fl, sizeof(p->fl)); locks_init_lock(&p->fl);
locks_copy_lock(&p->fl, fl);
p->server = NFS_SERVER(inode); p->server = NFS_SERVER(inode);
return p; return p;
} }
...@@ -6533,7 +6534,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, ...@@ -6533,7 +6534,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
p->server = server; p->server = server;
refcount_inc(&lsp->ls_count); refcount_inc(&lsp->ls_count);
p->ctx = get_nfs_open_context(ctx); p->ctx = get_nfs_open_context(ctx);
memcpy(&p->fl, fl, sizeof(p->fl)); locks_init_lock(&p->fl);
locks_copy_lock(&p->fl, fl);
return p; return p;
out_free_seqid: out_free_seqid:
nfs_free_seqid(p->arg.open_seqid); nfs_free_seqid(p->arg.open_seqid);
......
...@@ -238,7 +238,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, ...@@ -238,7 +238,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
} }
spin_unlock(&nn->blocked_locks_lock); spin_unlock(&nn->blocked_locks_lock);
if (found) if (found)
posix_unblock_lock(&found->nbl_lock); locks_delete_block(&found->nbl_lock);
return found; return found;
} }
...@@ -293,7 +293,7 @@ remove_blocked_locks(struct nfs4_lockowner *lo) ...@@ -293,7 +293,7 @@ remove_blocked_locks(struct nfs4_lockowner *lo)
nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock, nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock,
nbl_lru); nbl_lru);
list_del_init(&nbl->nbl_lru); list_del_init(&nbl->nbl_lru);
posix_unblock_lock(&nbl->nbl_lock); locks_delete_block(&nbl->nbl_lock);
free_blocked_lock(nbl); free_blocked_lock(nbl);
} }
} }
...@@ -4863,7 +4863,7 @@ nfs4_laundromat(struct nfsd_net *nn) ...@@ -4863,7 +4863,7 @@ nfs4_laundromat(struct nfsd_net *nn)
nbl = list_first_entry(&reaplist, nbl = list_first_entry(&reaplist,
struct nfsd4_blocked_lock, nbl_lru); struct nfsd4_blocked_lock, nbl_lru);
list_del_init(&nbl->nbl_lru); list_del_init(&nbl->nbl_lru);
posix_unblock_lock(&nbl->nbl_lock); locks_delete_block(&nbl->nbl_lock);
free_blocked_lock(nbl); free_blocked_lock(nbl);
} }
out: out:
......
...@@ -52,6 +52,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode, ...@@ -52,6 +52,7 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
if (lockres->l_flags & OCFS2_LOCK_ATTACHED && if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
lockres->l_level > LKM_NLMODE) { lockres->l_level > LKM_NLMODE) {
int old_level = 0; int old_level = 0;
struct file_lock request;
if (lockres->l_level == LKM_EXMODE) if (lockres->l_level == LKM_EXMODE)
old_level = 1; old_level = 1;
...@@ -66,11 +67,10 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode, ...@@ -66,11 +67,10 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
* level. * level.
*/ */
locks_lock_file_wait(file, locks_init_lock(&request);
&(struct file_lock) { request.fl_type = F_UNLCK;
.fl_type = F_UNLCK, request.fl_flags = FL_FLOCK;
.fl_flags = FL_FLOCK locks_lock_file_wait(file, &request);
});
ocfs2_file_unlock(file); ocfs2_file_unlock(file);
} }
......
...@@ -1044,10 +1044,15 @@ bool opens_in_grace(struct net *); ...@@ -1044,10 +1044,15 @@ bool opens_in_grace(struct net *);
* Obviously, the last two criteria only matter for POSIX locks. * Obviously, the last two criteria only matter for POSIX locks.
*/ */
struct file_lock { struct file_lock {
struct file_lock *fl_next; /* singly linked list for this inode */ struct file_lock *fl_blocker; /* The lock, that is blocking us */
struct list_head fl_list; /* link into file_lock_context */ struct list_head fl_list; /* link into file_lock_context */
struct hlist_node fl_link; /* node in global lists */ struct hlist_node fl_link; /* node in global lists */
struct list_head fl_block; /* circular list of blocked processes */ struct list_head fl_blocked_requests; /* list of requests with
* ->fl_blocker pointing here
*/
struct list_head fl_blocked_member; /* node in
* ->fl_blocker->fl_blocked_requests
*/
fl_owner_t fl_owner; fl_owner_t fl_owner;
unsigned int fl_flags; unsigned int fl_flags;
unsigned char fl_type; unsigned char fl_type;
...@@ -1119,7 +1124,7 @@ extern void locks_remove_file(struct file *); ...@@ -1119,7 +1124,7 @@ extern void locks_remove_file(struct file *);
extern void locks_release_private(struct file_lock *); extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, struct file_lock *); extern void posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *); extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
extern int posix_unblock_lock(struct file_lock *); extern int locks_delete_block(struct file_lock *);
extern int vfs_test_lock(struct file *, struct file_lock *); extern int vfs_test_lock(struct file *, struct file_lock *);
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *); extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl); extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
...@@ -1209,7 +1214,7 @@ static inline int posix_lock_file(struct file *filp, struct file_lock *fl, ...@@ -1209,7 +1214,7 @@ static inline int posix_lock_file(struct file *filp, struct file_lock *fl,
return -ENOLCK; return -ENOLCK;
} }
static inline int posix_unblock_lock(struct file_lock *waiter) static inline int locks_delete_block(struct file_lock *waiter)
{ {
return -ENOENT; return -ENOENT;
} }
......
...@@ -68,7 +68,7 @@ DECLARE_EVENT_CLASS(filelock_lock, ...@@ -68,7 +68,7 @@ DECLARE_EVENT_CLASS(filelock_lock,
__field(struct file_lock *, fl) __field(struct file_lock *, fl)
__field(unsigned long, i_ino) __field(unsigned long, i_ino)
__field(dev_t, s_dev) __field(dev_t, s_dev)
__field(struct file_lock *, fl_next) __field(struct file_lock *, fl_blocker)
__field(fl_owner_t, fl_owner) __field(fl_owner_t, fl_owner)
__field(unsigned int, fl_pid) __field(unsigned int, fl_pid)
__field(unsigned int, fl_flags) __field(unsigned int, fl_flags)
...@@ -82,7 +82,7 @@ DECLARE_EVENT_CLASS(filelock_lock, ...@@ -82,7 +82,7 @@ DECLARE_EVENT_CLASS(filelock_lock,
__entry->fl = fl ? fl : NULL; __entry->fl = fl ? fl : NULL;
__entry->s_dev = inode->i_sb->s_dev; __entry->s_dev = inode->i_sb->s_dev;
__entry->i_ino = inode->i_ino; __entry->i_ino = inode->i_ino;
__entry->fl_next = fl ? fl->fl_next : NULL; __entry->fl_blocker = fl ? fl->fl_blocker : NULL;
__entry->fl_owner = fl ? fl->fl_owner : NULL; __entry->fl_owner = fl ? fl->fl_owner : NULL;
__entry->fl_pid = fl ? fl->fl_pid : 0; __entry->fl_pid = fl ? fl->fl_pid : 0;
__entry->fl_flags = fl ? fl->fl_flags : 0; __entry->fl_flags = fl ? fl->fl_flags : 0;
...@@ -92,9 +92,9 @@ DECLARE_EVENT_CLASS(filelock_lock, ...@@ -92,9 +92,9 @@ DECLARE_EVENT_CLASS(filelock_lock,
__entry->ret = ret; __entry->ret = ret;
), ),
TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_next=0x%p fl_owner=0x%p fl_pid=%u fl_flags=%s fl_type=%s fl_start=%lld fl_end=%lld ret=%d", TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_blocker=0x%p fl_owner=0x%p fl_pid=%u fl_flags=%s fl_type=%s fl_start=%lld fl_end=%lld ret=%d",
__entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev), __entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
__entry->i_ino, __entry->fl_next, __entry->fl_owner, __entry->i_ino, __entry->fl_blocker, __entry->fl_owner,
__entry->fl_pid, show_fl_flags(__entry->fl_flags), __entry->fl_pid, show_fl_flags(__entry->fl_flags),
show_fl_type(__entry->fl_type), show_fl_type(__entry->fl_type),
__entry->fl_start, __entry->fl_end, __entry->ret) __entry->fl_start, __entry->fl_end, __entry->ret)
...@@ -125,7 +125,7 @@ DECLARE_EVENT_CLASS(filelock_lease, ...@@ -125,7 +125,7 @@ DECLARE_EVENT_CLASS(filelock_lease,
__field(struct file_lock *, fl) __field(struct file_lock *, fl)
__field(unsigned long, i_ino) __field(unsigned long, i_ino)
__field(dev_t, s_dev) __field(dev_t, s_dev)
__field(struct file_lock *, fl_next) __field(struct file_lock *, fl_blocker)
__field(fl_owner_t, fl_owner) __field(fl_owner_t, fl_owner)
__field(unsigned int, fl_flags) __field(unsigned int, fl_flags)
__field(unsigned char, fl_type) __field(unsigned char, fl_type)
...@@ -137,7 +137,7 @@ DECLARE_EVENT_CLASS(filelock_lease, ...@@ -137,7 +137,7 @@ DECLARE_EVENT_CLASS(filelock_lease,
__entry->fl = fl ? fl : NULL; __entry->fl = fl ? fl : NULL;
__entry->s_dev = inode->i_sb->s_dev; __entry->s_dev = inode->i_sb->s_dev;
__entry->i_ino = inode->i_ino; __entry->i_ino = inode->i_ino;
__entry->fl_next = fl ? fl->fl_next : NULL; __entry->fl_blocker = fl ? fl->fl_blocker : NULL;
__entry->fl_owner = fl ? fl->fl_owner : NULL; __entry->fl_owner = fl ? fl->fl_owner : NULL;
__entry->fl_flags = fl ? fl->fl_flags : 0; __entry->fl_flags = fl ? fl->fl_flags : 0;
__entry->fl_type = fl ? fl->fl_type : 0; __entry->fl_type = fl ? fl->fl_type : 0;
...@@ -145,9 +145,9 @@ DECLARE_EVENT_CLASS(filelock_lease, ...@@ -145,9 +145,9 @@ DECLARE_EVENT_CLASS(filelock_lease,
__entry->fl_downgrade_time = fl ? fl->fl_downgrade_time : 0; __entry->fl_downgrade_time = fl ? fl->fl_downgrade_time : 0;
), ),
TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_next=0x%p fl_owner=0x%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu", TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_blocker=0x%p fl_owner=0x%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu",
__entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev), __entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
__entry->i_ino, __entry->fl_next, __entry->fl_owner, __entry->i_ino, __entry->fl_blocker, __entry->fl_owner,
show_fl_flags(__entry->fl_flags), show_fl_flags(__entry->fl_flags),
show_fl_type(__entry->fl_type), show_fl_type(__entry->fl_type),
__entry->fl_break_time, __entry->fl_downgrade_time) __entry->fl_break_time, __entry->fl_downgrade_time)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment