nilfs2: add helper to find existent block on metadata file
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Thu, 16 Apr 2015 19:46:39 +0000 (12:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 13:04:04 +0000 (09:04 -0400)
Add a new metadata file function, nilfs_mdt_find_block(), which finds
an existent block on a metadata file in a given range of blocks.  This
function skips continuous hole blocks efficiently by using
nilfs_bmap_seek_key().

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/nilfs2/mdt.c
fs/nilfs2/mdt.h

index 892cf5ffdb8e165a373ae6e44036ef58ee1f5df2..dee34d9902813fe1dc1d1e1703445ca8ac013284 100644 (file)
@@ -260,6 +260,60 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,
        return ret;
 }
 
+/**
+ * nilfs_mdt_find_block - find and get a buffer on meta data file.
+ * @inode: inode of the meta data file
+ * @start: start block offset (inclusive)
+ * @end: end block offset (inclusive)
+ * @blkoff: block offset
+ * @out_bh: place to store a pointer to buffer_head struct
+ *
+ * nilfs_mdt_find_block() looks up an existing block in range of
+ * [@start, @end] and stores pointer to a buffer head of the block to
+ * @out_bh, and block offset to @blkoff, respectively.  @out_bh and
+ * @blkoff are substituted only when zero is returned.
+ *
+ * Return Value: On success, it returns 0. On error, the following negative
+ * error code is returned.
+ *
+ * %-ENOMEM - Insufficient memory available.
+ *
+ * %-EIO - I/O error
+ *
+ * %-ENOENT - no block was found in the range
+ */
+int nilfs_mdt_find_block(struct inode *inode, unsigned long start,
+                        unsigned long end, unsigned long *blkoff,
+                        struct buffer_head **out_bh)
+{
+       __u64 next;
+       int ret;
+
+       if (unlikely(start > end))
+               return -ENOENT;
+
+       ret = nilfs_mdt_read_block(inode, start, true, out_bh);
+       if (!ret) {
+               *blkoff = start;
+               goto out;
+       }
+       if (unlikely(ret != -ENOENT || start == ULONG_MAX))
+               goto out;
+
+       ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next);
+       if (!ret) {
+               if (next <= end) {
+                       ret = nilfs_mdt_read_block(inode, next, true, out_bh);
+                       if (!ret)
+                               *blkoff = next;
+               } else {
+                       ret = -ENOENT;
+               }
+       }
+out:
+       return ret;
+}
+
 /**
  * nilfs_mdt_delete_block - make a hole on the meta data file.
  * @inode: inode of the meta data file
index a294ea38e4c7800aaf0d5a73a291f4e131ee05b2..fe529a87a208d4db026efbe98de71608a1622a6c 100644 (file)
@@ -78,6 +78,9 @@ int nilfs_mdt_get_block(struct inode *, unsigned long, int,
                        void (*init_block)(struct inode *,
                                           struct buffer_head *, void *),
                        struct buffer_head **);
+int nilfs_mdt_find_block(struct inode *inode, unsigned long start,
+                        unsigned long end, unsigned long *blkoff,
+                        struct buffer_head **out_bh);
 int nilfs_mdt_delete_block(struct inode *, unsigned long);
 int nilfs_mdt_forget_block(struct inode *, unsigned long);
 int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);