This patch introduces the nilfs_palloc_scan_entries() function,
which takes an inode of one of nilfs' meta data files and iterates
through all of its entries. For each entry the callback function
pointer that is given as a parameter is called. The data parameter
is passed to the callback function, so that it may receive
parameters and return results.

Signed-off-by: Andreas Rohner <[email protected]>
---
 fs/nilfs2/alloc.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/alloc.h |   6 +++
 2 files changed, 127 insertions(+)

diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
index 741fd02..0edd85a 100644
--- a/fs/nilfs2/alloc.c
+++ b/fs/nilfs2/alloc.c
@@ -545,6 +545,127 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
 }
 
 /**
+ * nilfs_palloc_scan_entries - scan through every entry and execute dofunc
+ * @inode: inode of metadata file using this allocator
+ * @dofunc: function executed for every entry
+ * @data: data pointer passed to dofunc
+ *
+ * Description: nilfs_palloc_scan_entries() walks through every allocated entry
+ * of a metadata file and executes dofunc on it. It passes a data pointer to
+ * dofunc, which can be used as an input parameter or for returning of results.
+ *
+ * Return Value: On success, 0 is returned. On error, a
+ * negative error code is returned.
+ */
+int nilfs_palloc_scan_entries(struct inode *inode,
+                             void (*dofunc)(struct inode *,
+                                            struct nilfs_palloc_req *,
+                                            void *),
+                             void *data)
+{
+       struct buffer_head *desc_bh, *bitmap_bh;
+       struct nilfs_palloc_group_desc *desc;
+       struct nilfs_palloc_req req;
+       unsigned char *bitmap;
+       void *desc_kaddr, *bitmap_kaddr;
+       unsigned long group, maxgroup, ngroups;
+       unsigned long n, m, entries_per_group, groups_per_desc_block;
+       unsigned long i, j, pos;
+       unsigned long blkoff, prev_blkoff;
+       int ret;
+
+       ngroups = nilfs_palloc_groups_count(inode);
+       maxgroup = ngroups - 1;
+       entries_per_group = nilfs_palloc_entries_per_group(inode);
+       groups_per_desc_block = nilfs_palloc_groups_per_desc_block(inode);
+
+       for (group = 0; group < ngroups;) {
+               ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh);
+               if (ret == -ENOENT)
+                       return 0;
+               else if (ret < 0)
+                       return ret;
+               req.pr_desc_bh = desc_bh;
+               desc_kaddr = kmap(desc_bh->b_page);
+               desc = nilfs_palloc_block_get_group_desc(inode, group,
+                                                        desc_bh, desc_kaddr);
+               n = nilfs_palloc_rest_groups_in_desc_block(inode, group,
+                                                          maxgroup);
+
+               for (i = 0; i < n; i++, desc++, group++) {
+                       m = entries_per_group -
+                                       nilfs_palloc_group_desc_nfrees(inode,
+                                                       group, desc);
+                       if (!m)
+                               continue;
+
+                       ret = nilfs_palloc_get_bitmap_block(
+                               inode, group, 0, &bitmap_bh);
+                       if (ret == -ENOENT) {
+                               ret = 0;
+                               goto out_desc;
+                       } else if (ret < 0)
+                               goto out_desc;
+
+                       req.pr_bitmap_bh = bitmap_bh;
+                       bitmap_kaddr = kmap(bitmap_bh->b_page);
+                       bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
+                       /* entry blkoff is always bigger than 0 */
+                       blkoff = 0;
+                       pos = 0;
+
+                       for (j = 0; j < m; ++j, ++pos) {
+                               pos = nilfs_find_next_bit(bitmap,
+                                               entries_per_group, pos);
+
+                               if (pos >= entries_per_group)
+                                       break;
+
+                               /* found an entry */
+                               req.pr_entry_nr =
+                                       entries_per_group * group + pos;
+
+                               prev_blkoff = blkoff;
+                               blkoff = nilfs_palloc_entry_blkoff(inode,
+                                                       req.pr_entry_nr);
+
+                               if (blkoff != prev_blkoff) {
+                                       if (prev_blkoff)
+                                               brelse(req.pr_entry_bh);
+
+                                       ret = nilfs_palloc_get_entry_block(
+                                                       inode, req.pr_entry_nr,
+                                                       0, &req.pr_entry_bh);
+                                       if (ret < 0)
+                                               goto out_entry;
+                               }
+
+                               dofunc(inode, &req, data);
+                       }
+
+                       if (blkoff)
+                               brelse(req.pr_entry_bh);
+                       kunmap(bitmap_bh->b_page);
+                       brelse(bitmap_bh);
+               }
+
+               kunmap(desc_bh->b_page);
+               brelse(desc_bh);
+       }
+
+       return 0;
+
+out_entry:
+       kunmap(bitmap_bh->b_page);
+       brelse(bitmap_bh);
+
+out_desc:
+       kunmap(desc_bh->b_page);
+       brelse(desc_bh);
+       return ret;
+}
+
+/**
  * nilfs_palloc_commit_alloc_entry - finish allocation of a persistent object
  * @inode: inode of metadata file using this allocator
  * @req: nilfs_palloc_req structure exchanged for the allocation
diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h
index 4bd6451..0592035 100644
--- a/fs/nilfs2/alloc.h
+++ b/fs/nilfs2/alloc.h
@@ -77,6 +77,7 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t);
 #define nilfs_set_bit_atomic           ext2_set_bit_atomic
 #define nilfs_clear_bit_atomic         ext2_clear_bit_atomic
 #define nilfs_find_next_zero_bit       find_next_zero_bit_le
+#define nilfs_find_next_bit                    find_next_bit_le
 
 /**
  * struct nilfs_bh_assoc - block offset and buffer head association
@@ -106,5 +107,10 @@ void nilfs_palloc_setup_cache(struct inode *inode,
                              struct nilfs_palloc_cache *cache);
 void nilfs_palloc_clear_cache(struct inode *inode);
 void nilfs_palloc_destroy_cache(struct inode *inode);
+int nilfs_palloc_scan_entries(struct inode *,
+                             void (*dofunc)(struct inode *,
+                                            struct nilfs_palloc_req *,
+                                            void *),
+                             void *);
 
 #endif /* _NILFS_ALLOC_H */
-- 
1.9.0

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

Reply via email to