OSDN Git Service

blkid: fix LARGEFILE_SOURCE redefined warnings
[android-x86/external-e2fsprogs.git] / lib / quota / quotaio_tree.c
index 48e58f6..964494d 100644 (file)
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <asm/byteorder.h>
 
 #include "common.h"
 #include "quotaio_tree.h"
 
 typedef char *dqbuf_t;
 
-#define getdqbuf()             smalloc(QT_BLKSIZE)
-#define freedqbuf(buf)         free(buf)
+#define freedqbuf(buf)         ext2fs_free_mem(&buf)
+
+static inline dqbuf_t getdqbuf(void)
+{
+       dqbuf_t buf;
+       if (ext2fs_get_memzero(QT_BLKSIZE, &buf)) {
+               log_err("Failed to allocate dqbuf");
+               return NULL;
+       }
+
+       return buf;
+}
 
 /* Is given dquot empty? */
 int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)
@@ -43,6 +52,11 @@ static int get_index(qid_t id, int depth)
        return (id >> ((QT_TREEDEPTH - depth - 1) * 8)) & 0xff;
 }
 
+static inline void mark_quotafile_info_dirty(struct quota_handle *h)
+{
+       h->qh_io_flags |= IOFL_INFODIRTY;
+}
+
 /* Read given block */
 static void read_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
 {
@@ -51,7 +65,7 @@ static void read_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
        err = h->e2fs_read(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf,
                        QT_BLKSIZE);
        if (err < 0)
-               log_fatal(2, "Cannot read block %u: %s", blk, strerror(errno));
+               log_err("Cannot read block %u: %s", blk, strerror(errno));
        else if (err != QT_BLKSIZE)
                memset(buf + err, 0, QT_BLKSIZE - err);
 }
@@ -64,8 +78,7 @@ static int write_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
        err = h->e2fs_write(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf,
                        QT_BLKSIZE);
        if (err < 0 && errno != ENOSPC)
-               log_fatal(2, "Cannot write block (%u): %s",
-                         blk, strerror(errno));
+               log_err("Cannot write block (%u): %s", blk, strerror(errno));
        if (err != QT_BLKSIZE)
                return -ENOSPC;
        return 0;
@@ -79,17 +92,20 @@ static int get_free_dqblk(struct quota_handle *h)
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
        int blk;
 
+       if (!buf)
+               return -ENOMEM;
+
        if (info->dqi_free_blk) {
                blk = info->dqi_free_blk;
                read_blk(h, blk, buf);
-               info->dqi_free_blk = __le32_to_cpu(dh->dqdh_next_free);
+               info->dqi_free_blk = ext2fs_le32_to_cpu(dh->dqdh_next_free);
        } else {
                memset(buf, 0, QT_BLKSIZE);
                /* Assure block allocation... */
                if (write_blk(h, info->dqi_blocks, buf) < 0) {
                        freedqbuf(buf);
                        log_err("Cannot allocate new quota block "
-                               "(out of disk space).", "");
+                               "(out of disk space).");
                        return -ENOSPC;
                }
                blk = info->dqi_blocks++;
@@ -105,9 +121,9 @@ static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf, uint blk)
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
 
-       dh->dqdh_next_free = __cpu_to_le32(info->dqi_free_blk);
-       dh->dqdh_prev_free = __cpu_to_le32(0);
-       dh->dqdh_entries = __cpu_to_le16(0);
+       dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_blk);
+       dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
+       dh->dqdh_entries = ext2fs_cpu_to_le16(0);
        info->dqi_free_blk = blk;
        mark_quotafile_info_dirty(h);
        write_blk(h, blk, buf);
@@ -118,9 +134,12 @@ static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
 {
        dqbuf_t tmpbuf = getdqbuf();
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
-       uint nextblk = __le32_to_cpu(dh->dqdh_next_free), prevblk =
+       uint nextblk = ext2fs_le32_to_cpu(dh->dqdh_next_free), prevblk =
+
+               ext2fs_le32_to_cpu(dh->dqdh_prev_free);
 
-               __le32_to_cpu(dh->dqdh_prev_free);
+       if (!tmpbuf)
+               return;
 
        if (nextblk) {
                read_blk(h, nextblk, tmpbuf);
@@ -138,7 +157,7 @@ static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
                mark_quotafile_info_dirty(h);
        }
        freedqbuf(tmpbuf);
-       dh->dqdh_next_free = dh->dqdh_prev_free = __cpu_to_le32(0);
+       dh->dqdh_next_free = dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
        write_blk(h, blk, buf); /* No matter whether write succeeds
                                 * block is out of list */
 }
