Whamcloud - gitweb
LU-137 osd-ldiskfs: pass through resize ioctl
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_integrity.c
index 3a6433d..a6b4978 100644 (file)
  * Codes copied from kernel 3.10.0-862.el7
  * drivers/scsi/sd_dif.c and block/t10-pi.c
  */
-#include <linux/blkdev.h>
+#ifdef HAVE_LINUX_BLK_INTEGRITY_HEADER
+ #include <linux/blk-integrity.h>
+#else
+ #include <linux/blkdev.h>
+#endif
 #include <linux/blk_types.h>
 
 #include <obd_cksum.h>
 #include "osd_internal.h"
 
 #if IS_ENABLED(CONFIG_CRC_T10DIF)
+#ifdef HAVE_BLK_INTEGRITY_ITER
+# define blk_status_gen blk_status_t
+# define RETURN_GEN(_gen_fn) return _gen_fn
+#else
+# define blk_status_gen void
+# define RETURN_GEN(_gen_fn) _gen_fn
+# define blk_integrity_iter blk_integrity_exchg
+# define interval sector_size
+# define seed sector
+# define blk_status_t int
+# define BLK_STS_PROTECTION -EIO
+# define BLK_STS_OK 0
+#endif
 /*
  * Data Integrity Field tuple.
  */
-struct sd_dif_tuple {
+struct t10_pi_tuple {
        __be16 guard_tag;        /* Checksum */
        __be16 app_tag;          /* Opaque storage */
        __be32 ref_tag;          /* Target LBA or indirect LBA */
 };
 
+#define T10_PI_APP_ESCAPE cpu_to_be16(0xffff)
+#define T10_PI_REF_ESCAPE cpu_to_be32(0xffffffff)
+
+static struct niobuf_local *find_lnb(struct blk_integrity_iter *iter)
+{
+       struct bio *bio = iter->bio;
+       struct bio_vec *bv = &bio->bi_io_vec[iter->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 + iter->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.
+ * 16 bit app tag, 32 bit reference tag (sector number).
+ *
+ * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
+ * tag space.
  */
-static void osd_dif_type1_generate(struct blk_integrity_exchg *bix,
-                                  obd_dif_csum_fn *fn)
+static blk_status_gen osd_dif_generate(struct blk_integrity_iter *iter,
+                               obd_dif_csum_fn *fn, enum osd_t10_type type)
 {
-       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;
-       sector_t sector = bix->sector;
+       struct niobuf_local *lnb = find_lnb(iter);
+       __be16 *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) {
-                       sdt->guard_tag = *guard_buf;
+       ENTRY;
+       for (i = 0 ; i < iter->data_size ; i += iter->interval) {
+               struct t10_pi_tuple *pi = iter->prot_buf;
+
+               if (lnb && lnb->lnb_guard_rpc) {
+                       pi->guard_tag = *guard_buf;
                        guard_buf++;
-               } else
-                       sdt->guard_tag = fn(buf, bix->sector_size);
-               sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
-               sdt->app_tag = 0;
+               } else {
+                       pi->guard_tag = fn(iter->data_buf, iter->interval);
+               }
+               pi->app_tag = 0;
 
-               buf += bix->sector_size;
-               sector++;
+               if (type == OSD_T10_TYPE1)
+                       pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed));
+               else /* if (type == OSD_T10_TYPE3) */
+                       pi->ref_tag = 0;
+
+               iter->data_buf += iter->interval;
+               iter->prot_buf += sizeof(struct t10_pi_tuple);
+               iter->seed++;
        }
-}
 
-static void osd_dif_type1_generate_crc(struct blk_integrity_exchg *bix)
-{
-       osd_dif_type1_generate(bix, obd_dif_crc_fn);
+#ifdef HAVE_BLK_INTEGRITY_ITER
+       RETURN(BLK_STS_OK);
+#else
+       RETURN_EXIT;
+#endif
 }
 
