linux/block/bio-integrity.c
<<
>>
Prefs
   1/*
   2 * bio-integrity.c - bio data integrity extensions
   3 *
   4 * Copyright (C) 2007, 2008, 2009 Oracle Corporation
   5 * Written by: Martin K. Petersen <martin.petersen@oracle.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License version
   9 * 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; see the file COPYING.  If not, write to
  18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  19 * USA.
  20 *
  21 */
  22
  23#include <linux/blkdev.h>
  24#include <linux/mempool.h>
  25#include <linux/export.h>
  26#include <linux/bio.h>
  27#include <linux/workqueue.h>
  28#include <linux/slab.h>
  29
  30#define BIP_INLINE_VECS 4
  31
  32static struct kmem_cache *bip_slab;
  33static struct workqueue_struct *kintegrityd_wq;
  34
  35/**
  36 * bio_integrity_alloc - Allocate integrity payload and attach it to bio
  37 * @bio:        bio to attach integrity metadata to
  38 * @gfp_mask:   Memory allocation mask
  39 * @nr_vecs:    Number of integrity metadata scatter-gather elements
  40 *
  41 * Description: This function prepares a bio for attaching integrity
  42 * metadata.  nr_vecs specifies the maximum number of pages containing
  43 * integrity metadata that can be attached.
  44 */
  45struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
  46                                                  gfp_t gfp_mask,
  47                                                  unsigned int nr_vecs)
  48{
  49        struct bio_integrity_payload *bip;
  50        struct bio_set *bs = bio->bi_pool;
  51        unsigned long idx = BIO_POOL_NONE;
  52        unsigned inline_vecs;
  53
  54        if (!bs) {
  55                bip = kmalloc(sizeof(struct bio_integrity_payload) +
  56                              sizeof(struct bio_vec) * nr_vecs, gfp_mask);
  57                inline_vecs = nr_vecs;
  58        } else {
  59                bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
  60                inline_vecs = BIP_INLINE_VECS;
  61        }
  62
  63        if (unlikely(!bip))
  64                return NULL;
  65
  66        memset(bip, 0, sizeof(*bip));
  67
  68        if (nr_vecs > inline_vecs) {
  69                bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
  70                                          bs->bvec_integrity_pool);
  71                if (!bip->bip_vec)
  72                        goto err;
  73        } else {
  74                bip->bip_vec = bip->bip_inline_vecs;
  75        }
  76
  77        bip->bip_slab = idx;
  78        bip->bip_bio = bio;
  79        bio->bi_integrity = bip;
  80
  81        return bip;
  82err:
  83        mempool_free(bip, bs->bio_integrity_pool);
  84        return NULL;
  85}
  86EXPORT_SYMBOL(bio_integrity_alloc);
  87
  88/**
  89 * bio_integrity_free - Free bio integrity payload
  90 * @bio:        bio containing bip to be freed
  91 *
  92 * Description: Used to free the integrity portion of a bio. Usually
  93 * called from bio_free().
  94 */
  95void bio_integrity_free(struct bio *bio)
  96{
  97        struct bio_integrity_payload *bip = bio->bi_integrity;
  98        struct bio_set *bs = bio->bi_pool;
  99
 100        if (bip->bip_owns_buf)
 101                kfree(bip->bip_buf);
 102
 103        if (bs) {
 104                if (bip->bip_slab != BIO_POOL_NONE)
 105                        bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
 106                                  bip->bip_slab);
 107
 108                mempool_free(bip, bs->bio_integrity_pool);
 109        } else {
 110                kfree(bip);
 111        }
 112
 113        bio->bi_integrity = NULL;
 114}
 115EXPORT_SYMBOL(bio_integrity_free);
 116
 117static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip)
 118{
 119        if (bip->bip_slab == BIO_POOL_NONE)
 120                return BIP_INLINE_VECS;
 121
 122        return bvec_nr_vecs(bip->bip_slab);
 123}
 124
 125/**
 126 * bio_integrity_add_page - Attach integrity metadata
 127 * @bio:        bio to update
 128 * @page:       page containing integrity metadata
 129 * @len:        number of bytes of integrity metadata in page
 130 * @offset:     start offset within page
 131 *
 132 * Description: Attach a page containing integrity metadata to bio.
 133 */
 134int bio_integrity_add_page(struct bio *bio, struct page *page,
 135                           unsigned int len, unsigned int offset)
 136{
 137        struct bio_integrity_payload *bip = bio->bi_integrity;
 138        struct bio_vec *iv;
 139
 140        if (bip->bip_vcnt >= bip_integrity_vecs(bip)) {
 141                printk(KERN_ERR "%s: bip_vec full\n", __func__);
 142                return 0;
 143        }
 144
 145        iv = bip->bip_vec + bip->bip_vcnt;
 146
 147        iv->bv_page = page;
 148        iv->bv_len = len;
 149        iv->bv_offset = offset;
 150        bip->bip_vcnt++;
 151
 152        return len;
 153}
 154EXPORT_SYMBOL(bio_integrity_add_page);
 155
 156static int bdev_integrity_enabled(struct block_device *bdev, int rw)
 157{
 158        struct blk_integrity *bi = bdev_get_integrity(bdev);
 159
 160        if (bi == NULL)
 161                return 0;
 162
 163        if (rw == READ && bi->verify_fn != NULL &&
 164            (bi->flags & INTEGRITY_FLAG_READ))
 165                return 1;
 166
 167        if (rw == WRITE && bi->generate_fn != NULL &&
 168            (bi->flags & INTEGRITY_FLAG_WRITE))
 169                return 1;
 170
 171        return 0;
 172}
 173
 174/**
 175 * bio_integrity_enabled - Check whether integrity can be passed
 176 * @bio:        bio to check
 177 *
 178 * Description: Determines whether bio_integrity_prep() can be called
 179 * on this bio or not.  bio data direction and target device must be
 180 * set prior to calling.  The functions honors the write_generate and
 181 * read_verify flags in sysfs.
 182 */
 183int bio_integrity_enabled(struct bio *bio)
 184{
 185        if (!bio_is_rw(bio))
 186                return 0;
 187
 188        /* Already protected? */
 189        if (bio_integrity(bio))
 190                return 0;
 191
 192        return bdev_integrity_enabled(bio->bi_bdev, bio_data_dir(bio));
 193}
 194EXPORT_SYMBOL(bio_integrity_enabled);
 195
 196/**
 197 * bio_integrity_hw_sectors - Convert 512b sectors to hardware ditto
 198 * @bi:         blk_integrity profile for device
 199 * @sectors:    Number of 512 sectors to convert
 200 *
 201 * Description: The block layer calculates everything in 512 byte
 202 * sectors but integrity metadata is done in terms of the hardware
 203 * sector size of the storage device.  Convert the block layer sectors
 204 * to physical sectors.
 205 */
 206static inline unsigned int bio_integrity_hw_sectors(struct blk_integrity *bi,
 207                                                    unsigned int sectors)
 208{
 209        /* At this point there are only 512b or 4096b DIF/EPP devices */
 210        if (bi->sector_size == 4096)
 211                return sectors >>= 3;
 212
 213        return sectors;
 214}
 215
 216static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
 217                                               unsigned int sectors)
 218{
 219        return bio_integrity_hw_sectors(bi, sectors) * bi->tuple_size;
 220}
 221
 222/**
 223 * bio_integrity_tag_size - Retrieve integrity tag space
 224 * @bio:        bio to inspect
 225 *
 226 * Description: Returns the maximum number of tag bytes that can be
 227 * attached to this bio. Filesystems can use this to determine how
 228 * much metadata to attach to an I/O.
 229 */
 230unsigned int bio_integrity_tag_size(struct bio *bio)
 231{
 232        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 233
 234        BUG_ON(bio->bi_iter.bi_size == 0);
 235
 236        return bi->tag_size * (bio->bi_iter.bi_size / bi->sector_size);
 237}
 238EXPORT_SYMBOL(bio_integrity_tag_size);
 239
 240static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len,
 241                             int set)
 242{
 243        struct bio_integrity_payload *bip = bio->bi_integrity;
 244        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 245        unsigned int nr_sectors;
 246
 247        BUG_ON(bip->bip_buf == NULL);
 248
 249        if (bi->tag_size == 0)
 250                return -1;
 251
 252        nr_sectors = bio_integrity_hw_sectors(bi,
 253                                        DIV_ROUND_UP(len, bi->tag_size));
 254
 255        if (nr_sectors * bi->tuple_size > bip->bip_iter.bi_size) {
 256                printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", __func__,
 257                       nr_sectors * bi->tuple_size, bip->bip_iter.bi_size);
 258                return -1;
 259        }
 260
 261        if (set)
 262                bi->set_tag_fn(bip->bip_buf, tag_buf, nr_sectors);
 263        else
 264                bi->get_tag_fn(bip->bip_buf, tag_buf, nr_sectors);
 265
 266        return 0;
 267}
 268
 269/**
 270 * bio_integrity_set_tag - Attach a tag buffer to a bio
 271 * @bio:        bio to attach buffer to
 272 * @tag_buf:    Pointer to a buffer containing tag data
 273 * @len:        Length of the included buffer
 274 *
 275 * Description: Use this function to tag a bio by leveraging the extra
 276 * space provided by devices formatted with integrity protection.  The
 277 * size of the integrity buffer must be <= to the size reported by
 278 * bio_integrity_tag_size().
 279 */
 280int bio_integrity_set_tag(struct bio *bio, void *tag_buf, unsigned int len)
 281{
 282        BUG_ON(bio_data_dir(bio) != WRITE);
 283
 284        return bio_integrity_tag(bio, tag_buf, len, 1);
 285}
 286EXPORT_SYMBOL(bio_integrity_set_tag);
 287
 288/**
 289 * bio_integrity_get_tag - Retrieve a tag buffer from a bio
 290 * @bio:        bio to retrieve buffer from
 291 * @tag_buf:    Pointer to a buffer for the tag data
 292 * @len:        Length of the target buffer
 293 *
 294 * Description: Use this function to retrieve the tag buffer from a
 295 * completed I/O. The size of the integrity buffer must be <= to the
 296 * size reported by bio_integrity_tag_size().
 297 */
 298int bio_integrity_get_tag(struct bio *bio, void *tag_buf, unsigned int len)
 299{
 300        BUG_ON(bio_data_dir(bio) != READ);
 301
 302        return bio_integrity_tag(bio, tag_buf, len, 0);
 303}
 304EXPORT_SYMBOL(bio_integrity_get_tag);
 305
 306/**
 307 * bio_integrity_generate_verify - Generate/verify integrity metadata for a bio
 308 * @bio:        bio to generate/verify integrity metadata for
 309 * @operate:    operate number, 1 for generate, 0 for verify
 310 */
 311static int bio_integrity_generate_verify(struct bio *bio, int operate)
 312{
 313        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 314        struct blk_integrity_exchg bix;
 315        struct bio_vec *bv;
 316        sector_t sector;
 317        unsigned int sectors, ret = 0, i;
 318        void *prot_buf = bio->bi_integrity->bip_buf;
 319
 320        if (operate)
 321                sector = bio->bi_iter.bi_sector;
 322        else
 323                sector = bio->bi_integrity->bip_iter.bi_sector;
 324
 325        bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
 326        bix.sector_size = bi->sector_size;
 327
 328        bio_for_each_segment_all(bv, bio, i) {
 329                void *kaddr = kmap_atomic(bv->bv_page);
 330                bix.data_buf = kaddr + bv->bv_offset;
 331                bix.data_size = bv->bv_len;
 332                bix.prot_buf = prot_buf;
 333                bix.sector = sector;
 334
 335                if (operate)
 336                        bi->generate_fn(&bix);
 337                else {
 338                        ret = bi->verify_fn(&bix);
 339                        if (ret) {
 340                                kunmap_atomic(kaddr);
 341                                return ret;
 342                        }
 343                }
 344
 345                sectors = bv->bv_len / bi->sector_size;
 346                sector += sectors;
 347                prot_buf += sectors * bi->tuple_size;
 348
 349                kunmap_atomic(kaddr);
 350        }
 351        return ret;
 352}
 353
 354/**
 355 * bio_integrity_generate - Generate integrity metadata for a bio
 356 * @bio:        bio to generate integrity metadata for
 357 *
 358 * Description: Generates integrity metadata for a bio by calling the
 359 * block device's generation callback function.  The bio must have a
 360 * bip attached with enough room to accommodate the generated
 361 * integrity metadata.
 362 */
 363static void bio_integrity_generate(struct bio *bio)
 364{
 365        bio_integrity_generate_verify(bio, 1);
 366}
 367
 368static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
 369{
 370        if (bi)
 371                return bi->tuple_size;
 372
 373        return 0;
 374}
 375
 376/**
 377 * bio_integrity_prep - Prepare bio for integrity I/O
 378 * @bio:        bio to prepare
 379 *
 380 * Description: Allocates a buffer for integrity metadata, maps the
 381 * pages and attaches them to a bio.  The bio must have data
 382 * direction, target device and start sector set priot to calling.  In
 383 * the WRITE case, integrity metadata will be generated using the
 384 * block device's integrity function.  In the READ case, the buffer
 385 * will be prepared for DMA and a suitable end_io handler set up.
 386 */
 387int bio_integrity_prep(struct bio *bio)
 388{
 389        struct bio_integrity_payload *bip;
 390        struct blk_integrity *bi;
 391        struct request_queue *q;
 392        void *buf;
 393        unsigned long start, end;
 394        unsigned int len, nr_pages;
 395        unsigned int bytes, offset, i;
 396        unsigned int sectors;
 397
 398        bi = bdev_get_integrity(bio->bi_bdev);
 399        q = bdev_get_queue(bio->bi_bdev);
 400        BUG_ON(bi == NULL);
 401        BUG_ON(bio_integrity(bio));
 402
 403        sectors = bio_integrity_hw_sectors(bi, bio_sectors(bio));
 404
 405        /* Allocate kernel buffer for protection data */
 406        len = sectors * blk_integrity_tuple_size(bi);
 407        buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
 408        if (unlikely(buf == NULL)) {
 409                printk(KERN_ERR "could not allocate integrity buffer\n");
 410                return -ENOMEM;
 411        }
 412
 413        end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 414        start = ((unsigned long) buf) >> PAGE_SHIFT;
 415        nr_pages = end - start;
 416
 417        /* Allocate bio integrity payload and integrity vectors */
 418        bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
 419        if (unlikely(bip == NULL)) {
 420                printk(KERN_ERR "could not allocate data integrity bioset\n");
 421                kfree(buf);
 422                return -EIO;
 423        }
 424
 425        bip->bip_owns_buf = 1;
 426        bip->bip_buf = buf;
 427        bip->bip_iter.bi_size = len;
 428        bip->bip_iter.bi_sector = bio->bi_iter.bi_sector;
 429
 430        /* Map it */
 431        offset = offset_in_page(buf);
 432        for (i = 0 ; i < nr_pages ; i++) {
 433                int ret;
 434                bytes = PAGE_SIZE - offset;
 435
 436                if (len <= 0)
 437                        break;
 438
 439                if (bytes > len)
 440                        bytes = len;
 441
 442                ret = bio_integrity_add_page(bio, virt_to_page(buf),
 443                                             bytes, offset);
 444
 445                if (ret == 0)
 446                        return 0;
 447
 448                if (ret < bytes)
 449                        break;
 450
 451                buf += bytes;
 452                len -= bytes;
 453                offset = 0;
 454        }
 455
 456        /* Install custom I/O completion handler if read verify is enabled */
 457        if (bio_data_dir(bio) == READ) {
 458                bip->bip_end_io = bio->bi_end_io;
 459                bio->bi_end_io = bio_integrity_endio;
 460        }
 461
 462        /* Auto-generate integrity metadata if this is a write */
 463        if (bio_data_dir(bio) == WRITE)
 464                bio_integrity_generate(bio);
 465
 466        return 0;
 467}
 468EXPORT_SYMBOL(bio_integrity_prep);
 469
 470/**
 471 * bio_integrity_verify - Verify integrity metadata for a bio
 472 * @bio:        bio to verify
 473 *
 474 * Description: This function is called to verify the integrity of a
 475 * bio.  The data in the bio io_vec is compared to the integrity
 476 * metadata returned by the HBA.
 477 */
 478static int bio_integrity_verify(struct bio *bio)
 479{
 480        return bio_integrity_generate_verify(bio, 0);
 481}
 482
 483/**
 484 * bio_integrity_verify_fn - Integrity I/O completion worker
 485 * @work:       Work struct stored in bio to be verified
 486 *
 487 * Description: This workqueue function is called to complete a READ
 488 * request.  The function verifies the transferred integrity metadata
 489 * and then calls the original bio end_io function.
 490 */
 491static void bio_integrity_verify_fn(struct work_struct *work)
 492{
 493        struct bio_integrity_payload *bip =
 494                container_of(work, struct bio_integrity_payload, bip_work);
 495        struct bio *bio = bip->bip_bio;
 496        int error;
 497
 498        error = bio_integrity_verify(bio);
 499
 500        /* Restore original bio completion handler */
 501        bio->bi_end_io = bip->bip_end_io;
 502        bio_endio_nodec(bio, error);
 503}
 504
 505/**
 506 * bio_integrity_endio - Integrity I/O completion function
 507 * @bio:        Protected bio
 508 * @error:      Pointer to errno
 509 *
 510 * Description: Completion for integrity I/O
 511 *
 512 * Normally I/O completion is done in interrupt context.  However,
 513 * verifying I/O integrity is a time-consuming task which must be run
 514 * in process context.  This function postpones completion
 515 * accordingly.
 516 */
 517void bio_integrity_endio(struct bio *bio, int error)
 518{
 519        struct bio_integrity_payload *bip = bio->bi_integrity;
 520
 521        BUG_ON(bip->bip_bio != bio);
 522
 523        /* In case of an I/O error there is no point in verifying the
 524         * integrity metadata.  Restore original bio end_io handler
 525         * and run it.
 526         */
 527        if (error) {
 528                bio->bi_end_io = bip->bip_end_io;
 529                bio_endio(bio, error);
 530
 531                return;
 532        }
 533
 534        INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
 535        queue_work(kintegrityd_wq, &bip->bip_work);
 536}
 537EXPORT_SYMBOL(bio_integrity_endio);
 538
 539/**
 540 * bio_integrity_advance - Advance integrity vector
 541 * @bio:        bio whose integrity vector to update
 542 * @bytes_done: number of data bytes that have been completed
 543 *
 544 * Description: This function calculates how many integrity bytes the
 545 * number of completed data bytes correspond to and advances the
 546 * integrity vector accordingly.
 547 */
 548void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
 549{
 550        struct bio_integrity_payload *bip = bio->bi_integrity;
 551        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 552        unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
 553
 554        bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
 555}
 556EXPORT_SYMBOL(bio_integrity_advance);
 557
 558/**
 559 * bio_integrity_trim - Trim integrity vector
 560 * @bio:        bio whose integrity vector to update
 561 * @offset:     offset to first data sector
 562 * @sectors:    number of data sectors
 563 *
 564 * Description: Used to trim the integrity vector in a cloned bio.
 565 * The ivec will be advanced corresponding to 'offset' data sectors
 566 * and the length will be truncated corresponding to 'len' data
 567 * sectors.
 568 */
 569void bio_integrity_trim(struct bio *bio, unsigned int offset,
 570                        unsigned int sectors)
 571{
 572        struct bio_integrity_payload *bip = bio->bi_integrity;
 573        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 574
 575        bio_integrity_advance(bio, offset << 9);
 576        bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors);
 577}
 578EXPORT_SYMBOL(bio_integrity_trim);
 579
 580/**
 581 * bio_integrity_clone - Callback for cloning bios with integrity metadata
 582 * @bio:        New bio
 583 * @bio_src:    Original bio
 584 * @gfp_mask:   Memory allocation mask
 585 *
 586 * Description: Called to allocate a bip when cloning a bio
 587 */
 588int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
 589                        gfp_t gfp_mask)
 590{
 591        struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
 592        struct bio_integrity_payload *bip;
 593
 594        BUG_ON(bip_src == NULL);
 595
 596        bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
 597
 598        if (bip == NULL)
 599                return -EIO;
 600
 601        memcpy(bip->bip_vec, bip_src->bip_vec,
 602               bip_src->bip_vcnt * sizeof(struct bio_vec));
 603
 604        bip->bip_vcnt = bip_src->bip_vcnt;
 605        bip->bip_iter = bip_src->bip_iter;
 606
 607        return 0;
 608}
 609EXPORT_SYMBOL(bio_integrity_clone);
 610
 611int bioset_integrity_create(struct bio_set *bs, int pool_size)
 612{
 613        if (bs->bio_integrity_pool)
 614                return 0;
 615
 616        bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab);
 617        if (!bs->bio_integrity_pool)
 618                return -1;
 619
 620        bs->bvec_integrity_pool = biovec_create_pool(pool_size);
 621        if (!bs->bvec_integrity_pool) {
 622                mempool_destroy(bs->bio_integrity_pool);
 623                return -1;
 624        }
 625
 626        return 0;
 627}
 628EXPORT_SYMBOL(bioset_integrity_create);
 629
 630void bioset_integrity_free(struct bio_set *bs)
 631{
 632        if (bs->bio_integrity_pool)
 633                mempool_destroy(bs->bio_integrity_pool);
 634
 635        if (bs->bvec_integrity_pool)
 636                mempool_destroy(bs->bvec_integrity_pool);
 637}
 638EXPORT_SYMBOL(bioset_integrity_free);
 639
 640void __init bio_integrity_init(void)
 641{
 642        /*
 643         * kintegrityd won't block much but may burn a lot of CPU cycles.
 644         * Make it highpri CPU intensive wq with max concurrency of 1.
 645         */
 646        kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
 647                                         WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
 648        if (!kintegrityd_wq)
 649                panic("Failed to create kintegrityd\n");
 650
 651        bip_slab = kmem_cache_create("bio_integrity_payload",
 652                                     sizeof(struct bio_integrity_payload) +
 653                                     sizeof(struct bio_vec) * BIP_INLINE_VECS,
 654                                     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
 655        if (!bip_slab)
 656                panic("Failed to create slab\n");
 657}
 658