/** * Initialize super sector. * * @super_sect super sector image to initialize. * @lbs logical block size. * @pbs physical block size. * @ddev_lb device size [logical block]. * @ldev_lb log device size [logical block] * @name name of the walb device, or NULL. * * RETURN: * true in success. */ bool init_super_sector_raw( struct walb_super_sector* super_sect, unsigned int lbs, unsigned int pbs, u64 ddev_lb, u64 ldev_lb, const char *name) { u32 salt; char *rname; bool ret; ASSERT(super_sect); ASSERT(0 < lbs); ASSERT(0 < pbs); ASSERT(0 < ddev_lb); ASSERT(0 < ldev_lb); ASSERT(sizeof(struct walb_super_sector) <= (size_t)pbs); /* Prepare super sector */ memset(super_sect, 0, sizeof(*super_sect)); /* Set sector type. */ super_sect->sector_type = SECTOR_TYPE_SUPER; /* Fill parameters. */ super_sect->version = WALB_LOG_VERSION; super_sect->logical_bs = lbs; super_sect->physical_bs = pbs; super_sect->metadata_size = 0; /* currently fixed */ ret = generate_uuid(super_sect->uuid); if (!ret) { return false; } memset_random((u8 *)&salt, sizeof(salt)); LOGn("salt: %"PRIu32"\n", salt); super_sect->log_checksum_salt = salt; super_sect->ring_buffer_size = ldev_lb / (pbs / lbs) - get_ring_buffer_offset(pbs); super_sect->oldest_lsid = 0; super_sect->written_lsid = 0; super_sect->device_size = ddev_lb; rname = set_super_sector_name(super_sect, name); if (name && strlen(name) != strlen(rname)) { printf("name %s is pruned to %s.\n", name, rname); } ASSERT(is_valid_super_sector_raw(super_sect, pbs)); return true; }
/** * Clear log and detect resize of log device. * * @wdev walb dev. * @ctl ioctl data. * RETURN: * 0 in success, or -EFAULT. */ static int ioctl_wdev_clear_log(struct walb_dev *wdev, struct walb_ctl *ctl) { u64 new_ldev_size, old_ldev_size; u8 new_uuid[UUID_SIZE], old_uuid[UUID_SIZE]; unsigned int pbs = wdev->physical_bs; bool is_grown = false; struct walb_super_sector *super; u64 lsid0_off; struct lsid_set lsids; u64 old_ring_buffer_size; u32 new_salt; ASSERT(ctl->command == WALB_IOCTL_CLEAR_LOG); LOGn("WALB_IOCTL_CLEAR_LOG.\n"); /* Freeze iocore and checkpointing. */ iocore_freeze(wdev); stop_checkpointing(&wdev->cpd); /* Get old/new log device size. */ old_ldev_size = wdev->ldev_size; new_ldev_size = wdev->ldev->bd_part->nr_sects; if (old_ldev_size > new_ldev_size) { LOGe("Log device shrink not supported.\n"); goto error0; } /* Backup variables. */ old_ring_buffer_size = wdev->ring_buffer_size; backup_lsid_set(wdev, &lsids); /* Initialize lsid(s). */ spin_lock(&wdev->lsid_lock); wdev->lsids.latest = 0; wdev->lsids.flush = 0; wdev->lsids.completed = 0; wdev->lsids.permanent = 0; wdev->lsids.written = 0; wdev->lsids.prev_written = 0; wdev->lsids.oldest = 0; spin_unlock(&wdev->lsid_lock); /* Grow the walblog device. */ if (old_ldev_size < new_ldev_size) { LOGn("Detect log device size change.\n"); /* Grow the disk. */ is_grown = true; if (!resize_disk(wdev->log_gd, new_ldev_size)) { LOGe("grow disk failed.\n"); iocore_set_readonly(wdev); goto error1; } LOGn("Grown log device size from %"PRIu64" to %"PRIu64".\n", old_ldev_size, new_ldev_size); wdev->ldev_size = new_ldev_size; /* Recalculate ring buffer size. */ wdev->ring_buffer_size = addr_pb(pbs, new_ldev_size) - get_ring_buffer_offset(pbs); } /* Generate new uuid and salt. */ get_random_bytes(new_uuid, 16); get_random_bytes(&new_salt, sizeof(new_salt)); wdev->log_checksum_salt = new_salt; /* Update superblock image. */ spin_lock(&wdev->lsuper0_lock); super = get_super_sector(wdev->lsuper0); memcpy(old_uuid, super->uuid, UUID_SIZE); memcpy(super->uuid, new_uuid, UUID_SIZE); super->ring_buffer_size = wdev->ring_buffer_size; super->log_checksum_salt = new_salt; /* super->metadata_size; */ lsid0_off = get_offset_of_lsid_2(super, 0); spin_unlock(&wdev->lsuper0_lock); /* Sync super sector. */ if (!walb_sync_super_block(wdev)) { LOGe("sync superblock failed.\n"); iocore_set_readonly(wdev); goto error2; } /* Invalidate first logpack */ if (!invalidate_lsid(wdev, 0)) { LOGe("invalidate lsid 0 failed.\n"); iocore_set_readonly(wdev); goto error2; } /* Clear log overflow. */ iocore_clear_log_overflow(wdev); /* Melt iocore and checkpointing. */ start_checkpointing(&wdev->cpd); iocore_melt(wdev); return 0; error2: restore_lsid_set(wdev, &lsids); wdev->ring_buffer_size = old_ring_buffer_size; #if 0 wdev->ldev_size = old_ldev_size; if (!resize_disk(wdev->log_gd, old_ldev_size)) { LOGe("resize_disk to shrink failed.\n"); } #endif error1: start_checkpointing(&wdev->cpd); iocore_melt(wdev); error0: return -EFAULT; }