-static void osd_dif_type1_generate_ip(struct blk_integrity_exchg *bix)
+static blk_status_t osd_dif_verify(struct blk_integrity_iter *iter,
+                                  obd_dif_csum_fn *fn, enum osd_t10_type type)
 {
-       osd_dif_type1_generate(bix, obd_dif_ip_fn);
-}
-
-static int osd_dif_type1_verify(struct blk_integrity_exchg *bix,
-                               obd_dif_csum_fn *fn)
-{
-       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;
-       sector_t sector = bix->sector;
+       struct niobuf_local *lnb = find_lnb(iter);
+       __be16 *guard_buf = lnb ? lnb->lnb_guards : NULL;
        unsigned int i;
-       __u16 csum;
-
-       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
-               /* Unwritten sectors */
-               if (sdt->app_tag == 0xffff)
-                       return 0;
-
-               if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
-                       CERROR("%s: ref tag error on sector %lu (rcvd %u)\n",
-                              bix->disk_name, (unsigned long)sector,
-                              be32_to_cpu(sdt->ref_tag));
-                       return -EIO;
+
+       ENTRY;
+       for (i = 0 ; i < iter->data_size ; i += iter->interval) {
+               struct t10_pi_tuple *pi = iter->prot_buf;
+               __be16 csum;
+
+               if (type == OSD_T10_TYPE1 ||
+                   type == OSD_T10_TYPE2) {
+                       if (pi->app_tag == T10_PI_APP_ESCAPE) {
+                               lnb = NULL;
+                               goto next;
+                       }
+
+                       if (be32_to_cpu(pi->ref_tag) !=
+                           lower_32_bits(iter->seed)) {
+                               CERROR("%s: ref tag error at location %llu (rcvd %u): rc = %d\n",
+                                      iter->disk_name,
+                                      (unsigned long long)iter->seed,
+                                      be32_to_cpu(pi->ref_tag),
+                                      BLK_STS_PROTECTION);
+                               RETURN(BLK_STS_PROTECTION);
+                       }
+               } else  if (type == OSD_T10_TYPE3) {
+                       if (pi->app_tag == T10_PI_APP_ESCAPE &&
+                           pi->ref_tag == T10_PI_REF_ESCAPE) {
+                               lnb = NULL;
+                               goto next;
+                       }
                }
 
-               csum = fn(buf, bix->sector_size);
+               csum = fn(iter->data_buf, iter->interval);
 
-               if (sdt->guard_tag != csum) {
-                       CERROR("%s: guard tag error on sector %lu " \
-                              "(rcvd %04x, data %04x)\n", bix->disk_name,
-                              (unsigned long)sector,
-                              be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
-                       return -EIO;
+               if (pi->guard_tag != csum) {
+                       CERROR("%s: guard tag error on sector %llu (rcvd %04x, want %04x): rc = %d\n",
+                              iter->disk_name, (unsigned long long)iter->seed,
+                              be16_to_cpu(pi->guard_tag), be16_to_cpu(csum),
+                              BLK_STS_PROTECTION);
+                       RETURN(BLK_STS_PROTECTION);
                }
 
-               *guard_buf = csum;
-               guard_buf++;
+               if (guard_buf) {
+                       *guard_buf = csum;
+                       guard_buf++;
+               }
 
-               buf += bix->sector_size;
-               sector++;
+next:
+               iter->data_buf += iter->interval;
+               iter->prot_buf += sizeof(struct t10_pi_tuple);
+               iter->seed++;
        }
 
-       lnb->lnb_guard_disk = 1;
-       return 0;
+       if (lnb)
+               lnb->lnb_guard_disk = 1;
+
+       RETURN(BLK_STS_OK);
 }
 
-static int osd_dif_type1_verify_crc(struct blk_integrity_exchg *bix)
+static blk_status_gen osd_dif_type1_generate_crc(struct blk_integrity_iter *iter)
 {
-       return osd_dif_type1_verify(bix, obd_dif_crc_fn);
+       RETURN_GEN(osd_dif_generate(iter, obd_dif_crc_fn, OSD_T10_TYPE1));
 }
 
-static int osd_dif_type1_verify_ip(struct blk_integrity_exchg *bix)
+static blk_status_gen osd_dif_type1_generate_ip(struct blk_integrity_iter *iter)
 {
-       return osd_dif_type1_verify(bix, obd_dif_ip_fn);
+       RETURN_GEN(osd_dif_generate(iter, obd_dif_ip_fn, OSD_T10_TYPE1));
 }
 
-/*
- * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
- * tag space.
- */
-static void osd_dif_type3_generate(struct blk_integrity_exchg *bix,
-                                  obd_dif_csum_fn *fn)
+static blk_status_gen osd_dif_type3_generate_crc(struct blk_integrity_iter *iter)
 {
-       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;
-       unsigned int i;
-
-       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
-               if (lnb->lnb_guard_rpc) {
-                       sdt->guard_tag = *guard_buf;
-                       guard_buf++;
-               } else
-                       sdt->guard_tag = fn(buf, bix->sector_size);
-               sdt->ref_tag = 0;
-               sdt->app_tag = 0;
-
-               buf += bix->sector_size;
-       }
+       RETURN_GEN(osd_dif_generate(iter, obd_dif_crc_fn, OSD_T10_TYPE3));
 }
 
-static void osd_dif_type3_generate_crc(struct blk_integrity_exchg *bix)
+static blk_status_gen osd_dif_type3_generate_ip(struct blk_integrity_iter *iter)
 {
-       osd_dif_type3_generate(bix, obd_dif_crc_fn);
+       RETURN_GEN(osd_dif_generate(iter, obd_dif_ip_fn, OSD_T10_TYPE3));
 }
-
-static void osd_dif_type3_generate_ip(struct blk_integrity_exchg *bix)
+static blk_status_t osd_dif_type1_verify_crc(struct blk_integrity_iter *iter)
 {
-       osd_dif_type3_generate(bix, obd_dif_ip_fn);
+       return osd_dif_verify(iter, obd_dif_crc_fn, OSD_T10_TYPE1);
 }
 
-static int osd_dif_type3_verify(struct blk_integrity_exchg *bix,
-                               obd_dif_csum_fn *fn)
+static blk_status_t osd_dif_type1_verify_ip(struct blk_integrity_iter *iter)
 {
-       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;
-       sector_t sector = bix->sector;
-       unsigned int i;
-       __u16 csum;
-
-       for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
-               /* Unwritten sectors */
-               if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff)
-                       return 0;
-
-               csum = fn(buf, bix->sector_size);
-
-               if (sdt->guard_tag != csum) {
-                       CERROR("%s: guard tag error on sector %lu " \
-                              "(rcvd %04x, data %04x)\n", bix->disk_name,
-                              (unsigned long)sector,
-                              be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
-                       return -EIO;
-               }
-
-               *guard_buf = csum;
-               guard_buf++;
-
-               buf += bix->sector_size;
-               sector++;
-       }
-
-       lnb->lnb_guard_disk = 1;
-       return 0;
+       return osd_dif_verify(iter, obd_dif_ip_fn, OSD_T10_TYPE1);
 }
 
-static int osd_dif_type3_verify_crc(struct blk_integrity_exchg *bix)
+static blk_status_t osd_dif_type3_verify_crc(struct blk_integrity_iter *iter)
 {
-       return osd_dif_type3_verify(bix, obd_dif_crc_fn);
+       return osd_dif_verify(iter, obd_dif_crc_fn, OSD_T10_TYPE3);
 }
 
-static int osd_dif_type3_verify_ip(struct blk_integrity_exchg *bix)
+static blk_status_t osd_dif_type3_verify_ip(struct blk_integrity_iter *iter)
 {
-       return osd_dif_type3_verify(bix, obd_dif_ip_fn);
+       return osd_dif_verify(iter, obd_dif_ip_fn, OSD_T10_TYPE3);
 }
 
 int osd_get_integrity_profile(struct osd_device *osd,