[PATCH] pipe: export size and blocks via system call fstat(2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



export size and blocks via system call fstat(2)

pipe or fifo doesn't support fstat(2). This patch makes it possible to check the
amount of data buffered in a pipe or fifo, and the pages used to store this
data via fstat(2).

Signed-off-by: Changli Gao <xiaosuo@xxxxxxxxx>
----
 fs/inode.c         |    5 +++--
 fs/pipe.c          |   51 ++++++++++++++++++++++++++++++++++++++++-----------
 include/linux/fs.h |    1 +
 3 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index 258ec22..850ff89 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1598,9 +1598,10 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 	} else if (S_ISBLK(mode)) {
 		inode->i_fop = &def_blk_fops;
 		inode->i_rdev = rdev;
-	} else if (S_ISFIFO(mode))
+	} else if (S_ISFIFO(mode)) {
+		inode->i_op = &pipe_iops;
 		inode->i_fop = &def_fifo_fops;
-	else if (S_ISSOCK(mode))
+	} else if (S_ISSOCK(mode))
 		inode->i_fop = &bad_sock_fops;
 	else
 		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
diff --git a/fs/pipe.c b/fs/pipe.c
index 37ba29f..3961fcf 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -625,25 +625,33 @@ bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
 	return -EBADF;
 }
 
-static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static int __pipe_get_size(struct inode *inode)
 {
-	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct pipe_inode_info *pipe;
 	int count, buf, nrbufs;
 
+	pipe = inode->i_pipe;
+	count = 0;
+	buf = pipe->curbuf;
+	nrbufs = pipe->nrbufs;
+	while (--nrbufs >= 0) {
+		count += pipe->bufs[buf].len;
+		buf = (buf+1) & (PIPE_BUFFERS-1);
+	}
+
+	return count;
+}
+
+static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = filp->f_path.dentry->d_inode;
+	int count;
+
 	switch (cmd) {
 		case FIONREAD:
 			mutex_lock(&inode->i_mutex);
-			pipe = inode->i_pipe;
-			count = 0;
-			buf = pipe->curbuf;
-			nrbufs = pipe->nrbufs;
-			while (--nrbufs >= 0) {
-				count += pipe->bufs[buf].len;
-				buf = (buf+1) & (PIPE_BUFFERS-1);
-			}
+			count = __pipe_get_size(inode);
 			mutex_unlock(&inode->i_mutex);
-
 			return put_user(count, (int __user *)arg);
 		default:
 			return -EINVAL;
@@ -934,6 +942,7 @@ static struct inode * get_pipe_inode(void)
 	inode->i_pipe = pipe;
 
 	pipe->readers = pipe->writers = 1;
+	inode->i_op = &pipe_iops;
 	inode->i_fop = &rdwr_pipefifo_fops;
 
 	/*
@@ -1112,6 +1121,26 @@ static struct file_system_type pipe_fs_type = {
 	.kill_sb	= kill_anon_super,
 };
 
+static int pipe_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+
+	generic_fillattr(inode, stat);
+	mutex_lock(&inode->i_mutex);
+	if (inode->i_pipe) {
+		stat->blocks = inode->i_pipe->nrbufs * (PAGE_SIZE / 512);
+		stat->size = __pipe_get_size(inode);
+	}
+	mutex_unlock(&inode->i_mutex);
+
+	return 0;
+}
+
+const struct inode_operations pipe_iops = {
+	.getattr	= pipe_getattr,
+};
+
 static int __init init_pipe_fs(void)
 {
 	int err = register_filesystem(&pipe_fs_type);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index eb86433..89103b9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1973,6 +1973,7 @@ extern const struct file_operations def_blk_fops;
 extern const struct file_operations def_chr_fops;
 extern const struct file_operations bad_sock_fops;
 extern const struct file_operations def_fifo_fops;
+extern const struct inode_operations pipe_iops;
 #ifdef CONFIG_BLOCK
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux