Skip to content

Commit befbfe0

Browse files
committed
Merge tag 'locks-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux
Pull file locking updates from Jeff Layton: "When we reworked the blocked locks into a tree structure instead of a flat list a few releases ago, we lost the ability to see all of the file locks in /proc/locks. Luo's patch fixes it to dump out all of the blocked locks instead, which restores the full output. This changes the format of /proc/locks as the blocked locks are shown at multiple levels of indentation now, but lslocks (the only common program I've ID'ed that scrapes this info) seems to be OK with that. Tian also contributed a small patch to remove a useless assignment" * tag 'locks-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux: fs/locks: remove useless assignment in fcntl_getlk fs/locks: print full locks information
2 parents 2f9ef05 + cbe6fc4 commit befbfe0

1 file changed

Lines changed: 56 additions & 10 deletions

File tree

fs/locks.c

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,7 +2369,6 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock)
23692369
if (flock->l_pid != 0)
23702370
goto out;
23712371

2372-
cmd = F_GETLK;
23732372
fl->fl_flags |= FL_OFDLCK;
23742373
fl->fl_owner = filp;
23752374
}
@@ -2825,7 +2824,7 @@ struct locks_iterator {
28252824
};
28262825

28272826
static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2828-
loff_t id, char *pfx)
2827+
loff_t id, char *pfx, int repeat)
28292828
{
28302829
struct inode *inode = NULL;
28312830
unsigned int fl_pid;
@@ -2841,7 +2840,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
28412840
if (fl->fl_file != NULL)
28422841
inode = locks_inode(fl->fl_file);
28432842

2844-
seq_printf(f, "%lld:%s ", id, pfx);
2843+
seq_printf(f, "%lld: ", id);
2844+
2845+
if (repeat)
2846+
seq_printf(f, "%*s", repeat - 1 + (int)strlen(pfx), pfx);
2847+
28452848
if (IS_POSIX(fl)) {
28462849
if (fl->fl_flags & FL_ACCESS)
28472850
seq_puts(f, "ACCESS");
@@ -2903,21 +2906,64 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
29032906
}
29042907
}
29052908

2909+
static struct file_lock *get_next_blocked_member(struct file_lock *node)
2910+
{
2911+
struct file_lock *tmp;
2912+
2913+
/* NULL node or root node */
2914+
if (node == NULL || node->fl_blocker == NULL)
2915+
return NULL;
2916+
2917+
/* Next member in the linked list could be itself */
2918+
tmp = list_next_entry(node, fl_blocked_member);
2919+
if (list_entry_is_head(tmp, &node->fl_blocker->fl_blocked_requests, fl_blocked_member)
2920+
|| tmp == node) {
2921+
return NULL;
2922+
}
2923+
2924+
return tmp;
2925+
}
2926+
29062927
static int locks_show(struct seq_file *f, void *v)
29072928
{
29082929
struct locks_iterator *iter = f->private;
2909-
struct file_lock *fl, *bfl;
2930+
struct file_lock *cur, *tmp;
29102931
struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)->i_sb);
2932+
int level = 0;
29112933

2912-
fl = hlist_entry(v, struct file_lock, fl_link);
2934+
cur = hlist_entry(v, struct file_lock, fl_link);
29132935

2914-
if (locks_translate_pid(fl, proc_pidns) == 0)
2936+
if (locks_translate_pid(cur, proc_pidns) == 0)
29152937
return 0;
29162938

2917-
lock_get_status(f, fl, iter->li_pos, "");
2939+
/* View this crossed linked list as a binary tree, the first member of fl_blocked_requests
2940+
* is the left child of current node, the next silibing in fl_blocked_member is the
2941+
* right child, we can alse get the parent of current node from fl_blocker, so this
2942+
* question becomes traversal of a binary tree
2943+
*/
2944+
while (cur != NULL) {
2945+
if (level)
2946+
lock_get_status(f, cur, iter->li_pos, "-> ", level);
2947+
else
2948+
lock_get_status(f, cur, iter->li_pos, "", level);
29182949

2919-
list_for_each_entry(bfl, &fl->fl_blocked_requests, fl_blocked_member)
2920-
lock_get_status(f, bfl, iter->li_pos, " ->");
2950+
if (!list_empty(&cur->fl_blocked_requests)) {
2951+
/* Turn left */
2952+
cur = list_first_entry_or_null(&cur->fl_blocked_requests,
2953+
struct file_lock, fl_blocked_member);
2954+
level++;
2955+
} else {
2956+
/* Turn right */
2957+
tmp = get_next_blocked_member(cur);
2958+
/* Fall back to parent node */
2959+
while (tmp == NULL && cur->fl_blocker != NULL) {
2960+
cur = cur->fl_blocker;
2961+
level--;
2962+
tmp = get_next_blocked_member(cur);
2963+
}
2964+
cur = tmp;
2965+
}
2966+
}
29212967

29222968
return 0;
29232969
}
@@ -2938,7 +2984,7 @@ static void __show_fd_locks(struct seq_file *f,
29382984

29392985
(*id)++;
29402986
seq_puts(f, "lock:\t");
2941-
lock_get_status(f, fl, *id, "");
2987+
lock_get_status(f, fl, *id, "", 0);
29422988
}
29432989
}
29442990

0 commit comments

Comments
 (0)