From: Akira Fujita <a-fujita@rs.jp.nec.com>
To: linux-ext4@vger.kernel.org, Theodore Tso <tytso@mit.edu>,
Mingming Cao <cmm@us.ibm.com>
Cc: linux-fsdevel@vger.kernel.org
Subject: [RFC][PATCH 7/9]ext4: Add the EXT4_IOC_FIEMAP_INO ioctl
Date: Fri, 24 Oct 2008 19:09:58 +0900 [thread overview]
Message-ID: <49019EF6.4000706@rs.jp.nec.com> (raw)
ext4: online defrag -- Add the EXT4_IOC_FIEMAP_INO ioctl.
From: Akira Fujita <a-fujita@rs.jp.nec.com>
The EXT4_IOC_FIEMAP_INO is used to get extents information of
inode which set to ioctl.
The defragger uses this ioctl to check the fragment condition
and to get extents information in the specified block group.
Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com>
---
fs/ext4/defrag.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/ext4/ext4.h | 7 +++
fs/ext4/ioctl.c | 7 +++
3 files changed, 127 insertions(+), 0 deletions(-)
diff --git a/fs/ext4/defrag.c b/fs/ext4/defrag.c
index 891e599..67030bc 100644
--- a/fs/ext4/defrag.c
+++ b/fs/ext4/defrag.c
@@ -20,6 +20,8 @@
#include "ext4_extents.h"
#include "group.h"
+#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
+
/**
* ext4_defrag_next_extent - Search for the next extent and set it to "extent"
*
@@ -91,6 +93,117 @@ err:
}
/**
+ * ext4_defrag_fiemap_ino - Get extents information by inode number
+ *
+ * @filp: pointer to file
+ * @arg: pointer to fiemap_ino
+ * @fiemap_ino->ino: an inode number which is used to get
+ * extent information
+ * @fiemap_ino->fiemap: request for fiemap ioctl
+ *
+ * This function returns 0 if succeed, otherwise returns error value.
+ */
+int
+ext4_defrag_fiemap_ino(struct file *filp, unsigned long arg)
+{
+ struct fiemap_ino fiemap_ino;
+ struct fiemap_extent_info fieinfo = { 0, };
+ struct inode *inode;
+ struct super_block *sb = filp->f_dentry->d_inode->i_sb;
+ u64 len = 0;
+ int err = 0;
+
+ if (copy_from_user(&fiemap_ino, (struct fiemap_ino __user *)arg,
+ sizeof(struct fiemap_ino)))
+ return -EFAULT;
+
+ /* Special inodes shouldn't be choiced */
+ if (fiemap_ino.ino < EXT4_GOOD_OLD_FIRST_INO)
+ return -ENOENT;
+
+ inode = ext4_iget(sb, fiemap_ino.ino);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ /*
+ * If we do not have the permission to access the inode,
+ * just skip it.
+ */
+ if (!capable(CAP_DAC_OVERRIDE)) {
+ if ((inode->i_mode & S_IRUSR) != S_IRUSR)
+ return -EACCES;
+ if (current->fsuid != inode->i_uid)
+ return -EACCES;
+ }
+
+ /* Return -ENOENT if a file does not exist */
+ if (!inode->i_nlink || !S_ISREG(inode->i_mode)) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!inode->i_op->fiemap) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (fiemap_ino.fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (fiemap_ino.fiemap.fm_length == 0) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (fiemap_ino.fiemap.fm_start > sb->s_maxbytes) {
+ err = -EFBIG;
+ goto out;
+ }
+
+ /*
+ * Check offset and length
+ * If the specified range exceeds the max file size,
+ * adjust the length.
+ */
+ if ((fiemap_ino.fiemap.fm_length > sb->s_maxbytes) ||
+ (sb->s_maxbytes - fiemap_ino.fiemap.fm_length)
+ < fiemap_ino.fiemap.fm_start)
+ len = sb->s_maxbytes - fiemap_ino.fiemap.fm_start;
+ else
+ len = fiemap_ino.fiemap.fm_length;
+
+ fieinfo.fi_flags = fiemap_ino.fiemap.fm_flags;
+ fieinfo.fi_extents_max = fiemap_ino.fiemap.fm_extent_count;
+ fieinfo.fi_extents_start =
+ (struct fiemap_extent *)(arg + sizeof(fiemap_ino));
+
+ if (fiemap_ino.fiemap.fm_extent_count != 0 &&
+ !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start,
+ fieinfo.fi_extents_max * sizeof(struct fiemap_extent))) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
+ filemap_write_and_wait(inode->i_mapping);
+
+ err = inode->i_op->fiemap(inode, &fieinfo,
+ fiemap_ino.fiemap.fm_start, len);
+ if (!err) {
+ fiemap_ino.fiemap.fm_flags = fieinfo.fi_flags;
+ fiemap_ino.fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
+ if (copy_to_user((char *)arg, &fiemap_ino, sizeof(fiemap_ino)))
+ err = -EFAULT;
+ }
+
+out:
+ iput(inode);
+ return err;
+}
+
+/**
* ext4_defrag_merge_across_blocks - Merge extents across leaf block
*
* @handle: journal handle
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f7b092d..c72703f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -305,6 +305,7 @@ struct ext4_new_group_data {
#define EXT4_IOC_DEFRAG _IOW('f', 15, struct ext4_ext_defrag_data)
#define EXT4_IOC_SUPER_INFO _IOR('f', 16, struct ext4_super_block)
#define EXT4_IOC_FREE_BLOCKS_INFO _IOWR('f', 17, struct ext4_extents_info)
+#define EXT4_IOC_FIEMAP_INO _IOWR('f', 18, struct fiemap_ino)
/*
* ioctl commands in 32 bit emulation
@@ -352,6 +353,11 @@ struct ext4_extents_info {
struct ext4_extent_data ext[DEFRAG_MAX_ENT];
};
+struct fiemap_ino {
+ __u64 ino;
+ struct fiemap fiemap;
+};
+
#define EXT4_TRANS_META_BLOCKS 4 /* bitmap + group desc + sb + inode */
/*
@@ -1185,6 +1191,7 @@ extern int ext4_ext_journal_restart(handle_t *handle, int needed);
/* defrag.c */
extern int ext4_defrag(struct file *filp, ext4_lblk_t block_start,
ext4_lblk_t defrag_size, ext4_fsblk_t goal);
+extern int ext4_defrag_fiemap_ino(struct file *filp, unsigned long arg);
static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
{
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 5709574..b69b54a 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -256,6 +256,13 @@ setversion_out:
return 0;
}
+ case EXT4_IOC_FIEMAP_INO: {
+ int err;
+
+ err = ext4_defrag_fiemap_ino(filp, arg);
+ return err;
+ }
+
case EXT4_IOC_FREE_BLOCKS_INFO: {
struct ext4_extents_info ext_info;
int err;
next reply other threads:[~2008-10-24 10:10 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-24 10:09 Akira Fujita [this message]
2008-10-26 8:40 ` [RFC][PATCH 7/9]ext4: Add the EXT4_IOC_FIEMAP_INO ioctl Andreas Dilger
2008-10-26 8:48 ` Christoph Hellwig
2008-10-26 8:49 ` Christoph Hellwig
2008-10-31 10:05 ` Christoph Hellwig
2008-11-06 7:39 ` Akira Fujita
2008-11-06 16:15 ` Theodore Tso
2008-10-27 10:21 ` Akira Fujita
2008-10-27 19:55 ` Andreas Dilger
2008-10-31 9:46 ` Akira Fujita
2008-11-04 21:42 ` Andreas Dilger
-- strict thread matches above, loose matches on Subject: below --
2008-11-13 11:34 Akira Fujita
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49019EF6.4000706@rs.jp.nec.com \
--to=a-fujita@rs.jp.nec.com \
--cc=cmm@us.ibm.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.