summaryrefslogtreecommitdiffstats
path: root/ctdb/common
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2012-06-06 11:50:25 +1000
committerAmitay Isaacs <amitay@gmail.com>2012-10-20 02:48:44 +1100
commit1011d10a515f165c29fb5470ad04acf856a6217a (patch)
tree743782c10fd8cff7c00142b4fa88e2e3b733697f /ctdb/common
parentef79dc012e8867116ea71880940fe531d41d2649 (diff)
downloadsamba-1011d10a515f165c29fb5470ad04acf856a6217a.tar.gz
samba-1011d10a515f165c29fb5470ad04acf856a6217a.tar.xz
samba-1011d10a515f165c29fb5470ad04acf856a6217a.zip
common: Add routines to get process and lock information
Currently these functions are implemented only for Linux. Signed-off-by: Amitay Isaacs <amitay@gmail.com> (This used to be ctdb commit be4051326b0c6a0fd301561af10fd15a0e90023b)
Diffstat (limited to 'ctdb/common')
-rw-r--r--ctdb/common/system_aix.c17
-rw-r--r--ctdb/common/system_freebsd.c18
-rw-r--r--ctdb/common/system_gnu.c18
-rw-r--r--ctdb/common/system_kfreebsd.c18
-rw-r--r--ctdb/common/system_linux.c179
5 files changed, 250 insertions, 0 deletions
diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c
index 388e943de0b..16b627ca479 100644
--- a/ctdb/common/system_aix.c
+++ b/ctdb/common/system_aix.c
@@ -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;
+}
diff --git a/ctdb/common/system_freebsd.c b/ctdb/common/system_freebsd.c
index ed30f8ccb72..37f1c74b451 100644
--- a/ctdb/common/system_freebsd.c
+++ b/ctdb/common/system_freebsd.c
@@ -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;
+}
diff --git a/ctdb/common/system_gnu.c b/ctdb/common/system_gnu.c
index 7b8af340ecb..8a3b5b1e540 100644
--- a/ctdb/common/system_gnu.c
+++ b/ctdb/common/system_gnu.c
@@ -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;
+}
diff --git a/ctdb/common/system_kfreebsd.c b/ctdb/common/system_kfreebsd.c
index 9e2aa07112b..55958651866 100644
--- a/ctdb/common/system_kfreebsd.c
+++ b/ctdb/common/system_kfreebsd.c
@@ -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;
+}
diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c
index 21f5d6c8145..9d4d4ec6c92 100644
--- a/ctdb/common/system_linux.c
+++ b/ctdb/common/system_linux.c
@@ -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;
+}