__be32 ref_tag; /* Target LBA or indirect LBA */
};
+static struct niobuf_local *find_lnb(struct blk_integrity_exchg *bix)
+{
+ struct bio *bio = bix->bio;
+ struct bio_vec *bv = bio_iovec_idx(bio, bix->bi_idx);
+ struct osd_bio_private *bio_private = bio->bi_private;
+ struct osd_iobuf *iobuf = bio_private->obp_iobuf;
+ int index = bio_private->obp_start_page_idx + bix->bi_idx;
+ int i;
+
+ /*
+ * blocks are contiguous in bio but pages added to bio
+ * could have a gap comparing to iobuf->dr_pages.
+ * e.g. a page mapped to a hole in the middle.
+ */
+ for (i = index; i < iobuf->dr_npages; i++) {
+ if (iobuf->dr_pages[i] == bv->bv_page)
+ return iobuf->dr_lnbs[i];
+ }
+
+ return NULL;
+}
+
/*
* Type 1 and Type 2 protection use the same format: 16 bit guard tag,
* 16 bit app tag, 32 bit reference tag.
{
void *buf = bix->data_buf;
struct sd_dif_tuple *sdt = bix->prot_buf;
- struct bio *bio = bix->bio;
- struct osd_bio_private *bio_private = bio->bi_private;
- struct osd_iobuf *iobuf = bio_private->obp_iobuf;
- int index = bio_private->obp_start_page_idx + bix->bi_idx;
- struct niobuf_local *lnb = iobuf->dr_lnbs[index];
- __u16 *guard_buf = lnb->lnb_guards;
+ struct niobuf_local *lnb = find_lnb(bix);
+ __u16 *guard_buf = lnb ? lnb->lnb_guards : NULL;
sector_t sector = bix->sector;
unsigned int i;
for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
- if (lnb->lnb_guard_rpc) {
+ if (lnb && lnb->lnb_guard_rpc) {
sdt->guard_tag = *guard_buf;
guard_buf++;
} else
{
void *buf = bix->data_buf;
struct sd_dif_tuple *sdt = bix->prot_buf;
- struct bio *bio = bix->bio;
- struct osd_bio_private *bio_private = bio->bi_private;
- struct osd_iobuf *iobuf = bio_private->obp_iobuf;
- int index = bio_private->obp_start_page_idx + bix->bi_idx;
- struct niobuf_local *lnb = iobuf->dr_lnbs[index];
- __u16 *guard_buf = lnb->lnb_guards;
+ struct niobuf_local *lnb = find_lnb(bix);
+ __u16 *guard_buf = lnb ? lnb->lnb_guards : NULL;
sector_t sector = bix->sector;
unsigned int i;
__u16 csum;
return -EIO;
}
- *guard_buf = csum;
- guard_buf++;
+ if (guard_buf) {
+ *guard_buf = csum;
+ guard_buf++;
+ }
buf += bix->sector_size;
sector++;
}
- lnb->lnb_guard_disk = 1;
+ if (lnb)
+ lnb->lnb_guard_disk = 1;
return 0;
}
{
void *buf = bix->data_buf;
struct sd_dif_tuple *sdt = bix->prot_buf;
- struct bio *bio = bix->bio;
- struct osd_bio_private *bio_private = bio->bi_private;
- struct osd_iobuf *iobuf = bio_private->obp_iobuf;
- int index = bio_private->obp_start_page_idx + bix->bi_idx;
- struct niobuf_local *lnb = iobuf->dr_lnbs[index];
- __u16 *guard_buf = lnb->lnb_guards;
+ struct niobuf_local *lnb = find_lnb(bix);
+ __u16 *guard_buf = lnb ? lnb->lnb_guards : NULL;
unsigned int i;
for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
- if (lnb->lnb_guard_rpc) {
+ if (lnb && lnb->lnb_guard_rpc) {
sdt->guard_tag = *guard_buf;
guard_buf++;
} else
{
void *buf = bix->data_buf;
struct sd_dif_tuple *sdt = bix->prot_buf;
- struct bio *bio = bix->bio;
- struct osd_bio_private *bio_private = bio->bi_private;
- struct osd_iobuf *iobuf = bio_private->obp_iobuf;
- int index = bio_private->obp_start_page_idx + bix->bi_idx;
- struct niobuf_local *lnb = iobuf->dr_lnbs[index];
- __u16 *guard_buf = lnb->lnb_guards;
+ struct niobuf_local *lnb = find_lnb(bix);
+ __u16 *guard_buf = lnb ? lnb->lnb_guards : NULL;
sector_t sector = bix->sector;
unsigned int i;
__u16 csum;
return -EIO;
}
- *guard_buf = csum;
- guard_buf++;
+ if (guard_buf) {
+ *guard_buf = csum;
+ guard_buf++;
+ }
buf += bix->sector_size;
sector++;
}
- lnb->lnb_guard_disk = 1;
+ if (lnb)
+ lnb->lnb_guard_disk = 1;
return 0;
}
{
struct blk_integrity *bi = bdev_get_integrity(bdev);
struct bio_integrity_payload *bip = bio->bi_integrity;
- struct niobuf_local *lnb;
+ struct niobuf_local *lnb = NULL;
unsigned short sector_size = blk_integrity_interval(bi);
void *bio_prot_buf = page_address(bip->bip_vec->bv_page) +
bip->bip_vec->bv_offset;
struct bio_vec *bv;
sector_t sector = bio_start_sector(bio);
- unsigned int sectors, total;
+ unsigned int j, sectors, total;
DECLARE_BVEC_ITER_ALL(iter_all);
__u16 *expected_guard;
int rc;
total = 0;
bio_for_each_segment_all(bv, bio, iter_all) {
- lnb = iobuf->dr_lnbs[index];
+ for (j = index; j < iobuf->dr_npages; j++) {
+ if (iobuf->dr_pages[j] == bv->bv_page) {
+ lnb = iobuf->dr_lnbs[j];
+ break;
+ }
+ }
+ if (!lnb)
+ continue;
expected_guard = lnb->lnb_guards;
sectors = bv->bv_len / sector_size;
if (lnb->lnb_guard_rpc) {
total += sectors * bi->tuple_size;
LASSERT(total <= bip_size(bio->bi_integrity));
index++;
+ lnb = NULL;
}
return 0;
}
rm -f $F77_TMP
unset F77_TMP
+check_filefrag_77n() {
+ local nr_ext=0
+ local starts=()
+ local ends=()
+
+ while read extidx a b start end rest; do
+ if [[ "${extidx}" =~ ^[0-9]+: ]]; then
+ nr_ext=$(( $nr_ext + 1 ))
+ starts+=( ${start%..} )
+ ends+=( ${end%:} )
+ fi
+ done < <( filefrag -sv $1 )
+
+ [[ $nr_ext -eq 2 ]] && [[ "${starts[-1]}" == $(( ${ends[0]} + 1 )) ]] && return 0
+ return 1
+}
+
+test_77n() {
+ [[ "$CKSUM_TYPES" =~ t10 ]] || skip "no T10 checksum support on osc"
+
+ touch $DIR/$tfile
+ $TRUNCATE $DIR/$tfile 0
+ dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=0
+ dd if=/dev/urandom of=$DIR/$tfile bs=4k conv=notrunc count=1 seek=2
+ check_filefrag_77n $DIR/$tfile ||
+ skip "$tfile blocks not contiguous around hole"
+
+ set_checksums 1
+ stack_trap "set_checksums $ORIG_CSUM" EXIT
+ stack_trap "set_checksum_type $ORIG_CSUM_TYPE" EXIT
+ stack_trap "rm -f $DIR/$tfile"
+
+ for algo in $CKSUM_TYPES; do
+ if [[ "$algo" =~ ^t10 ]]; then
+ set_checksum_type $algo ||
+ error "fail to set checksum type $algo"
+ dd if=$DIR/$tfile of=/dev/null bs=12k count=1 iflag=direct ||
+ error "fail to read $tfile with $algo"
+ fi
+ done
+ rm -f $DIR/$tfile
+ return 0
+}
+run_test 77n "Verify read from a hole inside contiguous blocks with T10PI"
+
cleanup_test_78() {
trap 0
rm -f $DIR/$tfile