All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC] ubifs: introduce an ioctl to get UBIFS files compressed size
@ 2015-03-25 13:00 ` hujianyang
  0 siblings, 0 replies; 2+ messages in thread
From: hujianyang @ 2015-03-25 13:00 UTC (permalink / raw)
  To: Artem Bityutskiy, Richard Weinberger
  Cc: markus.heininger, Andreas Dilger, linux-mtd, linux-fsdevel, David Sterba

As discussed in last mail, I don't think record compressed size in
*ubifs_ino_inode* could suffer power cut easily, rebuild the records
of each file may increase the mount time and we may need to write
more meta data to keep the consistency of compressed size. And I
don't think *fiemap* is a good interface either, because it is can't
report compressed size at present.

http://lists.infradead.org/pipermail/linux-mtd/2015-February/057978.html

So I tried another way, introduce a new ioctl which scan the tnc_tree
to get the compressed size in each *ubifs_data_node* of the request
file.

Similar with:
https://patchwork.kernel.org/patch/117782/

But This isn't a good solution in performance side. Just want to show
my code to push the achievement of this feature.

Any test or any advisement is welcomed.

Thanks everyone~!

Signed-off-by: hujianyang <hujianyang@huawei.com>
---
 fs/ubifs/ioctl.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/ubifs.h |    2 +
 2 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index 648b143..a148e32 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -144,6 +144,62 @@ out_unlock:
 	return err;
 }

+static long ubifs_ioctl_compsize(struct file *file, void __user *arg)
+{
+	struct inode *inode = file_inode(file);
+	struct ubifs_inode *ui = ubifs_inode(inode);
+	struct ubifs_info *c = inode->i_sb->s_fs_info;
+	loff_t compsize = 0;
+	loff_t synced_i_size;
+	unsigned int block, beyond, dlen;
+	struct ubifs_data_node *dn;
+	union ubifs_key key;
+	int err = 0;
+
+	if (S_ISDIR(inode->i_mode))
+		return -EISDIR;
+
+	dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
+	if (!dn)
+		return -ENOMEM;
+
+	filemap_write_and_wait(inode->i_mapping);
+
+	mutex_lock(&ui->ui_mutex);
+
+	spin_lock(&ui->ui_lock);
+	synced_i_size = ui->synced_i_size;
+	spin_unlock(&ui->ui_lock);
+
+	block = 0;
+	beyond = (synced_i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
+
+	while (block < beyond) {
+		data_key_init(c, &key, inode->i_ino, block);
+		err = ubifs_tnc_lookup(c, &key, dn);
+		if (err) {
+			if (err != -ENOENT) {
+				mutex_unlock(&ui->ui_mutex);
+				goto out;
+			}
+		} else {
+			dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+			compsize += dlen;
+		}
+		block += 1;
+	}
+
+	mutex_unlock(&ui->ui_mutex);
+
+	err = 0;
+	if (copy_to_user(arg, &compsize, sizeof(compsize)))
+		err = -EFAULT;
+
+out:
+	kfree(dn);
+	return err;
+}
+
 long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int flags, err;
@@ -182,6 +238,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return err;
 	}

+	case UBIFS_IOC_COMPR_SIZE:
+		return ubifs_ioctl_compsize(file, (void __user *)arg);
+
 	default:
 		return -ENOTTY;
 	}
@@ -197,6 +256,8 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case FS_IOC32_SETFLAGS:
 		cmd = FS_IOC_SETFLAGS;
 		break;
+	case UBIFS_IOC_COMPR_SIZE:
+		return ubifs_ioctl_compsize(file, (void __user *)arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 2911d2d..9000be8 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -169,6 +169,8 @@
 /* Maximum number of data nodes to bulk-read */
 #define UBIFS_MAX_BULK_READ 32

+#define UBIFS_IOC_COMPR_SIZE _IOR('O', 0, loff_t)
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH RFC] ubifs: introduce an ioctl to get UBIFS files compressed size
@ 2015-03-25 13:00 ` hujianyang
  0 siblings, 0 replies; 2+ messages in thread
