summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2012-10-30 21:32:10 +0000
committertrasz <trasz@FreeBSD.org>2012-10-30 21:32:10 +0000
commitff5b37a93e45dfa350cd924478c25f32e87f922a (patch)
tree2c00e9d729a9009b78e4f58c7aab66de552d87a6
parent335b7a9f3cabbf193a9059af1bcc6c52bbe672af (diff)
downloadFreeBSD-src-ff5b37a93e45dfa350cd924478c25f32e87f922a.zip
FreeBSD-src-ff5b37a93e45dfa350cd924478c25f32e87f922a.tar.gz
Fix problem with geom_label(4) not recognizing UFS labels on filesystems
extended using growfs(8). The problem here is that geom_label checks if the filesystem size recorded in UFS superblock is equal to the provider (i.e. device) size. This check cannot be removed due to backward compatibility. On the other hand, in most cases growfs(8) cannot set fs_size in the superblock to match the provider size, because, differently from newfs(8), it cannot recompute cylinder group sizes. To fix this problem, add another superblock field, fs_providersize, used only for this purpose. The geom_label(4) will attach if either fs_size (filesystem created with newfs(8)) or fs_providersize (filesystem expanded using growfs(8)) matches the device size. PR: kern/165962 Reviewed by: mckusick Sponsored by: FreeBSD Foundation
-rw-r--r--sbin/dumpfs/dumpfs.c5
-rw-r--r--sbin/growfs/growfs.c1
-rw-r--r--sbin/newfs/mkfs.c1
-rw-r--r--sbin/newfs/newfs.c2
-rw-r--r--sbin/newfs/newfs.h1
-rw-r--r--sys/geom/label/g_label_ufs.c3
-rw-r--r--sys/ufs/ffs/fs.h3
7 files changed, 11 insertions, 5 deletions
diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c
index d560845..a41ca4d 100644
--- a/sbin/dumpfs/dumpfs.c
+++ b/sbin/dumpfs/dumpfs.c
@@ -277,8 +277,9 @@ dumpfs(const char *name)
printf("unknown flags (%#x)", fsflags);
putchar('\n');
printf("fsmnt\t%s\n", afs.fs_fsmnt);
- printf("volname\t%s\tswuid\t%ju\n",
- afs.fs_volname, (uintmax_t)afs.fs_swuid);
+ printf("volname\t%s\tswuid\t%ju\tprovidersize\t%ju\n",
+ afs.fs_volname, (uintmax_t)afs.fs_swuid,
+ (uintmax_t)afs.fs_providersize);
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
afs.fs_csp = calloc(1, afs.fs_cssize);
if (bread(&disk, fsbtodb(&afs, afs.fs_csaddr), afs.fs_csp, afs.fs_cssize) == -1)
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index 0c16119..ad837a8 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -1498,6 +1498,7 @@ main(int argc, char **argv)
}
sblock.fs_size = dbtofsb(&osblock, size / DEV_BSIZE);
+ sblock.fs_providersize = dbtofsb(&osblock, mediasize / DEV_BSIZE);
/*
* Are we really growing?
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index efc22c3..0a547f9 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -263,6 +263,7 @@ restart:
}
sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
+ sblock.fs_providersize = dbtofsb(&sblock, mediasize / sectorsize);
/*
* Before the filesystem is finally initialized, mark it
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index 6163774..3ce0be7 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -94,6 +94,7 @@ int lflag; /* enable multilabel for file system */
int nflag; /* do not create .snap directory */
int tflag; /* enable TRIM */
intmax_t fssize; /* file system size */
+off_t mediasize; /* device size */
int sectorsize; /* bytes/sector */
int realsectorsize; /* bytes/sector in hardware */
int fsize = 0; /* fragment size */
@@ -135,7 +136,6 @@ main(int argc, char *argv[])
char *cp, *special;
intmax_t reserved;
int ch, i, rval;
- off_t mediasize;
char part_name; /* partition name, default to full disk */
part_name = 'c';
diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h
index 25bfcc8..9e1da0d 100644
--- a/sbin/newfs/newfs.h
+++ b/sbin/newfs/newfs.h
@@ -88,6 +88,7 @@ extern int lflag; /* enable multilabel MAC for file system */
extern int nflag; /* do not create .snap directory */
extern int tflag; /* enable TRIM */
extern intmax_t fssize; /* file system size */
+extern off_t mediasize; /* device size */
extern int sectorsize; /* bytes/sector */
extern int realsectorsize; /* bytes/sector in hardware*/
extern int fsize; /* fragment size */
diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c
index 6a313e2..46a3cb1 100644
--- a/sys/geom/label/g_label_ufs.c
+++ b/sys/geom/label/g_label_ufs.c
@@ -90,7 +90,8 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh
pp->mediasize / fs->fs_fsize == fs->fs_old_size) {
/* Valid UFS1. */
} else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 &&
- pp->mediasize / fs->fs_fsize == fs->fs_size) {
+ ((pp->mediasize / fs->fs_fsize == fs->fs_size) ||
+ (pp->mediasize / fs->fs_fsize == fs->fs_providersize))) {
/* Valid UFS2. */
} else {
g_free(fs);
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 3715539..c992b1d 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -329,7 +329,8 @@ struct fs {
int32_t fs_old_cpc; /* cyl per cycle in postbl */
int32_t fs_maxbsize; /* maximum blocking factor permitted */
int64_t fs_unrefs; /* number of unreferenced inodes */
- int64_t fs_sparecon64[16]; /* old rotation block list head */
+ int64_t fs_providersize; /* size of underlying GEOM provider */
+ int64_t fs_sparecon64[15]; /* old rotation block list head */
int64_t fs_sblockloc; /* byte offset of standard superblock */
struct csum_total fs_cstotal; /* (u) cylinder summary information */
ufs_time_t fs_time; /* last time written */
OpenPOWER on IntegriCloud