library: normalize recently added namespaces interface

While 'invisible' thread subdirectories are accessible
under /proc/ with stat/opendir calls, they have always
been treated as non-existent, as is true with readdir.

This patch trades the /proc/#/ns access convention for
the more proper /proc/#/task/#/ns approach when thread
access is desired. In addition some namespace code has
been simplified and made slightly more efficient given
the calloc nature of proc_t acquisition and its reuse.

Reference(s):
commit a01ee3c0b3

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2013-11-10 00:00:00 -06:00 committed by Craig Small
parent 89c2f28e39
commit 583cdaca1a
2 changed files with 21 additions and 32 deletions

View File

@ -457,19 +457,6 @@ static void oomadj2proc(const char* S, proc_t *restrict P)
#endif #endif
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
static ino_t _ns2proc(unsigned pid, const char *ns)
{
struct stat s;
char filename[40];
snprintf(filename, sizeof(filename), "/proc/%i/ns/%s", pid, ns);
if (stat(filename, &s) == -1)
return 0;
return s.st_ino;
}
static const char *ns_names[] = { static const char *ns_names[] = {
[IPCNS] = "ipc", [IPCNS] = "ipc",
[MNTNS] = "mnt", [MNTNS] = "mnt",
@ -494,11 +481,20 @@ int get_ns_id(const char *name) {
return -1; return -1;
} }
static void ns2proc(proc_t *restrict P) { static void ns2proc(const char *directory, proc_t *restrict p) {
char path[PROCPATHLEN];
struct stat sb;
int i; int i;
for (i = 0; i < NUM_NS; i++) for (i = 0; i < NUM_NS; i++) {
P->ns[i] = _ns2proc(P->tgid, ns_names[i]); snprintf(path, sizeof(path), "%s/ns/%s", directory, ns_names[i]);
if (0 == stat(path, &sb))
p->ns[i] = (long)sb.st_ino;
#if 0
else // this allows a caller to distinguish
p->ns[i] = -errno; // between the ENOENT or EACCES errors
#endif
}
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@ -802,7 +798,6 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
static struct stat sb; // stat() buffer static struct stat sb; // stat() buffer
char *restrict const path = PT->path; char *restrict const path = PT->path;
unsigned flags = PT->flags; unsigned flags = PT->flags;
int i;
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */ if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
goto next_proc; goto next_proc;
@ -890,11 +885,8 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
} }
#endif #endif
if (unlikely(flags & PROC_FILLNS)) // read /proc/#/ns/* if (unlikely(flags & PROC_FILLNS)) // read /proc/#/ns/*
ns2proc(p); ns2proc(path, p);
else
for (i = 0; i < NUM_NS; i++)
p->ns[i] = 0;
return p; return p;
next_proc: next_proc:
@ -914,7 +906,6 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
static struct utlbuf_s ub = { NULL, 0 }; // buf for stat,statm,status static struct utlbuf_s ub = { NULL, 0 }; // buf for stat,statm,status
static struct stat sb; // stat() buffer static struct stat sb; // stat() buffer
unsigned flags = PT->flags; unsigned flags = PT->flags;
int i;
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */ if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
goto next_task; goto next_task;
@ -1027,11 +1018,9 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
oomadj2proc(ub.buf, t); oomadj2proc(ub.buf, t);
} }
#endif #endif
if (unlikely(flags & PROC_FILLNS))
ns2proc(t); if (unlikely(flags & PROC_FILLNS)) // read /proc/#/task/#/ns/*
else ns2proc(path, t);
for (i = 0; i < NUM_NS; i++)
t->ns[i] = 0;
return t; return t;
next_task: next_task:

View File

@ -31,14 +31,14 @@ EXTERN_C_BEGIN
// neither tgid nor tid seemed correct. (in other words, FIXME) // neither tgid nor tid seemed correct. (in other words, FIXME)
#define XXXID tid #define XXXID tid
#define NUM_NS 6
enum ns_type { enum ns_type {
IPCNS = 0, IPCNS = 0,
MNTNS, MNTNS,
NETNS, NETNS,
PIDNS, PIDNS,
USERNS, USERNS,
UTSNS UTSNS,
NUM_NS // total namespaces (fencepost)
}; };
extern const char *get_ns_name(int id); extern const char *get_ns_name(int id);
extern int get_ns_id(const char *name); extern int get_ns_id(const char *name);
@ -169,8 +169,8 @@ typedef struct proc_t {
oom_score, // oom_score (badness for OOM killer) oom_score, // oom_score (badness for OOM killer)
oom_adj; // oom_adj (adjustment to OOM score) oom_adj; // oom_adj (adjustment to OOM score)
#endif #endif
ino_t long
ns[NUM_NS]; // ns/* inode number of /proc/<pid>/ns/* ns[NUM_NS]; // (ns subdir) inode number of namespaces
} proc_t; } proc_t;
// PROCTAB: data structure holding the persistent information readproc needs // PROCTAB: data structure holding the persistent information readproc needs