@@ -150,13 +169,16 @@ static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
        struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
 
-       dh->dqdh_next_free = __cpu_to_le32(info->dqi_free_entry);
-       dh->dqdh_prev_free = __cpu_to_le32(0);
+       if (!tmpbuf)
+               return;
+
+       dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_entry);
+       dh->dqdh_prev_free = ext2fs_cpu_to_le32(0);
        write_blk(h, blk, buf);
        if (info->dqi_free_entry) {
                read_blk(h, info->dqi_free_entry, tmpbuf);
                ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
-                               __cpu_to_le32(blk);
+                               ext2fs_cpu_to_le32(blk);
                write_blk(h, info->dqi_free_entry, tmpbuf);
        }
        freedqbuf(tmpbuf);
@@ -176,6 +198,11 @@ static uint find_free_dqentry(struct quota_handle *h, struct dquot *dquot,
 
        *err = 0;
        buf = getdqbuf();
+       if (!buf) {
+               *err = -ENOMEM;
+               return 0;
+       }
+
        dh = (struct qt_disk_dqdbheader *)buf;
        if (info->dqi_free_entry) {
                blk = info->dqi_free_entry;
@@ -193,10 +220,12 @@ static uint find_free_dqentry(struct quota_handle *h, struct dquot *dquot,
        }
 
        /* Block will be full? */
-       if (__le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info))
+       if (ext2fs_le16_to_cpu(dh->dqdh_entries) + 1 >=
+           qtree_dqstr_in_blk(info))
                remove_free_dqentry(h, buf, blk);
 
-       dh->dqdh_entries = __cpu_to_le16(__le16_to_cpu(dh->dqdh_entries) + 1);
+       dh->dqdh_entries =
+               ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) + 1);
        /* Find free structure in block */
        ddquot = buf + sizeof(struct qt_disk_dqdbheader);
        for (i = 0;
@@ -205,8 +234,7 @@ static uint find_free_dqentry(struct quota_handle *h, struct dquot *dquot,
                ddquot += info->dqi_entry_size;
 
        if (i == qtree_dqstr_in_blk(info))
-               log_fatal(2, "find_free_dqentry(): Data block full but it "
-                            "shouldn't.", "");
+               log_err("find_free_dqentry(): Data block full unexpectedly.");
 
        write_blk(h, blk, buf);
        dquot->dq_dqb.u.v2_mdqb.dqb_off =
@@ -228,6 +256,9 @@ static int do_insert_tree(struct quota_handle *h, struct dquot *dquot,
 
        log_debug("inserting in tree: treeblk=%u, depth=%d", *treeblk, depth);
        buf = getdqbuf();
+       if (!buf)
+               return -ENOMEM;
+
        if (!*treeblk) {
                ret = get_free_dqblk(h);
                if (ret < 0)
@@ -240,21 +271,22 @@ static int do_insert_tree(struct quota_handle *h, struct dquot *dquot,
        }
 
        ref = (u_int32_t *) buf;
-       newblk = __le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
+       newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
        if (!newblk)
                newson = 1;
        if (depth == QT_TREEDEPTH - 1) {
                if (newblk)
-                       log_fatal(2, "Inserting already present quota entry "
-                                    "(block %u).",
-                                 ref[get_index(dquot->dq_id, depth)]);
+                       log_err("Inserting already present quota entry "
+                               "(block %u).",
+                               ref[get_index(dquot->dq_id, depth)]);
                newblk = find_free_dqentry(h, dquot, &ret);
        } else {
                ret = do_insert_tree(h, dquot, &newblk, depth + 1);
        }
 
        if (newson && ret >= 0) {
-               ref[get_index(dquot->dq_id, depth)] = __cpu_to_le32(newblk);
+               ref[get_index(dquot->dq_id, depth)] =
+                       ext2fs_cpu_to_le32(newblk);
                write_blk(h, *treeblk, buf);
        } else if (newact && ret < 0) {
                put_free_dqblk(h, buf, *treeblk);
@@ -271,21 +303,28 @@ static void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
        uint tmp = QT_TREEOFF;
 
        if (do_insert_tree(h, dquot, &tmp, 0) < 0)
-               log_fatal(2, "Cannot write quota (id %u): %s",
-                         (uint) dquot->dq_id, strerror(errno));
+               log_err("Cannot write quota (id %u): %s",
+                       (uint) dquot->dq_id, strerror(errno));
 }
 
 /* Write dquot to file */
 void qtree_write_dquot(struct dquot *dquot)
 {
        ssize_t ret;
+       char *ddquot;
        struct quota_handle *h = dquot->dq_h;
        struct qtree_mem_dqinfo *info =
                        &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
        log_debug("writing ddquot 1: off=%llu, info->dqi_entry_size=%u",
                        dquot->dq_dqb.u.v2_mdqb.dqb_off,
                        info->dqi_entry_size);
-       char *ddquot = (char *)smalloc(info->dqi_entry_size);
+       ret = ext2fs_get_mem(info->dqi_entry_size, &ddquot);
+       if (ret) {
+               errno = ENOMEM;
+               log_err("Quota write failed (id %u): %s",
+                       (uint)dquot->dq_id, strerror(errno));
+               return;
+       }
 
        if (!dquot->dq_dqb.u.v2_mdqb.dqb_off)
                dq_insert_tree(dquot->dq_h, dquot);
@@ -299,9 +338,10 @@ void qtree_write_dquot(struct dquot *dquot)
        if (ret != info->dqi_entry_size) {
                if (ret > 0)
                        errno = ENOSPC;
-               log_fatal(2, "Quota write failed (id %u): %s",
-                         (uint)dquot->dq_id, strerror(errno));
+               log_err("Quota write failed (id %u): %s",
+                       (uint)dquot->dq_id, strerror(errno));
        }
+       ext2fs_free_mem(&ddquot);
 }
 
 /* Free dquot entry in data block */
@@ -311,17 +351,21 @@ static void free_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk)
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
        dqbuf_t buf = getdqbuf();
 
+       if (!buf)
+               return;
+
        if (dquot->dq_dqb.u.v2_mdqb.dqb_off >> QT_BLKSIZE_BITS != blk)
-               log_fatal(2, "Quota structure has offset to other block (%u) "
-                            "than it should (%u).", blk,
+               log_err("Quota structure has offset to other block (%u) "
+                       "than it should (%u).", blk,
                          (uint) (dquot->dq_dqb.u.v2_mdqb.dqb_off >>
                                  QT_BLKSIZE_BITS));
 
        read_blk(h, blk, buf);
        dh = (struct qt_disk_dqdbheader *)buf;
-       dh->dqdh_entries = __cpu_to_le16(__le16_to_cpu(dh->dqdh_entries) - 1);
+       dh->dqdh_entries =
+               ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) - 1);
 
-       if (!__le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
+       if (!ext2fs_le16_to_cpu(dh->dqdh_entries)) {    /* Block got free? */
                remove_free_dqentry(h, buf, blk);
                put_free_dqblk(h, buf, blk);
        } else {
@@ -330,7 +374,7 @@ static void free_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk)
                       0, info->dqi_entry_size);
 
                /* First free entry? */
-               if (__le16_to_cpu(dh->dqdh_entries) ==
+               if (ext2fs_le16_to_cpu(dh->dqdh_entries) ==
                                qtree_dqstr_in_blk(info) - 1)
                        /* This will also write data block */
                        insert_free_dqentry(h, buf, blk);
@@ -349,8 +393,11 @@ static void remove_tree(struct quota_handle *h, struct dquot *dquot,
        uint newblk;
        u_int32_t *ref = (u_int32_t *) buf;
 
+       if (!buf)
+               return;
+
        read_blk(h, *blk, buf);
-       newblk = __le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
+       newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
        if (depth == QT_TREEDEPTH - 1) {
                free_dqentry(h, dquot, newblk);
                newblk = 0;
@@ -361,7 +408,7 @@ static void remove_tree(struct quota_handle *h, struct dquot *dquot,
        if (!newblk) {
                int i;
 
-               ref[get_index(dquot->dq_id, depth)] = __cpu_to_le32(0);
+               ref[get_index(dquot->dq_id, depth)] = ext2fs_cpu_to_le32(0);
 
                /* Block got empty? */
                for (i = 0; i < QT_BLKSIZE && !buf[i]; i++);
@@ -388,14 +435,17 @@ void qtree_delete_dquot(struct dquot *dquot)
 }
 
 /* Find entry in block */
-static loff_t find_block_dqentry(struct quota_handle *h,
-                                struct dquot *dquot, uint blk)
+static ext2_loff_t find_block_dqentry(struct quota_handle *h,
+                                     struct dquot *dquot, uint blk)
 {
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
        dqbuf_t buf = getdqbuf();
        int i;
        char *ddquot = buf + sizeof(struct qt_disk_dqdbheader);
 
+       if (!buf)
+               return -ENOMEM;
+
        read_blk(h, blk, buf);
        for (i = 0;
             i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
@@ -403,24 +453,28 @@ static loff_t find_block_dqentry(struct quota_handle *h,
                ddquot += info->dqi_entry_size;
 
        if (i == qtree_dqstr_in_blk(info))
-               log_fatal(2, "Quota for id %u referenced but not present.",
-                         dquot->dq_id);
+               log_err("Quota for id %u referenced but not present.",
+                       dquot->dq_id);
        freedqbuf(buf);
        return (blk << QT_BLKSIZE_BITS) + sizeof(struct qt_disk_dqdbheader) +
                i * info->dqi_entry_size;
 }
 
 /* Find entry for given id in the tree */
-static loff_t find_tree_dqentry(struct quota_handle *h, struct dquot *dquot,
-                               uint blk, int depth)
+static ext2_loff_t find_tree_dqentry(struct quota_handle *h,
+                                    struct dquot *dquot,
+                                    uint blk, int depth)
 {
        dqbuf_t buf = getdqbuf();
-       loff_t ret = 0;
+       ext2_loff_t ret = 0;
        u_int32_t *ref = (u_int32_t *) buf;
 
+       if (!buf)
+               return -ENOMEM;
+
        read_blk(h, blk, buf);
        ret = 0;
-       blk = __le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
+       blk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]);
        if (!blk)       /* No reference? */
                goto out_buf;
        if (depth < QT_TREEDEPTH - 1)
@@ -433,23 +487,30 @@ out_buf:
 }
 
 /* Find entry for given id in the tree - wrapper function */
-static inline loff_t find_dqentry(struct quota_handle *h, struct dquot *dquot)
+static inline ext2_loff_t find_dqentry(struct quota_handle *h,
+                                      struct dquot *dquot)
 {
        return find_tree_dqentry(h, dquot, QT_TREEOFF, 0);
 }
 
 /*
- *  Read dquot (either from disk or from kernel)
- *  User can use errno to detect errstr when NULL is returned
+ *  Read dquot from disk.
  */
 struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id)
 {
        struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree;
-       loff_t offset;
+       ext2_loff_t offset;
        ssize_t ret;
-       char *ddquot = smalloc(info->dqi_entry_size);
+       char *ddquot;
        struct dquot *dquot = get_empty_dquot();
 
+       if (!dquot)
+               return NULL;
+       if (ext2fs_get_mem(info->dqi_entry_size, &ddquot)) {
+               ext2fs_free_mem(&dquot);
+               return NULL;
+       }
+
        dquot->dq_id = id;
        dquot->dq_h = h;
        dquot->dq_dqb.u.v2_mdqb.dqb_off = 0;
@@ -463,23 +524,24 @@ struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id)
                if (ret != info->dqi_entry_size) {
                        if (ret > 0)
                                errno = EIO;
-                       log_fatal(2,
-                               "Cannot read quota structure for id %u: %s",
+                       log_err("Cannot read quota structure for id %u: %s",
                                dquot->dq_id, strerror(errno));
                }
                info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
        }
+       ext2fs_free_mem(&ddquot);
        return dquot;
 }
 
 /*
- *     Scan all dquots in file and call callback on each
+ * Scan all dquots in file and call callback on each
  */
 #define set_bit(bmp, ind) ((bmp)[(ind) >> 3] |= (1 << ((ind) & 7)))
 #define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7)))
 
 static int report_block(struct dquot *dquot, uint blk, char *bitmap,
-                       int (*process_dquot) (struct dquot *, char *))
+                       int (*process_dquot) (struct dquot *, void *),
+                       void *data)
 {
        struct qtree_mem_dqinfo *info =
                        &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
@@ -488,16 +550,23 @@ static int report_block(struct dquot *dquot, uint blk, char *bitmap,
        char *ddata;
        int entries, i;
 
+       if (!buf)
+               return 0;
+
        set_bit(bitmap, blk);
        read_blk(dquot->dq_h, blk, buf);
        dh = (struct qt_disk_dqdbheader *)buf;
        ddata = buf + sizeof(struct qt_disk_dqdbheader);
-       entries = __le16_to_cpu(dh->dqdh_entries);
+       entries = ext2fs_le16_to_cpu(dh->dqdh_entries);
        for (i = 0; i < qtree_dqstr_in_blk(info);
                        i++, ddata += info->dqi_entry_size)
                if (!qtree_entry_unused(info, ddata)) {
+                       dquot->dq_dqb.u.v2_mdqb.dqb_off =
+                               (blk << QT_BLKSIZE_BITS) +
+                               sizeof(struct qt_disk_dqdbheader) +
+                               i * info->dqi_entry_size;
                        info->dqi_ops->disk2mem_dqblk(dquot, ddata);
-                       if (process_dquot(dquot, NULL) < 0)
+                       if (process_dquot(dquot, data) < 0)
                                break;
                }
        freedqbuf(buf);
@@ -507,38 +576,44 @@ static int report_block(struct dquot *dquot, uint blk, char *bitmap,
 static void check_reference(struct quota_handle *h, uint blk)
 {
        if (blk >= h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks)
-               log_fatal(2, "Illegal reference (%u >= %u) in %s quota file. "
-                            "Quota file is probably corrupted.\n"
-                            "Please run e2fsck (8) to fix it.",
-                         blk,
-                         h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks,
-                         type2name(h->qh_type));
+               log_err("Illegal reference (%u >= %u) in %s quota file. "
+                       "Quota file is probably corrupted.\n"
+                       "Please run e2fsck (8) to fix it.",
+                       blk,
+                       h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks,
+                       type2name(h->qh_type));
 }
 
 static int report_tree(struct dquot *dquot, uint blk, int depth, char *bitmap,
-                      int (*process_dquot) (struct dquot *, char *))
+                      int (*process_dquot) (struct dquot *, void *),
+                      void *data)
 {
        int entries = 0, i;
        dqbuf_t buf = getdqbuf();
        u_int32_t *ref = (u_int32_t *) buf;
 
+       if (!buf)
+               return 0;
+
        read_blk(dquot->dq_h, blk, buf);
        if (depth == QT_TREEDEPTH - 1) {
                for (i = 0; i < QT_BLKSIZE >> 2; i++) {
-                       blk = __le32_to_cpu(ref[i]);
+                       blk = ext2fs_le32_to_cpu(ref[i]);
                        check_reference(dquot->dq_h, blk);
                        if (blk && !get_bit(bitmap, blk))
                                entries += report_block(dquot, blk, bitmap,
-                                                       process_dquot);
+                                                       process_dquot, data);
                }
        } else {
-               for (i = 0; i < QT_BLKSIZE >> 2; i++)
-                       blk = __le32_to_cpu(ref[i]);
+               for (i = 0; i < QT_BLKSIZE >> 2; i++) {
+                       blk = ext2fs_le32_to_cpu(ref[i]);
                        if (blk) {
                                check_reference(dquot->dq_h, blk);
                                entries += report_tree(dquot, blk, depth + 1,
-                                                      bitmap, process_dquot);
+                                                      bitmap, process_dquot,
+                                                      data);
                        }
+               }
        }
        freedqbuf(buf);
        return entries;
@@ -555,20 +630,26 @@ static uint find_set_bits(char *bmp, int blocks)
 }
 
 int qtree_scan_dquots(struct quota_handle *h,
-                     int (*process_dquot) (struct dquot *, char *))
+                     int (*process_dquot) (struct dquot *, void *),
+                     void *data)
 {
        char *bitmap;
        struct v2_mem_dqinfo *v2info = &h->qh_info.u.v2_mdqi;
        struct qtree_mem_dqinfo *info = &v2info->dqi_qtree;
        struct dquot *dquot = get_empty_dquot();
 
+       if (!dquot)
+               return -1;
+
        dquot->dq_h = h;
-       bitmap = smalloc((info->dqi_blocks + 7) >> 3);
-       memset(bitmap, 0, (info->dqi_blocks + 7) >> 3);
+       if (ext2fs_get_memzero((info->dqi_blocks + 7) >> 3, &bitmap)) {
+               ext2fs_free_mem(&dquot);
+               return -1;
+       }
        v2info->dqi_used_entries = report_tree(dquot, QT_TREEOFF, 0, bitmap,
-                                              process_dquot);
+                                              process_dquot, data);
        v2info->dqi_data_blocks = find_set_bits(bitmap, info->dqi_blocks);
-       free(bitmap);
-       free(dquot);
+       ext2fs_free_mem(&bitmap);
+       ext2fs_free_mem(&dquot);
        return 0;
 }