|
@@ -806,3 +806,74 @@ out:
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
|
|
|
|
+ struct buffer_head *bhs[], int flags,
|
|
|
|
+ int (*validate)(struct super_block *sb,
|
|
|
|
+ struct buffer_head *bh))
|
|
|
|
+{
|
|
|
|
+ int rc = 0;
|
|
|
|
+ u64 p_block, p_count;
|
|
|
|
+ int i, count, done = 0;
|
|
|
|
+
|
|
|
|
+ mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, "
|
|
|
|
+ "flags = %x, validate = %p)\n",
|
|
|
|
+ inode, (unsigned long long)v_block, nr, bhs, flags,
|
|
|
|
+ validate);
|
|
|
|
+
|
|
|
|
+ if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >=
|
|
|
|
+ i_size_read(inode)) {
|
|
|
|
+ BUG_ON(!(flags & OCFS2_BH_READAHEAD));
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ while (done < nr) {
|
|
|
|
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
|
|
|
|
+ rc = ocfs2_extent_map_get_blocks(inode, v_block + done,
|
|
|
|
+ &p_block, &p_count, NULL);
|
|
|
|
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
|
|
|
|
+ if (rc) {
|
|
|
|
+ mlog_errno(rc);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!p_block) {
|
|
|
|
+ rc = -EIO;
|
|
|
|
+ mlog(ML_ERROR,
|
|
|
|
+ "Inode #%llu contains a hole at offset %llu\n",
|
|
|
|
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
|
|
|
|
+ (unsigned long long)(v_block + done) <<
|
|
|
|
+ inode->i_sb->s_blocksize_bits);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ count = nr - done;
|
|
|
|
+ if (p_count < count)
|
|
|
|
+ count = p_count;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the caller passed us bhs, they should have come
|
|
|
|
+ * from a previous readahead call to this function. Thus,
|
|
|
|
+ * they should have the right b_blocknr.
|
|
|
|
+ */
|
|
|
|
+ for (i = 0; i < count; i++) {
|
|
|
|
+ if (!bhs[done + i])
|
|
|
|
+ continue;
|
|
|
|
+ BUG_ON(bhs[done + i]->b_blocknr != (p_block + i));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = ocfs2_read_blocks(inode, p_block, count, bhs + done,
|
|
|
|
+ flags, validate);
|
|
|
|
+ if (rc) {
|
|
|
|
+ mlog_errno(rc);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ done += count;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ mlog_exit(rc);
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|