diff options
author | kib <kib@FreeBSD.org> | 2011-10-05 16:56:06 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2011-10-05 16:56:06 +0000 |
commit | 87f923aeea5b3c0d34da4ce543dcc1600e666a71 (patch) | |
tree | c2df6a9e42dc6e1e31e1ec425f1a144c7d62eb6b /sys/kern/sys_pipe.c | |
parent | 12b63c734fff294408d34cb8d31a23f2fd8e1967 (diff) | |
download | FreeBSD-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/sys_pipe.c')
-rw-r--r-- | sys/kern/sys_pipe.c | 28 |
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*/ |