Signed-off-by: Dmitry Monakhov <dmonak...@openvz.org>
---
 misc/e4defrag2.c |   68 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/misc/e4defrag2.c b/misc/e4defrag2.c
index 7aab2b4..d351965 100644
--- a/misc/e4defrag2.c
+++ b/misc/e4defrag2.c
@@ -242,6 +242,7 @@ struct fmap_extent_cache
 {
        unsigned fec_size;      /* map array size */
        unsigned fec_extents;   /* number of valid entries */
+       struct fmap_extent *fec_xattr;
        struct fmap_extent fec_map[];
 };
 
@@ -252,6 +253,9 @@ struct fmap_extent_stat
        unsigned group; /* Number of groups, counter is speculative */
        unsigned local_ex; /* Number of extents from  the same group as inode */
        unsigned local_sz; /* Total len of local extents */
+       unsigned nr_idx; /* Number of index blocks */
+       __u64    xattr; /* xattr phys block */
+
 };
 
 /* Used space and integral inode usage stats */
@@ -750,9 +754,10 @@ static int __get_inode_fiemap(struct defrag_context *dfx, 
int fd,
                (*fec)->fec_size = DEFAULT_FMAP_CACHE_SZ;
                (*fec)->fec_extents = 0;
        }
-       if (fest)
+       if (fest) {
                memset(fest, 0 , sizeof(*fest));
-
+               fest->nr_idx = st->st_blocks >> (blksz_log - 9);
+       }
        ext_buf = fiemap_buf->fm_extents;
        memset(fiemap_buf, 0, fie_buf_size);
        fiemap_buf->fm_length = FIEMAP_MAX_OFFSET;
@@ -791,6 +796,12 @@ static int __get_inode_fiemap(struct defrag_context *dfx, 
int fd,
                                        fest->group++;
                                        prev_blk_grp = blk_grp;
                                }
+                               /* We are work on livefs so race is possible */
+                               if (fest->nr_idx < len) {
+                                       ret = -1;
+                                       goto out;
+                               }
+                                       fest->nr_idx -= len;
                        }
 
                        if ((*fec)->fec_extents && lblk == lblk_last && pblk == 
pblk_last) {
@@ -834,12 +845,36 @@ static int __get_inode_fiemap(struct defrag_context *dfx, 
int fd,
                 */
        } while (fiemap_buf->fm_mapped_extents == EXTENT_MAX_COUNT &&
                 !(ext_buf[EXTENT_MAX_COUNT-1].fe_flags & FIEMAP_EXTENT_LAST));
+
+       /* get xattr block */
+       fiemap_buf->fm_flags |= FIEMAP_FLAG_XATTR;
+       fiemap_buf->fm_start = 0;
+       memset(ext_buf, 0, ext_buf_size);
+       ret = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf);
+       if (ret < 0 || fiemap_buf->fm_mapped_extents == 0) {
+               if (debug_flag & DBG_FIEMAP) {
+                       fprintf(stderr, "%s: Can't get xattr info for"
+                               " inode:%ld ret:%d mapped:%d\n",
+                               __func__, st->st_ino, ret,
+                               fiemap_buf->fm_mapped_extents);
+               }
+               goto out;
+       }
+       if (!(ext_buf[0].fe_flags & FIEMAP_EXTENT_DATA_INLINE)) {
+               fest->xattr = ext_buf[i].fe_physical >> blksz_log;
+               if (fest->nr_idx)
+                       ret = -1;
+
+               fest->nr_idx--;
+       }
 out:
        /////////////FIXME:DEBUG
