@@ -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;
}
@@ -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.
*/
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(-)