The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=039d1496b0790a27cbec18e06b9494bf41254019

commit 039d1496b0790a27cbec18e06b9494bf41254019
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2022-04-03 14:42:03 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2022-04-09 21:47:49 +0000

    libprocstat: add procstat_getadvlock(3)
    
    For now, only for sysctl target.  This is not a new situation, for
    instance kstacks also work for sysctl only.
    
    Reviewed by:    markj, rmacklem
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D34756
---
 lib/libprocstat/Symbol.map    |   5 ++
 lib/libprocstat/libprocstat.c | 135 ++++++++++++++++++++++++++++++++++++++++++
 lib/libprocstat/libprocstat.h |  26 ++++++++
 3 files changed, 166 insertions(+)

diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index cea784900536..3d0f37b5981e 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -44,3 +44,8 @@ FBSD_1.6 {
        procstat_get_pts_info;
        procstat_get_vnode_info;
 };
+
+FBSD_1.7 {
+        procstat_getadvlock;
+        procstat_freeadvlock;
+};
\ No newline at end of file
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 850d37598423..5948bf72230d 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -2644,3 +2644,138 @@ procstat_freekstack(struct procstat *procstat __unused,
 
        free(kkstp);
 }
+
+static struct advlock_list *
+procstat_getadvlock_sysctl(struct procstat *procstat __unused)
+{
+       struct advlock_list *res;
+       struct advlock *a;
+       void *buf;
+       char *c;
+       struct kinfo_lockf *kl;
+       size_t buf_len;
+       int error;
+       static const int kl_name[] = { CTL_KERN, KERN_LOCKF };
+
+       res = malloc(sizeof(*res));
+       if (res == NULL)
+               return (NULL);
+       STAILQ_INIT(res);
+       buf = NULL;
+
+       buf_len = 0;
+       error = sysctl(kl_name, nitems(kl_name), NULL, &buf_len, NULL, 0);
+       if (error != 0) {
+               warn("sysctl KERN_LOCKF size");
+               goto fail;
+       }
+       buf_len *= 2;
+       buf = malloc(buf_len);
+       if (buf == NULL) {
+               warn("malloc");
+               goto fail;
+       }
+       error = sysctl(kl_name, nitems(kl_name), buf, &buf_len, NULL, 0);
+       if (error != 0) {
+               warn("sysctl KERN_LOCKF data");
+               goto fail;
+       }
+
+       for (c = buf; (char *)c < (char *)buf + buf_len;
+           c += kl->kl_structsize) {
+               kl = (struct kinfo_lockf *)(void *)c;
+               if (sizeof(*kl) < (size_t)kl->kl_structsize) {
+                       warn("ABI broken");
+                       goto fail;
+               }
+               a = malloc(sizeof(*a));
+               if (a == NULL) {
+                       warn("malloc advlock");
+                       goto fail;
+               }
+               switch (kl->kl_rw) {
+               case KLOCKF_RW_READ:
+                       a->rw = PS_ADVLOCK_RO;
+                       break;
+               case KLOCKF_RW_WRITE:
+                       a->rw = PS_ADVLOCK_RW;
+                       break;
+               default:
+                       warn("ABI broken");
+                       free(a);
+                       goto fail;
+               }
+               switch (kl->kl_type) {
+               case KLOCKF_TYPE_FLOCK:
+                       a->type = PS_ADVLOCK_TYPE_FLOCK;
+                       break;
+               case KLOCKF_TYPE_PID:
+                       a->type = PS_ADVLOCK_TYPE_PID;
+                       break;
+               case KLOCKF_TYPE_REMOTE:
+                       a->type = PS_ADVLOCK_TYPE_REMOTE;
+                       break;
+               default:
+                       warn("ABI broken");
+                       free(a);
+                       goto fail;
+               }
+               a->pid = kl->kl_pid;
+               a->sysid = kl->kl_sysid;
+               a->file_fsid = kl->kl_file_fsid;
+               a->file_rdev = kl->kl_file_rdev;
+               a->file_fileid = kl->kl_file_fileid;
+               a->start = kl->kl_start;
+               a->len = kl->kl_len;
+               if (kl->kl_path[0] != '\0') {
+                       a->path = strdup(kl->kl_path);
+                       if (a->path == NULL) {
+                               warn("malloc");
+                               free(a);
+                               goto fail;
+                       }
+               } else
+                       a->path = NULL;
+               STAILQ_INSERT_TAIL(res, a, next);
+       }
+
+       free(buf);
+       return (res);
+
+fail:
+       free(buf);
+       procstat_freeadvlock(procstat, res);
+       return (NULL);
+}
+
+struct advlock_list *
+procstat_getadvlock(struct procstat *procstat)
+{
+       switch(procstat->type) {
+       case PROCSTAT_KVM:
+               warnx("kvm method is not supported");
+               return (NULL);
+       case PROCSTAT_SYSCTL:
+               return (procstat_getadvlock_sysctl(procstat));
+       case PROCSTAT_CORE:
+               warnx("core method is not supported");
+               return (NULL);
+       default:
+               warnx("unknown access method: %d", procstat->type);
+               return (NULL);
+       }
+}
+
+void
+procstat_freeadvlock(struct procstat *procstat __unused,
+    struct advlock_list *lst)
+{
+       struct advlock *a, *a1;
+
+       STAILQ_FOREACH_SAFE(a, lst, next, a1) {
+               free(__DECONST(char *, a->path));
+               free(a);
+       }
+       free(lst);
+}
+
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 0624ec5289d4..8736870d163e 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -168,8 +168,33 @@ struct sockstat {
 
 STAILQ_HEAD(filestat_list, filestat);
 
+struct advlock {
+       int             rw;                     /* PS_ADVLOCK_RO/RW */
+       int             type;                   /* PS_ADVLOCK_TYPE_ */
+       int             pid;
+       int             sysid;
+       uint64_t        file_fsid;
+       uint64_t        file_rdev;
+       uint64_t        file_fileid;
+       off_t           start;
+       off_t           len;                    /* len == 0 till the EOF */
+       const char      *path;
+       STAILQ_ENTRY(advlock)   next;
+};
+
+#define        PS_ADVLOCK_RO           0x01
+#define        PS_ADVLOCK_RW           0x02
+
+#define        PS_ADVLOCK_TYPE_FLOCK   0x01
+#define        PS_ADVLOCK_TYPE_PID     0x02
+#define        PS_ADVLOCK_TYPE_REMOTE  0x03
+
+STAILQ_HEAD(advlock_list, advlock);
+
 __BEGIN_DECLS
 void   procstat_close(struct procstat *procstat);
+void   procstat_freeadvlock(struct procstat *procstat,
+    struct advlock_list *advlocks);
 void   procstat_freeargv(struct procstat *procstat);
 #ifndef ZFS
 void   procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv);
@@ -185,6 +210,7 @@ void        procstat_freeptlwpinfo(struct procstat 
*procstat,
     struct ptrace_lwpinfo *pl);
 void   procstat_freevmmap(struct procstat *procstat,
     struct kinfo_vmentry *vmmap);
+struct advlock_list    *procstat_getadvlock(struct procstat *procstat);
 struct filestat_list   *procstat_getfiles(struct procstat *procstat,
     struct kinfo_proc *kp, int mmapped);
 struct kinfo_proc      *procstat_getprocs(struct procstat *procstat,

Reply via email to