Project

General

Profile

Submit #2776 ยป 0001-sbin-hammer-add-hammer-volume-erase-command.patch

tkusumi, 01/23/2015 10:01 AM

View differences:

sbin/hammer/cmd_pseudofs.c
static void init_pfsd(hammer_pseudofs_data_t pfsd, int is_slave);
static void pseudofs_usage(int code);
static char *strtrl(char **path, int len);
static int getyn(void);
static int timetosecs(char *str);
/*
......
struct hammer_ioc_pseudofs_rw pfs;
struct stat st;
int fd;
int i;
if (ac == 0)
pseudofs_usage(1);
......
printf("This will irrevocably destroy all data on this PFS!!!!!\n");
printf("Do you really want to do this? ");
fflush(stdout);
if (getyn() == 0) {
if (get_yes() == 0) {
fprintf(stderr, "No action taken on PFS#%d\n", pfs.pfs_id);
exit(1);
}
......
printf("This PFS is currently setup as a MASTER!\n");
printf("Are you absolutely sure you want to destroy it? ");
fflush(stdout);
if (getyn() == 0) {
if (get_yes() == 0) {
fprintf(stderr, "No action taken on PFS#%d\n",
pfs.pfs_id);
exit(1);
......
}
printf("Destroying PFS #%d (%s) in ", pfs.pfs_id, pfs.ondisk->label);
for (i = 5; i; --i) {
printf(" %d", i);
fflush(stdout);
sleep(1);
}
wait_grace_period(5);
printf(".. starting destruction pass\n");
fflush(stdout);
......
exit(code);
}
static
int
getyn(void)
{
char buf[256];
int len;
if (fgets(buf, sizeof(buf), stdin) == NULL)
return(0);
len = strlen(buf);
while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
--len;
buf[len] = 0;
if (strcmp(buf, "y") == 0 ||
strcmp(buf, "yes") == 0 ||
strcmp(buf, "Y") == 0 ||
strcmp(buf, "YES") == 0) {
return(1);
}
return(0);
}
/*
* Convert time in the form [Nd/]hh[:mm[:ss]] to seconds.
*
sbin/hammer/cmd_volume.c
*
* - volume-add: Add new volume to HAMMER filesystem
* - volume-del: Remove volume from HAMMER filesystem
* - volume-erase: Erase signature or header from HAMMER filesystem volume
* - volume-list: List volumes making up a HAMMER filesystem
*/
......
#include <string.h>
#include <stdlib.h>
static void erase_volume(struct volume_info *vol, int full);
static void dump_volume(struct volume_info *vol, int full);
static int find_volume(const char *vol_name, const char *mnt_name);
static uint64_t check_volume(const char *vol_name);
/*
......
}
/*
* volume-erase <device> [signature|header]
*/
void
hammer_cmd_volume_erase(char **av, int ac)
{
int i, mntsize, hdr, ret = 0;
char *device;
const char *what;
struct statfs *stfsbuf;
struct volume_info *vol;
if (ac == 0 || ac > 2) {
fprintf(stderr,
"hammer volume-erase <device> [signature|header]\n");
exit(1);
}
device = av[0];
if (ac == 1)
hdr = 0; /* signature only */
else if (strcmp(av[1], "signature") == 0)
hdr = 0;
else if (strcmp(av[1], "header") == 0)
hdr = 1;
else {
fprintf(stderr,
"hammer volume-erase: Unknown keyword %s\n", av[1]);
exit(1);
}
what = hdr ? "header" : "signature";
/*
* Check if it's currently mounted as HAMMER filesystem
*/
mntsize = getmntinfo(&stfsbuf, MNT_NOWAIT);
for (i = 0; i < mntsize; i++) {
struct statfs *stfs = &stfsbuf[i];
if (strcmp(stfs->f_fstypename, "hammer") == 0) {
int result = find_volume(device, stfs->f_mntonname);
if (result == 0) {
fprintf(stderr,
"hammer volume-erase: %s is used by %s\n",
device, stfs->f_mntonname);
exit(1); /* existing filesystem */
} else if (result < 0) {
exit(1); /* error */
}
}
}
/*
* Setup volume with HAMMER_MAX_VOLUMES as we don't know id
*/
vol = setup_volume(HAMMER_MAX_VOLUMES, device, 0, O_RDWR);
assert(vol && vol->ondisk);
if (vol->ondisk->vol_no < 0 ||
vol->ondisk->vol_no >= HAMMER_MAX_VOLUMES) {
fprintf(stderr, "hammer volume-erase: %s has invalid id %d\n",
device, vol->ondisk->vol_no);
ret = 1;
goto fail_free_volume;
}
vol = get_volume(vol->ondisk->vol_no);
assert(vol && vol->ondisk);
if (DebugOpt)
dump_volume(vol, hdr);
/*
* Assume little endian (x86_64)
*/
if (vol->ondisk->vol_signature != HAMMER_FSBUF_VOLUME) {
fprintf(stderr, "hammer volume-erase: %s is already erased\n",
device);
ret = 1;
goto fail_rel_volume;
}
/*
* Taken from sbin/hammer/cmd_pseudofs.c
*/
printf("You have requested that volume %s of %s be erased\n",
what, device);
printf("Do you really want to do this? ");
fflush(stdout);
if (get_yes() == 0) {
fprintf(stderr, "No action taken\n");
ret = 1;
goto fail_rel_volume;
}
printf("Erasing volume %s of %s", what, device);
wait_grace_period(5);
printf("\n");
erase_volume(vol, hdr);
printf("Erased\n");
if (DebugOpt)
dump_volume(vol, hdr);
fail_rel_volume:
rel_volume(vol);
fail_free_volume:
if (vol->name)
free(vol->name);
if (vol->ondisk)
free(vol->ondisk);
if (vol)
free(vol);
if (ret)
exit(ret);
}
static void
erase_volume(struct volume_info *vol, int full)
{
int n;
char *p;
if (full) {
p = (char *)vol->ondisk;
n = (int)sizeof(struct hammer_volume_ondisk);
} else {
p = (char *)&vol->ondisk->vol_signature;
n = (int)sizeof(u_int64_t);
}
memset(p, 0, n);
vol->cache.modified = 1;
flush_volume(vol);
}
static void
dump_volume(struct volume_info *vol, int full)
{
int i, n;
char *p;
if (full) {
p = (char *)vol->ondisk;
n = (int)sizeof(struct hammer_volume_ondisk);
} else {
p = (char *)&vol->ondisk->vol_signature;
n = (int)sizeof(u_int64_t);
}
for (i = 0; i < n; i++)
printf("%02X ", p[i] & 0xFF);
printf("\n");
}
/*
* volume-list <filesystem>
*/
void
......
close(fd);
return pinfo.media_size;
}
/*
* Check if vol_name is a part of currently mounted HAMMER filesystem
*
* Returns either of the followings:
* 0 - vol_name found in mnt_name
* 1 - vol_name NOT found in mnt_name
* < 0 - error
*/
static int
find_volume(const char *vol_name, const char *mnt_name)
{
int i, fd = -1, ret = -1;
struct stat st;
struct hammer_ioc_volume_list ioc;
fd = open(mnt_name, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Unable to access %s: %s\n",
mnt_name, strerror(errno));
ret = -1;
goto end;
}
/*
* volume-list ioctl
*/
bzero(&ioc, sizeof(ioc));
ioc.vols = malloc(HAMMER_MAX_VOLUMES *
sizeof(struct hammer_ioc_volume));
if (ioc.vols == NULL) {
fprintf(stderr, "Unable to allocate memory: %s\n",
strerror(errno));
ret = -1;
goto end;
}
ioc.nvols = HAMMER_MAX_VOLUMES;
if ((ret = ioctl(fd, HAMMERIOC_LIST_VOLUMES, &ioc)) < 0) {
fprintf(stderr, "ioctl: %s\n", strerror(errno));
goto end;
}
if ((ret = stat(vol_name, &st)) < 0) {
fprintf(stderr, "Unable to stat %s: %s\n",
vol_name, strerror(errno));
goto end;
}
for (i = 0; i < ioc.nvols; i++) {
char *path = ioc.vols[i].device_name;
struct stat _st;
if ((ret = stat(path, &_st)) < 0) {
fprintf(stderr, "Unable to stat %s: %s\n",
path, strerror(errno));
goto end;
}
if ((st.st_dev == _st.st_dev) && (st.st_ino == _st.st_ino)) {
ret = 0; /* found */
goto end;
}
}
ret = 1; /* not found */
end:
if (ioc.vols)
free(ioc.vols);
if (fd > -1)
close(fd);
return ret;
}
sbin/hammer/hammer.8
file system, formatting will be denied.
You can overcome this sanity check by using
.Xr dd 1
to erase the beginning sectors of the device.
to erase the beginning sectors of the device or by using
.Nm volume-erase
command.
.Pp
Remember that you have to specify
.Ar device ,
......
.Pa /boot/loader.conf ,
see
.Xr loader 8 .
.\" ==== volume-erase ====
.It Cm volume-erase Ar device [signature|header]
Erase
.Nm HAMMER
filesystem signature or the entire volume header from
the volume
.Ar device .
.Pp
This command is safer than using
.Xr dd 1
as it has some safety measures. This command overwrites
.Nm HAMMER
filesystem signature or the entire volume header with 0
after making sure you are going to erase the volume
.Ar device
.Pp
If the
.Nm header
keyword is specified this command erases the entire volume
header instead of just signature. If the
.Nm signature
keyword is specified this command only erases signature. Using
no keyword works the same as specifying
.Nm signature
keyword.
.Pp
As safety measure the
.Fl y
flag have no effect on this directive.
.\" ==== volume-list ====
.It Cm volume-list Ar filesystem
List the volumes that make up
sbin/hammer/hammer.c
hammer_cmd_volume_del(av + 1, ac - 1);
exit(0);
}
if (strcmp(av[0], "volume-erase") == 0) {
hammer_cmd_volume_erase(av + 1, ac - 1);
exit(0);
}
if (strcmp(av[0], "volume-list") == 0) {
hammer_cmd_volume_list(av + 1, ac - 1);
exit(0);
......
"hammer version-upgrade <filesystem> <version> [force]\n"
"hammer volume-add <device> <filesystem>\n"
"hammer volume-del <device> <filesystem>\n"
"hammer volume-erase <device> [signature|header]\n"
"hammer volume-list <filesystem>\n"
);
sbin/hammer/hammer.h
void hammer_cmd_set_version(char **av, int ac);
void hammer_cmd_volume_add(char **av, int ac);
void hammer_cmd_volume_del(char **av, int ac);
void hammer_cmd_volume_erase(char **av, int ac);
void hammer_cmd_volume_list(char **av, int ac);
void hammer_cmd_dedup_simulate(char **av, int ac);
void hammer_cmd_dedup(char **av, int ac);
sbin/hammer/hammer_util.h
void panic(const char *ctl, ...) __printflike(1, 2);
int get_yes(void);
void wait_grace_period(int);
sbin/hammer/misc.c
++rlen;
}
}
int
get_yes(void)
{
char buf[256];
int len;
if (fgets(buf, sizeof(buf), stdin) == NULL)
return(0);
len = strlen(buf);
while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
--len;
buf[len] = 0;
if (strcmp(buf, "y") == 0 ||
strcmp(buf, "yes") == 0 ||
strcmp(buf, "Y") == 0 ||
strcmp(buf, "YES") == 0) {
return(1);
}
return(0);
}
void
wait_grace_period(int count)
{
int i;
for (i = count; i; --i) {
printf(" %d", i);
fflush(stdout);
sleep(1);
}
}
sys/vfs/hammer/hammer_volume.c
*/
if (ondisk->vol_signature == HAMMER_FSBUF_VOLUME) {
kprintf("hammer_volume_add: Formatting of valid HAMMER volume "
"%s denied. Erase with dd!\n", vol_name);
"%s denied. Erase with dd or hammer volume-erase!\n",
vol_name);
error = EFTYPE;
goto late_failure;
}
    (1-1/1)