From 7badb909e21dcb1b4431427e324eb117014f4a3b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 18 Feb 2013 13:12:01 +0100 Subject: [PATCH] lslocks: add BLOCKER column BLOCKER - PID of the process blocking the lock Signed-off-by: Karel Zak --- misc-utils/lslocks.8 | 3 +++ misc-utils/lslocks.c | 62 +++++++++++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/misc-utils/lslocks.8 b/misc-utils/lslocks.8 index 518ff0fbaa..8881c8c571 100644 --- a/misc-utils/lslocks.8 +++ b/misc-utils/lslocks.8 @@ -61,6 +61,9 @@ will fallback to the device's mountpoint. The path might be truncated, use .B "--notruncate" to get the full path. +.IP "BLOCKER" +Process ID which blocks the lock. + .SH NOTES .nf The lslocks command is meant to replace the lslk(8) command, originally written by diff --git a/misc-utils/lslocks.c b/misc-utils/lslocks.c index fb40dcb73d..7c0637bf09 100644 --- a/misc-utils/lslocks.c +++ b/misc-utils/lslocks.c @@ -55,6 +55,7 @@ enum { COL_START, COL_END, COL_PATH, + COL_BLOCKER }; /* column names */ @@ -76,6 +77,7 @@ static struct colinfo infos[] = { [COL_START] = { "START", 10, TT_FL_RIGHT, N_("relative byte offset of the lock")}, [COL_END] = { "END", 10, TT_FL_RIGHT, N_("ending offset of the lock")}, [COL_PATH] = { "PATH", 0, TT_FL_TRUNC, N_("path of the locked file")}, + [COL_BLOCKER] = { "BLOCKER", 0, TT_FL_RIGHT, N_("PID of the process blocking the lock") } }; #define NCOLS ARRAY_SIZE(infos) static int columns[NCOLS], ncolumns; @@ -96,6 +98,7 @@ struct lock { unsigned int mandatory :1, blocked :1; char *size; + int id; }; static void disable_columns_truncate(void) @@ -248,7 +251,9 @@ static int get_local_locks(struct list_head *locks) * separated by ' ' - check /fs/locks.c */ switch (i) { - case 0: /* ignore */ + case 0: /* ID: */ + tok[strlen(tok) - 1] = '\0'; + l->id = strtos32_or_err(tok, _("failed to parse ID")); break; case 1: /* posix, flock, etc */ if (strcmp(tok, "->") == 0) { /* optional field */ @@ -306,22 +311,6 @@ static int get_local_locks(struct list_head *locks) free(szstr); } - if (pid && pid != l->pid) { - /* - * It's easier to just parse the file then decide if - * it should be added to the list - otherwise just - * get rid of stored data - */ - free(l->path); - free(l->size); - free(l->mode); - free(l->cmdname); - free(l->type); - free(l); - - continue; - } - list_add(&l->locks, locks); } @@ -374,7 +363,21 @@ static void rem_lock(struct lock *lock) free(lock); } -static void add_tt_line(struct tt *tt, struct lock *l) +static pid_t get_blocker(int id, struct list_head *locks) +{ + struct list_head *p; + + list_for_each(p, locks) { + struct lock *l = list_entry(p, struct lock, locks); + + if (l->id == id && !l->blocked) + return l->pid; + } + + return 0; +} + +static void add_tt_line(struct tt *tt, struct lock *l, struct list_head *locks) { int i; struct tt_line *line; @@ -425,6 +428,13 @@ static void add_tt_line(struct tt *tt, struct lock *l) case COL_PATH: xasprintf(&str, "%s", l->path ? l->path : notfnd); break; + case COL_BLOCKER: + { + pid_t bl = l->blocked && l->id ? + get_blocker(l->id, locks) : 0; + if (bl) + xasprintf(&str, "%d", (int) bl); + } default: break; } @@ -456,10 +466,20 @@ static int show_locks(struct list_head *locks, int tt_flags) } } + /* prepare data for output */ + list_for_each(p, locks) { + struct lock *l = list_entry(p, struct lock, locks); + + if (pid && pid != l->pid) + continue; + + add_tt_line(tt, l, locks); + } + + /* destroy the list */ list_for_each_safe(p, pnext, locks) { - struct lock *lock = list_entry(p, struct lock, locks); - add_tt_line(tt, lock); - rem_lock(lock); + struct lock *l = list_entry(p, struct lock, locks); + rem_lock(l); } tt_print_table(tt); -- 2.47.2