|
@@ -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
|