COL_START,
COL_END,
COL_PATH,
- COL_BLOCKER
+ COL_BLOCKER,
+ COL_HOLDERS,
};
/* column names */
[COL_START] = { "START", 10, SCOLS_FL_RIGHT, N_("relative byte offset of the lock")},
[COL_END] = { "END", 10, SCOLS_FL_RIGHT, N_("ending offset of the lock")},
[COL_PATH] = { "PATH", 0, SCOLS_FL_TRUNC, N_("path of the locked file")},
- [COL_BLOCKER] = { "BLOCKER", 0, SCOLS_FL_RIGHT, N_("PID of the process blocking the lock") }
+ [COL_BLOCKER] = { "BLOCKER", 0, SCOLS_FL_RIGHT, N_("PID of the process blocking the lock") },
+ [COL_HOLDERS] = { "HOLDERS", 0, SCOLS_FL_WRAP, N_("HOLDERS of the lock") },
};
static int columns[ARRAY_SIZE(infos) * 2];
const char *cmdname;
};
-static bool is_co_holder(struct lock *l, struct lock *m)
+static bool is_holder(struct lock *l, struct lock *m)
{
return (l->start == m->start &&
l->end == m->end &&
list_for_each(p, &(*head)->chain) {
struct lock *m = list_entry(p, struct lock, locks);
- if (is_co_holder(l, m)) {
+ if (is_holder(l, m)) {
/* size and id can be ignored. */
l->pid = m->pid;
l->cmdname = xstrdup(m->cmdname);
return 0;
}
-static void add_scols_line(struct libscols_table *table, struct lock *l, struct list_head *locks)
+static void xstrcoholder(char **str, struct lock *l)
+{
+ xstrfappend(str, "%d,%s,%d",
+ l->pid, l->cmdname, l->fd);
+}
+
+static void add_scols_line(struct libscols_table *table, struct lock *l, struct list_head *locks, void *pid_locks)
{
size_t i;
struct libscols_line *line;
xasprintf(&str, "%d", (int) bl);
break;
}
+ case COL_HOLDERS:
+ {
+ struct lock_tnode tmp = { .dev = l->dev, .inode = l->inode, };
+ struct lock_tnode **head = tfind(&tmp, pid_locks, lock_tnode_compare);
+ struct list_head *p;
+
+ if (!head)
+ break;
+
+ list_for_each(p, &(*head)->chain) {
+ struct lock *m = list_entry(p, struct lock, locks);
+
+ if (!is_holder(l, m))
+ continue;
+
+ if (str)
+ xstrputc(&str, '\n');
+ xstrcoholder(&str, m);
+ }
+ break;
+ }
default:
break;
}
free(node);
}
-static int show_locks(struct list_head *locks, pid_t target_pid)
+static int show_locks(struct list_head *locks, pid_t target_pid, void *pid_locks)
{
int rc = 0;
size_t i;
if (!cl)
err(EXIT_FAILURE, _("failed to allocate output column"));
+ if (col->flags & SCOLS_FL_WRAP) {
+ scols_column_set_wrapfunc(cl,
+ scols_wrapnl_chunksize,
+ scols_wrapnl_nextchunk,
+ NULL);
+ scols_column_set_safechars(cl, "\n");
+ }
+
if (json) {
int id = get_column_id(i);
case COL_M:
scols_column_set_json_type(cl, SCOLS_JSON_BOOLEAN);
break;
+ case COL_HOLDERS:
+ scols_column_set_json_type(cl, SCOLS_JSON_ARRAY_STRING);
+ break;
default:
scols_column_set_json_type(cl, SCOLS_JSON_STRING);
break;
if (target_pid && target_pid != l->pid)
continue;
- add_scols_line(table, l, locks);
+ add_scols_line(table, l, locks, pid_locks);
}
scols_print_table(table);
rc = get_proc_locks(&proc_locks, add_to_list, &pid_locks);
if (!rc && !list_empty(&proc_locks))
- rc = show_locks(&proc_locks, target_pid);
+ rc = show_locks(&proc_locks, target_pid, &pid_locks);
tdestroy(pid_locks, rem_tnode);
rem_locks(&proc_locks);