diff options
author | Amitay Isaacs <amitay@gmail.com> | 2012-06-06 11:50:25 +1000 |
---|---|---|
committer | Amitay Isaacs <amitay@gmail.com> | 2012-10-20 02:48:44 +1100 |
commit | 1011d10a515f165c29fb5470ad04acf856a6217a (patch) | |
tree | 743782c10fd8cff7c00142b4fa88e2e3b733697f /ctdb/common | |
parent | ef79dc012e8867116ea71880940fe531d41d2649 (diff) | |
download | samba-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.c | 17 | ||||
-rw-r--r-- | ctdb/common/system_freebsd.c | 18 | ||||
-rw-r--r-- | ctdb/common/system_gnu.c | 18 | ||||
-rw-r--r-- | ctdb/common/system_kfreebsd.c | 18 | ||||
-rw-r--r-- | ctdb/common/system_linux.c | 179 |
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; +} |