common: Add routines to get process and lock information
authorAmitay Isaacs <amitay@gmail.com>
Wed, 6 Jun 2012 01:50:25 +0000 (11:50 +1000)
committerAmitay Isaacs <amitay@gmail.com>
Fri, 19 Oct 2012 15:48:44 +0000 (02:48 +1100)
Currently these functions are implemented only for Linux.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
(This used to be ctdb commit be4051326b0c6a0fd301561af10fd15a0e90023b)

ctdb/common/system_aix.c
ctdb/common/system_freebsd.c
ctdb/common/system_gnu.c
ctdb/common/system_kfreebsd.c
ctdb/common/system_linux.c
ctdb/include/ctdb_private.h

index 388e943de0b79f735218d4c7e46745744e9c088c..16b627ca47998e017ae0f4be81197ab2bf855db7 100644 (file)
@@ -373,3 +373,20 @@ int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
        return ret;
 }
 
+char *ctdb_get_process_name(pid_t pid)
+{
+       /* FIXME: not implemented */
+       return NULL;
+}
+
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info)
+{
+       /* FIXME: not implemented */
+       return false;
+}
+
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid)
+{
+       /* FIXME: not implemented */
+       return false;
+}
index ed30f8ccb723caea29274c247fff7a74997f8c4e..37f1c74b451cb2f1e9eb0b5c715f0cdf214cf9aa 100644 (file)
@@ -368,3 +368,21 @@ int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
        /* FIXME not implemented */
        return 1;
 }
+
+char *ctdb_get_process_name(pid_t pid)
+{
+       /* FIXME: not implemented */
+       return NULL;
+}
+
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info)
+{
+       /* FIXME: not implemented */
+       return false;
+}
+
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid)
+{
+       /* FIXME: not implemented */
+       return false;
+}
index 7b8af340ecb6607aceeebd53068abbdeb46362f4..8a3b5b1e54089ea321f7391a846cf93757009f61 100644 (file)
@@ -361,3 +361,21 @@ int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
        /* FIXME not implemented */
        return 1;
 }
+
+char *ctdb_get_process_name(pid_t pid)
+{
+       /* FIXME: not implemented */
+       return NULL;
+}
+
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info)
+{
+       /* FIXME: not implemented */
+       return false;
+}
+
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid)
+{
+       /* FIXME: not implemented */
+       return false;
+}
index 9e2aa07112b7baf294e47b1006ae11dbd2d8446f..55958651866b142f0cbaec6a998b12c17e00d79a 100644 (file)
@@ -361,3 +361,21 @@ int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
        /* FIXME not implemented */
        return 1;
 }
+
+char *ctdb_get_process_name(pid_t pid)
+{
+       /* FIXME: not implemented */
+       return NULL;
+}
+
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info)
+{
+       /* FIXME: not implemented */
+       return false;
+}
+
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid)
+{
+       /* FIXME: not implemented */
+       return false;
+}
index 21f5d6c814538b9f5c3dd2017bcd7d930d6ae3c9..9d4d4ec6c92e1a32d4dba6857fdf0a48bd9c4680 100644 (file)
@@ -574,3 +574,182 @@ int ctdb_get_peer_pid(const int fd, pid_t *peer_pid)
        return ret;
 }
 
