Changeset View
Changeset View
Standalone View
Standalone View
sbin/growfs/growfs.c
Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
static int isblock(struct fs *, unsigned char *, int); | static int isblock(struct fs *, unsigned char *, int); | ||||
static void clrblock(struct fs *, unsigned char *, int); | static void clrblock(struct fs *, unsigned char *, int); | ||||
static void setblock(struct fs *, unsigned char *, int); | static void setblock(struct fs *, unsigned char *, int); | ||||
static void initcg(int, time_t, int, unsigned int); | static void initcg(int, time_t, int, unsigned int); | ||||
static void updjcg(int, time_t, int, int, unsigned int); | static void updjcg(int, time_t, int, int, unsigned int); | ||||
static void updcsloc(time_t, int, int, unsigned int); | static void updcsloc(time_t, int, int, unsigned int); | ||||
static void frag_adjust(ufs2_daddr_t, int); | static void frag_adjust(ufs2_daddr_t, int); | ||||
static void updclst(int); | static void updclst(int); | ||||
static void mount_reload(const struct statfs *stfs); | |||||
static void cgckhash(struct cg *); | static void cgckhash(struct cg *); | ||||
/* | /* | ||||
* Here we actually start growing the file system. We basically read the | * Here we actually start growing the file system. We basically read the | ||||
* cylinder summary from the first cylinder group as we want to update | * cylinder summary from the first cylinder group as we want to update | ||||
* this on the fly during our various operations. First we handle the | * this on the fly during our various operations. First we handle the | ||||
* changes in the former last cylinder group. Afterwards we create all new | * changes in the former last cylinder group. Afterwards we create all new | ||||
* cylinder groups. Now we handle the cylinder group containing the | * cylinder groups. Now we handle the cylinder group containing the | ||||
▲ Show 20 Lines • Show All 1,128 Lines • ▼ Show 20 Lines | is_dev(const char *name) | ||||
if (stat(name, &devstat) != 0) | if (stat(name, &devstat) != 0) | ||||
return (0); | return (0); | ||||
if (!S_ISCHR(devstat.st_mode)) | if (!S_ISCHR(devstat.st_mode)) | ||||
return (0); | return (0); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | |||||
* Return mountpoint on which the device is currently mounted. | |||||
*/ | |||||
static const struct statfs * | |||||
dev_to_statfs(const char *dev) | |||||
{ | |||||
struct stat devstat, mntdevstat; | |||||
struct statfs *mntbuf, *statfsp; | |||||
char device[MAXPATHLEN]; | |||||
char *mntdevname; | |||||
int i, mntsize; | |||||
/* | |||||
* First check the mounted filesystems. | |||||
*/ | |||||
if (stat(dev, &devstat) != 0) | |||||
return (NULL); | |||||
if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode)) | |||||
return (NULL); | |||||
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | |||||
for (i = 0; i < mntsize; i++) { | |||||
statfsp = &mntbuf[i]; | |||||
mntdevname = statfsp->f_mntfromname; | |||||
if (*mntdevname != '/') { | |||||
strcpy(device, _PATH_DEV); | |||||
strcat(device, mntdevname); | |||||
mntdevname = device; | |||||
} | |||||
if (stat(mntdevname, &mntdevstat) == 0 && | |||||
mntdevstat.st_rdev == devstat.st_rdev) | |||||
return (statfsp); | |||||
} | |||||
return (NULL); | |||||
} | |||||
static const char * | static const char * | ||||
mountpoint_to_dev(const char *mountpoint) | getdev(const char *name, struct statfs *statfsp) | ||||
{ | { | ||||
struct statfs *mntbuf, *statfsp; | |||||
struct fstab *fs; | |||||
int i, mntsize; | |||||
/* | |||||
* First check the mounted filesystems. | |||||
*/ | |||||
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | |||||
for (i = 0; i < mntsize; i++) { | |||||
statfsp = &mntbuf[i]; | |||||
if (strcmp(statfsp->f_mntonname, mountpoint) == 0) | |||||
return (statfsp->f_mntfromname); | |||||
} | |||||
/* | |||||
* Check the fstab. | |||||
*/ | |||||
fs = getfsfile(mountpoint); | |||||
if (fs != NULL) | |||||
return (fs->fs_spec); | |||||
return (NULL); | |||||
} | |||||
static const char * | |||||
getdev(const char *name) | |||||
{ | |||||
static char device[MAXPATHLEN]; | static char device[MAXPATHLEN]; | ||||
const char *cp, *dev; | const char *cp; | ||||
if (is_dev(name)) | if (is_dev(name)) | ||||
return (name); | return (name); | ||||
cp = strrchr(name, '/'); | cp = strrchr(name, '/'); | ||||
if (cp == NULL) { | if (cp == NULL) { | ||||
snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name); | snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name); | ||||
if (is_dev(device)) | if (is_dev(device)) | ||||
return (device); | return (device); | ||||
} | } | ||||
dev = mountpoint_to_dev(name); | if (statfsp != NULL) | ||||
if (dev != NULL && is_dev(dev)) | return (statfsp->f_mntfromname); | ||||
return (dev); | |||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* growfs(8) is a utility which allows to increase the size of an existing | * growfs(8) is a utility which allows to increase the size of an existing | ||||
* ufs file system. Currently this can only be done on unmounted file system. | * ufs file system. Currently this can only be done on unmounted file system. | ||||
* It recognizes some command line options to specify the new desired size, | * It recognizes some command line options to specify the new desired size, | ||||
Show All 15 Lines | |||||
* userland access to the file system locking facility. | * userland access to the file system locking facility. | ||||
*/ | */ | ||||
int | int | ||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
DBG_FUNC("main") | DBG_FUNC("main") | ||||
struct fs *fs; | struct fs *fs; | ||||
const char *device; | const char *device; | ||||
const struct statfs *statfsp; | struct statfs *statfsp; | ||||
uint64_t size = 0; | uint64_t size = 0; | ||||
off_t mediasize; | off_t mediasize; | ||||
int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0; | int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0; | ||||
char *p, reply[5], oldsizebuf[6], newsizebuf[6]; | char *p, reply[5], oldsizebuf[6], newsizebuf[6]; | ||||
void *testbuf; | void *testbuf; | ||||
DBG_ENTER; | DBG_ENTER; | ||||
Show All 35 Lines | main(int argc, char **argv) | ||||
argv += optind; | argv += optind; | ||||
if (argc != 1) | if (argc != 1) | ||||
usage(); | usage(); | ||||
/* | /* | ||||
* Now try to guess the device name. | * Now try to guess the device name. | ||||
*/ | */ | ||||
device = getdev(*argv); | statfsp = getmntpoint(*argv); | ||||
device = getdev(*argv, statfsp); | |||||
if (device == NULL) | if (device == NULL) | ||||
errx(1, "cannot find special device for %s", *argv); | errx(1, "cannot find special device for %s", *argv); | ||||
statfsp = dev_to_statfs(device); | |||||
fsi = open(device, O_RDONLY); | fsi = open(device, O_RDONLY); | ||||
if (fsi < 0) | if (fsi < 0) | ||||
err(1, "%s", device); | err(1, "%s", device); | ||||
/* | /* | ||||
* Try to guess the slice size if not specified. | * Try to guess the slice size if not specified. | ||||
*/ | */ | ||||
if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1) | if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1) | ||||
▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | if (fso > -1) { | ||||
if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { | if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { | ||||
error = ioctl(fso, UFSRESUME); | error = ioctl(fso, UFSRESUME); | ||||
if (error != 0) | if (error != 0) | ||||
err(1, "UFSRESUME"); | err(1, "UFSRESUME"); | ||||
} | } | ||||
error = close(fso); | error = close(fso); | ||||
if (error != 0) | if (error != 0) | ||||
err(1, "close"); | err(1, "close"); | ||||
if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0) | if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0 && | ||||
mount_reload(statfsp); | chkdoreload(statfsp, warn) != 0) | ||||
exit(9); | |||||
} | } | ||||
DBG_CLOSE; | DBG_CLOSE; | ||||
DBG_LEAVE; | DBG_LEAVE; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (lcs < sblock.fs_contigsumsize) { | ||||
if (lcs) | if (lcs) | ||||
cg_clustersum(&acg)[lcs]--; | cg_clustersum(&acg)[lcs]--; | ||||
lcs++; | lcs++; | ||||
cg_clustersum(&acg)[lcs]++; | cg_clustersum(&acg)[lcs]++; | ||||
} | } | ||||
DBG_LEAVE; | DBG_LEAVE; | ||||
return; | return; | ||||
} | |||||
static void | |||||
mount_reload(const struct statfs *stfs) | |||||
{ | |||||
char errmsg[255]; | |||||
struct iovec *iov; | |||||
int iovlen; | |||||
iov = NULL; | |||||
iovlen = 0; | |||||
*errmsg = '\0'; | |||||
build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4); | |||||
build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1); | |||||
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); | |||||
build_iovec(&iov, &iovlen, "update", NULL, 0); | |||||
build_iovec(&iov, &iovlen, "reload", NULL, 0); | |||||
if (nmount(iov, iovlen, stfs->f_flags) < 0) { | |||||
errmsg[sizeof(errmsg) - 1] = '\0'; | |||||
err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname, | |||||
*errmsg != '\0' ? ": " : "", errmsg); | |||||
} | |||||
} | } | ||||
/* | /* | ||||
* Calculate the check-hash of the cylinder group. | * Calculate the check-hash of the cylinder group. | ||||
*/ | */ | ||||
static void | static void | ||||
cgckhash(struct cg *cgp) | cgckhash(struct cg *cgp) | ||||
{ | { | ||||
if ((sblock.fs_metackhash & CK_CYLGRP) == 0) | if ((sblock.fs_metackhash & CK_CYLGRP) == 0) | ||||
return; | return; | ||||
cgp->cg_ckhash = 0; | cgp->cg_ckhash = 0; | ||||
cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); | cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); | ||||
} | } |