Merge remote-tracking branches 'spi/topic/mtk', 'spi/topic/pxa2xx', 'spi/topic/qspi...
[firefly-linux-kernel-4.4.55.git] / fs / nilfs2 / mdt.c
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