static int read_log_rec_buf(struct ntfs_log *log,
			    const struct LFS_RECORD_HDR *rh, void *buffer)
{
	int err;
	struct RECORD_PAGE_HDR *ph = NULL;
	u64 lsn = le64_to_cpu(rh->this_lsn);
	u32 vbo = lsn_to_vbo(log, lsn) & ~log->page_mask;
	u32 off = lsn_to_page_off(log, lsn) + log->record_header_len;
	u32 data_len = le32_to_cpu(rh->client_data_len);

	/*
	 * While there are more bytes to transfer,
	 * we continue to attempt to perform the read.
	 */
	for (;;) {
		bool usa_error;
		u32 tail = log->page_size - off;

		if (tail >= data_len)
			tail = data_len;

		data_len -= tail;

		err = read_log_page(log, vbo, &ph, &usa_error);
		if (err)
			goto out;

		/*
		 * The last lsn on this page better be greater or equal
		 * to the lsn we are copying.
		 */
		if (lsn > le64_to_cpu(ph->rhdr.lsn)) {
			err = -EINVAL;
			goto out;
		}

		memcpy(buffer, Add2Ptr(ph, off), tail);

		/* If there are no more bytes to transfer, we exit the loop. */
		if (!data_len) {
			if (!is_log_record_end(ph) ||
			    lsn > le64_to_cpu(ph->record_hdr.last_end_lsn)) {
				err = -EINVAL;
				goto out;
			}
			break;
		}

		if (ph->rhdr.lsn == ph->record_hdr.last_end_lsn ||
		    lsn > le64_to_cpu(ph->rhdr.lsn)) {
			err = -EINVAL;
			goto out;
		}

		vbo = next_page_off(log, vbo);
		off = log->data_off;

		/*
		 * Adjust our pointer the user's buffer to transfer
		 * the next block to.
		 */
		buffer = Add2Ptr(buffer, tail);
	}

out:
	kfree(ph);
	return err;
}
static int read_log_rec_buf(struct ntfs_log *log,
			    const struct LFS_RECORD_HDR *rh, void *buffer)
{
	int err;
	struct RECORD_PAGE_HDR *ph = NULL;
	u64 lsn = le64_to_cpu(rh->this_lsn);
	u32 vbo = lsn_to_vbo(log, lsn) & ~log->page_mask;
	u32 off = lsn_to_page_off(log, lsn) + log->record_header_len;
	u32 data_len = le32_to_cpu(rh->client_data_len);

	 
	for (;;) {
		bool usa_error;
		u32 tail = log->page_size - off;

		if (tail >= data_len)
			tail = data_len;

		data_len -= tail;

		err = read_log_page(log, vbo, &ph, &usa_error);
		if (err)
			goto out;

		 
		if (lsn > le64_to_cpu(ph->rhdr.lsn)) {
			err = -EINVAL;
			goto out;
		}

		memcpy(buffer, Add2Ptr(ph, off), tail);

		 
		if (!data_len) {
			if (!is_log_record_end(ph) ||
			    lsn > le64_to_cpu(ph->record_hdr.last_end_lsn)) {
				err = -EINVAL;
				goto out;
			}
			break;
		}

		if (ph->rhdr.lsn == ph->record_hdr.last_end_lsn ||
		    lsn > le64_to_cpu(ph->rhdr.lsn)) {
			err = -EINVAL;
			goto out;
		}

		vbo = next_page_off(log, vbo);
		off = log->data_off;

		 
		buffer = Add2Ptr(buffer, tail);
	}

out:
	kfree(ph);
	return err;
}