- Get all extents information of specified inode number to calculate
  the combination of extents which should be moved to other block group.

Signed-off-by: Takashi Sato <[EMAIL PROTECTED]>
Signed-off-by: Akira Fujita <[EMAIL PROTECTED]>
---
diff -X Online-Defrag_linux-2.6.19-rc6-git/Documentation/dontdiff -upNr 
Online-Defrag_linux-2.6.19-rc6-git-EXTENTS_INFO/fs/ext4/extents.c 
Online-Defrag_linux-2.6.19-rc6-git-MOVE_VICTIM/fs/ext4/extents.c
--- Online-Defrag_linux-2.6.19-rc6-git-EXTENTS_INFO/fs/ext4/extents.c   
2007-06-20 08:50:57.000000000 +0900
+++ Online-Defrag_linux-2.6.19-rc6-git-MOVE_VICTIM/fs/ext4/extents.c    
2007-06-20 08:27:44.000000000 +0900
@@ -43,6 +43,12 @@
 #include <linux/ext4_fs_extents.h>
 #include <asm/uaccess.h>
 
+#define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32)
+#define EXT_SET_EXTENT_DATA(src, dest)  do {\
+               dest.block = le32_to_cpu(src->ee_block);\
+               dest.start = ext_pblock(src);\
+               dest.len = le16_to_cpu(src->ee_len);\
+                                       } while (0)
 /*
  * ext_pblock:
  * combine low and high parts of physical block number into ext4_fsblk_t
@@ -2479,6 +2485,121 @@ ext4_ext_next_extent(struct inode *inode
 }
 
 /**
+ * ext4_ext_extents_info() - get extents information
+ *
+ * @ext_info:                   pointer to ext4_extents_info
+ *  @ext_info->ino              describe an inode which is used to get extent
+ *                              information
+ *  @ext_info->max_entries:     defined by DEFRAG_MAX_ENT
+ *  @ext_info->entries:                amount of extents (output)
+ *  @ext_info->ext[]:           array of extent (output)
+ *  @ext_info->offset:          starting block offset of targeted extent
+ *                              (file relative)
+ *
+ * @sb:                         for iget()
+ *
+ * This function returns 0 if next extent(s) exists,
+ * or returns 1 if next extent doesn't exist, otherwise returns error value.
+ * Called under truncate_mutex lock.
+ */
+static int ext4_ext_extents_info(struct ext4_extents_info *ext_info,
+                               struct super_block *sb)
+{
+       struct ext4_ext_path *path = NULL;
+       struct ext4_extent *ext = NULL;
+       struct inode *inode = NULL;
+       unsigned long offset = ext_info->offset;
+       int max = ext_info->max_entries;
+       int is_last_extent = 0;
+       int depth = 0;
+       int entries = 0;
+       int err = 0;
+
+       inode = iget(sb, ext_info->ino);
+       if (!inode)
+               return -EACCES;
+
+       mutex_lock(&EXT4_I(inode)->truncate_mutex);
+
+       /* if a file doesn't exist*/
+       if ((!inode->i_nlink) || (inode->i_ino < 12) ||
+                       !S_ISREG(inode->i_mode)) {
+               ext_info->entries = 0;
+               err = -ENOENT;
+               goto out;
+       }
+
+       path = ext4_ext_find_extent(inode, offset, NULL);
+       if (IS_ERR(path)) {
+               err = PTR_ERR(path);
+               path = NULL;
+               goto out;
+       }
+       depth = ext_depth(inode);
+       ext = path[depth].p_ext;
+       EXT_SET_EXTENT_DATA(ext, ext_info->ext[entries]);
+       entries = 1;
+
+       /*
+        * The ioctl can return 'max' ext4_extent_data per a call,
+        * so if @inode has > 'max' extents, we must get away here.
+        */
+       while (entries < max) {
+               is_last_extent = ext4_ext_next_extent(inode, path, &ext);
+               /* found next extent (not the last one)*/
+               if (is_last_extent == 0) {
+                       EXT_SET_EXTENT_DATA(ext, ext_info->ext[entries]);
+                       entries++;
+
+                       /*
+                        * If @inode has > 'max' extents,
+                        * this function should be called again,
+                        * (per a call, it can resolve only 'max' extents)
+                        * next time we have to start from 'max*n+1'th extent.
+                        */
+                       if (entries == max) {
+                               ext_info->offset =
+                                               le32_to_cpu(ext->ee_block) +
+                                               le32_to_cpu(ext->ee_len);
+                               /* check the extent is the last one or not*/
+                               is_last_extent =
+                                       ext4_ext_next_extent(inode, path, &ext);
+                               if (is_last_extent) {
+                                       is_last_extent = 1;
+                                       err = is_last_extent;
+                               } else if (is_last_extent < 0) {
+                                       /*ERR*/
+                                       err = is_last_extent;
+                                       goto out;
+                               }
+                               break;
+                       }
+
+               /* the extent is the last one */
+               } else if (is_last_extent == 1) {
+                       ext_info->offset = 0;
+                       err = is_last_extent;
+                       break;
+               } else {
+                       /* ERR */
+                       err = is_last_extent;
+                       goto out;
+               }
+       }
+
+       ext_info->entries = entries;
+
+out:
+       if (path) {
+               ext4_ext_drop_refs(path);
+               kfree(path);
+       }
+       mutex_unlock(&EXT4_I(inode)->truncate_mutex);
+       iput(inode);
+       return err;
+}
+
+/**
  * ext4_ext_fblocks_distribution - Search free block distribution
  * @filp      target file
  * @ex_info   ext4_extents_info
@@ -2653,6 +2774,20 @@ int ext4_ext_ioctl(struct inode *inode, 
                if (!err)
                        err = copy_to_user((struct ext4_extents_info*)arg,
                                &ext_info, sizeof(ext_info));
+       } else if (cmd == EXT4_IOC_EXTENTS_INFO) {
+               struct ext4_extents_info ext_info;
+
+               if (copy_from_user(&ext_info,
+                               (struct ext4_extents_info __user *)arg,
+                               sizeof(ext_info)))
+                       return -EFAULT;
+
+               err = ext4_ext_extents_info(&ext_info, inode->i_sb);
+               if (err >= 0) {
+                       if (copy_to_user((struct ext4_extents_info __user *)arg,
+                               &ext_info, sizeof(ext_info)))
+                               return -EFAULT;
+               }
        } else if (cmd == EXT4_IOC_DEFRAG) {
                struct ext4_ext_defrag_data defrag;
 

-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to