-       if (debug_flag & DBG_FIEMAP && fest)
-               printf("%s fmap stat ino:%ld hole:%d frag:%d local_ex:%d 
local_sz:%d group:%d\n",
+       if ((debug_flag & DBG_FIEMAP) && fest)
+               printf("%s fmap stat ino:%ld hole:%d frag:%d local_ex:%d "
+                      "local_sz:%d group:%d nr_idx:%u xattr:%lld ret:%d\n",
                       __func__, st->st_ino, fest->hole, fest->frag,
-                      fest->local_ex, fest->local_sz, fest->group);
+                      fest->local_ex, fest->local_sz, fest->group, 
fest->nr_idx,
+                      fest->xattr, ret);
 
        free(fiemap_buf);
 
@@ -1134,7 +1169,6 @@ static int scan_inode_pass3(struct defrag_context *dfx, 
int fd,
                ret = do_iaf_defrag_one(dfx, dirfd, name, stat, fec, &fest);
                if (!ret)
                        goto out;
-               
        }
 
        if (stat->st_mtime  < older_than)
@@ -1916,7 +1950,7 @@ static int prepare_donor(struct defrag_context *dfx, 
dgrp_t group,
                printf("%s grp:%u donor_fd:%d blocks:%llu frag:%u\n",
                       __func__, group, donor->fd, blocks, max_frag);
        }
-       assert(blocks);
+       assert(blocks && max_frag);
 
        /* First try to reuse existing donor if available */
        if (donor->fd != -1) {
@@ -1954,23 +1988,28 @@ static int check_iaf(struct defrag_context *dfx, struct 
stat64 *stat,
        __u64 eof_lblk;
        //// FIXME free_space_average should be tunable
        __u64 free_space_average = 64;
+       __u32 meta_blocks;
        int ret  = 1;
 
        if (!S_ISREG(stat->st_mode))
                ret = 0;
-       if (fec->fec_extents < 2)
-               ret = 0;
+       if (fec->fec_extents < 2) {
+               /*
+                * Older kernels can not collapse tree depth to zero for flat 
inodes
+                * Let's fix it by relocating it once again
+                */
+               if (fest->nr_idx == 0)
+                       ret = 0;
+       }
        if (fest->hole)
                ret = 0;
 
-
        eof_lblk = fec->fec_map[fec->fec_extents -1].lblk +
                fec->fec_map[fec->fec_extents -1].len;
 
        if (eof_lblk / fest->frag > free_space_average)
                ret = 0;
 
-
        if (debug_flag & DBG_RT)
                printf("%s ino:%ld frag:%d eof_blk:%lld free_space_aver:%d 
ret:%d\n",
                       __FUNCTION__, stat->st_ino, eof_lblk, fest->frag,
@@ -2055,7 +2094,7 @@ static int do_iaf_defrag_one(struct defrag_context *dfx, 
int dirfd, const char *
        __u64 eof_lblk = fec->fec_map[fec->fec_extents -1].lblk +
                fec->fec_map[fec->fec_extents -1].len;
 
-       assert(fest->frag >= 2);
+       assert(fest->frag >= 2 || fest->nr_idx);
        ret  = 0;
 
        /* Need to reopen file for RW */
@@ -2088,6 +2127,8 @@ static int do_iaf_defrag_one(struct defrag_context *dfx, 
int dirfd, const char *
         * FIXME: This should be tunable
         */
        force_local = eof_lblk < 4;
+       if (!fest->local_ex)
+               force_local = 0;
 
        if (debug_flag & (DBG_SCAN|DBG_IAF)) {
                int i;
@@ -2100,7 +2141,8 @@ static int do_iaf_defrag_one(struct defrag_context *dfx, 
int dirfd, const char *
                               fec->fec_map[i].pblk);
        }
 
-       ret = prepare_donor(dfx, ino_grp, &donor, eof_lblk, force_local, 
fest->frag / 2);
+       ret = prepare_donor(dfx, ino_grp, &donor, eof_lblk, force_local,
+                           (fest->nr_idx + fest->frag) / 2);
        if (ret) {
                if (debug_flag & (DBG_SCAN|DBG_IAF))
                        fprintf(stderr, "%s: group:%u Can not allocate donor"
-- 
1.7.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to