libblkid: support zone reset for wipefs
We cannot overwrite superblock magic in a sequential required zone. So, wipefs cannot work as it is. Instead, this commit implements the wiping by zone resetting. Zone resetting must be done only for a sequential write zone. This is checked by is_conventional(). Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
This commit is contained in:
parent
6be38dccae
commit
db22115875
|
@ -1229,6 +1229,39 @@ int blkid_do_probe(blkid_probe pr)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_BLKZONED_H
|
||||||
|
static int is_conventional(blkid_probe pr, uint64_t offset)
|
||||||
|
{
|
||||||
|
struct blk_zone_report *rep = NULL;
|
||||||
|
int ret;
|
||||||
|
uint64_t zone_mask;
|
||||||
|
|
||||||
|
if (!pr->zone_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
zone_mask = ~(pr->zone_size - 1);
|
||||||
|
rep = blkdev_get_zonereport(blkid_probe_get_fd(pr),
|
||||||
|
(offset & zone_mask) >> 9, 1);
|
||||||
|
if (!rep)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (rep->zones[0].type == BLK_ZONE_TYPE_CONVENTIONAL)
|
||||||
|
ret = 1;
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
free(rep);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline int is_conventional(blkid_probe pr __attribute__((__unused__)),
|
||||||
|
uint64_t offset __attribute__((__unused__)))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* blkid_do_wipe:
|
* blkid_do_wipe:
|
||||||
* @pr: prober
|
* @pr: prober
|
||||||
|
@ -1268,6 +1301,7 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
|
||||||
const char *off = NULL;
|
const char *off = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
uint64_t offset, magoff;
|
uint64_t offset, magoff;
|
||||||
|
int conventional;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
struct blkid_chain *chn;
|
struct blkid_chain *chn;
|
||||||
|
@ -1303,6 +1337,11 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
|
||||||
if (len > sizeof(buf))
|
if (len > sizeof(buf))
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
rc = is_conventional(pr, offset);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
conventional = rc == 1;
|
||||||
|
|
||||||
DBG(LOWPROBE, ul_debug(
|
DBG(LOWPROBE, ul_debug(
|
||||||
"do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
|
"do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
|
||||||
offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
|
offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
|
||||||
|
@ -1310,13 +1349,31 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
|
||||||
if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
|
if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!dryrun && len) {
|
||||||
|
if (conventional) {
|
||||||
memset(buf, 0, len);
|
memset(buf, 0, len);
|
||||||
|
|
||||||
if (!dryrun && len) {
|
|
||||||
/* wipen on device */
|
/* wipen on device */
|
||||||
if (write_all(fd, buf, len))
|
if (write_all(fd, buf, len))
|
||||||
return -1;
|
return -1;
|
||||||
fsync(fd);
|
fsync(fd);
|
||||||
|
} else {
|
||||||
|
#ifdef HAVE_LINUX_BLKZONED_H
|
||||||
|
uint64_t zone_mask = ~(pr->zone_size - 1);
|
||||||
|
struct blk_zone_range range = {
|
||||||
|
.sector = (offset & zone_mask) >> 9,
|
||||||
|
.nr_sectors = pr->zone_size >> 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = ioctl(fd, BLKRESETZONE, &range);
|
||||||
|
if (rc < 0)
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
/* Should not reach here */
|
||||||
|
assert(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
pr->flags &= ~BLKID_FL_MODIF_BUFF; /* be paranoid */
|
pr->flags &= ~BLKID_FL_MODIF_BUFF; /* be paranoid */
|
||||||
|
|
||||||
return blkid_probe_step_back(pr);
|
return blkid_probe_step_back(pr);
|
||||||
|
|
Loading…
Reference in New Issue