summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-10-05 16:56:06 +0000
committerkib <kib@FreeBSD.org>2011-10-05 16:56:06 +0000
commit87f923aeea5b3c0d34da4ce543dcc1600e666a71 (patch)
treec2df6a9e42dc6e1e31e1ec425f1a144c7d62eb6b /sys/kern
parent12b63c734fff294408d34cb8d31a23f2fd8e1967 (diff)
downloadFreeBSD-src-87f923aeea5b3c0d34da4ce543dcc1600e666a71.zip
FreeBSD-src-87f923aeea5b3c0d34da4ce543dcc1600e666a71.tar.gz
Supply unique (st_dev, st_ino) value pair for the fstat(2) done on the pipes.
Reviewed by: jhb, Peter Jeremy <peterjeremy acm org> MFC after: 2 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/sys_pipe.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index b7ae521..13e056f 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
@@ -224,6 +225,8 @@ static int pipe_zone_init(void *mem, int size, int flags);
static void pipe_zone_fini(void *mem, int size);
static uma_zone_t pipe_zone;
+static struct unrhdr *pipeino_unr;
+static dev_t pipedev_ino;
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, pipeinit, NULL);
@@ -235,6 +238,10 @@ pipeinit(void *dummy __unused)
pipe_zone_ctor, NULL, pipe_zone_init, pipe_zone_fini,
UMA_ALIGN_PTR, 0);
KASSERT(pipe_zone != NULL, ("pipe_zone not initialized"));
+ pipeino_unr = new_unrhdr(1, INT32_MAX, NULL);
+ KASSERT(pipeino_unr != NULL, ("pipe fake inodes not initialized"));
+ pipedev_ino = devfs_alloc_cdp_inode();
+ KASSERT(pipedev_ino > 0, ("pipe dev inode not initialized"));
}
static int
@@ -562,6 +569,12 @@ pipe_create(pipe, backing)
/* If we're not backing this pipe, no need to do anything. */
error = 0;
}
+ if (error == 0) {
+ pipe->pipe_ino = alloc_unr(pipeino_unr);
+ if (pipe->pipe_ino == -1)
+ /* pipeclose will clear allocated kva */
+ error = ENOMEM;
+ }
return (error);
}
@@ -1408,9 +1421,10 @@ pipe_stat(fp, ub, active_cred, td)
ub->st_ctim = pipe->pipe_ctime;
ub->st_uid = fp->f_cred->cr_uid;
ub->st_gid = fp->f_cred->cr_gid;
+ ub->st_dev = pipedev_ino;
+ ub->st_ino = pipe->pipe_ino;
/*
- * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, st_gen.
- * XXX (st_dev, st_ino) should be unique.
+ * Left as 0: st_nlink, st_rdev, st_flags, st_gen.
*/
return (0);
}
@@ -1463,6 +1477,7 @@ pipeclose(cpipe)
{
struct pipepair *pp;
struct pipe *ppipe;
+ ino_t ino;
KASSERT(cpipe != NULL, ("pipeclose: cpipe == NULL"));
@@ -1521,6 +1536,12 @@ pipeclose(cpipe)
knlist_destroy(&cpipe->pipe_sel.si_note);
/*
+ * Postpone the destroy of the fake inode number allocated for
+ * our end, until pipe mtx is unlocked.
+ */
+ ino = cpipe->pipe_ino;
+
+ /*
* If both endpoints are now closed, release the memory for the
* pipe pair. If not, unlock.
*/
@@ -1532,6 +1553,9 @@ pipeclose(cpipe)
uma_zfree(pipe_zone, cpipe->pipe_pair);
} else
PIPE_UNLOCK(cpipe);
+
+ if (ino > 0)
+ free_unr(pipeino_unr, cpipe->pipe_ino);
}
/*ARGSUSED*/
OpenPOWER on IntegriCloud