+/*
+ * Find the process name from process ID
+ */
+char *ctdb_get_process_name(pid_t pid)
+{
+       char path[32];
+       char buf[PATH_MAX];
+       char *ptr;
+       int n;
+
+       snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+       n = readlink(path, buf, sizeof(buf));
+       if (n < 0) {
+               return NULL;
+       }
+
+       /* Remove any extra fields */
+       buf[n] = '\0';
+       ptr = strtok(buf, " ");
+       return strdup(ptr);
+}
+
+
+/*
+ * Parsing a line from /proc/locks,
+ */
+static bool parse_proc_locks_line(char *line, pid_t *pid,
+                                 struct ctdb_lock_info *curlock)
+{
+       char *ptr, *saveptr;
+
+       /* output of /proc/locks
+        *
+        * lock assigned
+        * 1: POSIX  ADVISORY  WRITE 25945 fd:00:6424820 212 212
+        *
+        * lock waiting
+        * 1: -> POSIX  ADVISORY  WRITE 25946 fd:00:6424820 212 212
+        */
+
+       /* Id: */
+       ptr = strtok_r(line, " ", &saveptr);
+       if (ptr == NULL) return false;
+
+       /* -> */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+       if (strcmp(ptr, "->") == 0) {
+               curlock->waiting = true;
+               ptr = strtok_r(NULL, " ", &saveptr);
+       } else {
+               curlock->waiting = false;
+       }
+
+       /* POSIX */
+       if (ptr == NULL || strcmp(ptr, "POSIX") != 0) {
+               return false;
+       }
+
+       /* ADVISORY */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+
+       /* WRITE */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+       if (strcmp(ptr, "READ") == 0) {
+               curlock->read_only = true;
+       } else if (strcmp(ptr, "WRITE") == 0) {
+               curlock->read_only = false;
+       } else {
+               return false;
+       }
+
+       /* PID */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+       *pid = atoi(ptr);
+
+       /* MAJOR:MINOR:INODE */
+       ptr = strtok_r(NULL, " :", &saveptr);
+       if (ptr == NULL) return false;
+       ptr = strtok_r(NULL, " :", &saveptr);
+       if (ptr == NULL) return false;
+       ptr = strtok_r(NULL, " :", &saveptr);
+       if (ptr == NULL) return false;
+       curlock->inode = atol(ptr);
+
+       /* START OFFSET */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+       curlock->start = atol(ptr);
+
+       /* END OFFSET */
+       ptr = strtok_r(NULL, " ", &saveptr);
+       if (ptr == NULL) return false;
+       if (strncmp(ptr, "EOF", 3) == 0) {
+               curlock->end = (off_t)-1;
+       } else {
+               curlock->end = atol(ptr);
+       }
+
+       return true;
+}
+
+/*
+ * Find information of lock being waited on for given process ID
+ */
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info)
+{
+       FILE *fp;
+       struct ctdb_lock_info curlock;
+       pid_t pid;
+       char buf[1024];
+       char *ptr;
+       bool status = false;
+
+       if ((fp = fopen("/proc/locks", "r")) == NULL) {
+               DEBUG(DEBUG_ERR, ("Failed to read locks information"));
+               return false;
+       }
+       while ((ptr = fgets(buf, sizeof(buf), fp)) != NULL) {
+               if (! parse_proc_locks_line(buf, &pid, &curlock)) {
+                       continue;
+               }
+               if (pid == req_pid && curlock.waiting) {
+                       *lock_info = curlock;
+                       status = true;
+                       break;
+               }
+       }
+       fclose(fp);
+
+       return status;
+}
+
+/*
+ * Find process ID which holds an overlapping byte lock for required
+ * inode and byte range.
+ */
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid)
+{
+       FILE *fp;
+       struct ctdb_lock_info curlock;
+       pid_t pid;
+       char buf[1024];
+       char *ptr;
+       bool status = false;
+
+       if ((fp = fopen("/proc/locks", "r")) == NULL) {
+               DEBUG(DEBUG_ERR, ("Failed to read locks information"));
+               return false;
+       }
+       while ((ptr = fgets(buf, sizeof(buf), fp)) != NULL) {
+               if (! parse_proc_locks_line(buf, &pid, &curlock)) {
+                       continue;
+               }
+
+               if (curlock.waiting) {
+                       continue;
+               }
+
+               if (curlock.inode != reqlock->inode) {
+                       continue;
+               }
+
+               if (curlock.start > reqlock->end ||
+                   curlock.end < reqlock->start) {
+                       /* Outside the required range */
+                       continue;
+               }
+               *blocker_pid = pid;
+               status = true;
+               break;
+       }
+       fclose(fp);
+
+       return status;
+}
index 7e86b10528195552221d649d2a829da0a6a0a0a2..5689c58b2f69c409bc5678b18d988f829948e056 100644 (file)
@@ -1182,6 +1182,18 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
                      const ctdb_sock_addr *src,
                      uint32_t seq, uint32_t ack, int rst);
 
+/* Details of a byte range lock */
+struct ctdb_lock_info {
+       ino_t inode;
+       off_t start, end;
+       bool waiting;
+       bool read_only;
+};
+
+char *ctdb_get_process_name(pid_t pid);
+bool ctdb_get_lock_info(pid_t req_pid, struct ctdb_lock_info *lock_info);
+bool ctdb_get_blocker_pid(struct ctdb_lock_info *reqlock, pid_t *blocker_pid);
+
 int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses);
 int ctdb_set_single_public_ip(struct ctdb_context *ctdb,
                              const char *iface,