From: hujianyang @ 2015-03-25 13:00 UTC (permalink / raw)
  To: Artem Bityutskiy, Richard Weinberger
  Cc: Andreas Dilger, linux-fsdevel, linux-mtd, David Sterba, markus.heininger

As discussed in last mail, I don't think record compressed size in
*ubifs_ino_inode* could suffer power cut easily, rebuild the records
of each file may increase the mount time and we may need to write
more meta data to keep the consistency of compressed size. And I
don't think *fiemap* is a good interface either, because it is can't
report compressed size at present.

http://lists.infradead.org/pipermail/linux-mtd/2015-February/057978.html

So I tried another way, introduce a new ioctl which scan the tnc_tree
to get the compressed size in each *ubifs_data_node* of the request
file.

Similar with:
https://patchwork.kernel.org/patch/117782/

But This isn't a good solution in performance side. Just want to show
my code to push the achievement of this feature.

Any test or any advisement is welcomed.

Thanks everyone~!

Signed-off-by: hujianyang <hujianyang@huawei.com>
---
 fs/ubifs/ioctl.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/ubifs.h |    2 +
 2 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index 648b143..a148e32 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -144,6 +144,62 @@ out_unlock:
 	return err;
 }

+static long ubifs_ioctl_compsize(struct file *file, void __user *arg)
+{
+	struct inode *inode = file_inode(file);
+	struct ubifs_inode *ui = ubifs_inode(inode);
+	struct ubifs_info *c = inode->i_sb->s_fs_info;
+	loff_t compsize = 0;
+	loff_t synced_i_size;
+	unsigned int block, beyond, dlen;
+	struct ubifs_data_node *dn;
+	union ubifs_key key;
+	int err = 0;
+
+	if (S_ISDIR(inode->i_mode))
+		return -EISDIR;
+
+	dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
+	if (!dn)
+		return -ENOMEM;
+
+	filemap_write_and_wait(inode->i_mapping);
+
+	mutex_lock(&ui->ui_mutex);
+
+	spin_lock(&ui->ui_lock);
+	synced_i_size = ui->synced_i_size;
+	spin_unlock(&ui->ui_lock);
+
+	block = 0;
+	beyond = (synced_i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
+
+	while (block < beyond) {
+		data_key_init(c, &key, inode->i_ino, block);
+		err = ubifs_tnc_lookup(c, &key, dn);
+		if (err) {
+			if (err != -ENOENT) {
+				mutex_unlock(&ui->ui_mutex);
+				goto out;
+			}
+		} else {
+			dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+			compsize += dlen;
+		}
+		block += 1;
+	}
+
+	mutex_unlock(&ui->ui_mutex);
+
+	err = 0;
+	if (copy_to_user(arg, &compsize, sizeof(compsize)))
+		err = -EFAULT;
+
+out:
+	kfree(dn);
+	return err;
+}
+
 long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int flags, err;
@@ -182,6 +238,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return err;
 	}

+	case UBIFS_IOC_COMPR_SIZE:
+		return ubifs_ioctl_compsize(file, (void __user *)arg);
+
 	default:
 		return -ENOTTY;
 	}
@@ -197,6 +256,8 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case FS_IOC32_SETFLAGS:
 		cmd = FS_IOC_SETFLAGS;
 		break;
+	case UBIFS_IOC_COMPR_SIZE:
+		return ubifs_ioctl_compsize(file, (void __user *)arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 2911d2d..9000be8 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -169,6 +169,8 @@
 /* Maximum number of data nodes to bulk-read */
 #define UBIFS_MAX_BULK_READ 32

+#define UBIFS_IOC_COMPR_SIZE _IOR('O', 0, loff_t)
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-03-25 13:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-25 13:00 [PATCH RFC] ubifs: introduce an ioctl to get UBIFS files compressed size hujianyang
2015-03-25 13:00 ` hujianyang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.