summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2007-07-12 16:09:07 +0000
committerbde <bde@FreeBSD.org>2007-07-12 16:09:07 +0000
commit01c1ec9b1ae5e546930028126ab6d950d401c786 (patch)
treeec9034244b2c722defe64190f00e6063e92ad1b7
parent46995e966fea71f67bb69ba55d39bb676628444a (diff)
downloadFreeBSD-src-01c1ec9b1ae5e546930028126ab6d950d401c786.zip
FreeBSD-src-01c1ec9b1ae5e546930028126ab6d950d401c786.tar.gz
Fix some bugs involving the fsinfo block (many remain unfixed). This is
part of fixing msdosfs for large sector sizes. One of the fixed bugs was fatal for large sector sizes. 1. The fsinfo block has size 512, but it was misunderstood and declared as having size 1024, with nothing in the second 512 bytes except a signature at the end. The second 512 bytes actually normally (if the file system was created by Windows) consist of a second boot sector which is normally (in WinXP) empty except for a signature -- the normal layout is one boot sector, one fsinfo sector, another boot sector, then these 3 sectors duplicated. However, other layouts are valid. newfs_msdos produces a valid layout with one boot sector, one fsinfo sector, then these 2 sectors duplicated. The signature check for the extra part of the fsinfo was thus normally checking the signature in either the second boot sector or the first boot sector in the copy, and thus accidentally succeeding. The extra signature check would just fail for weirder layouts with 512-byte sectors, and for normal layouts with any other sector size. Remove the extra bytes and the extra signature check. 2. Old versions did i/o to the fsinfo block using size 1024, with the second half only used for the extra signature check on read. This was harmless for sector size 512, and worked accidentally for sector size 1024. The i/o just failed for larger sector sizes. The version being fixed did i/o to the fsinfo block using size fsi_size(pmp) = (1024 << ((pmp)->pm_BlkPerSec >> 2)). This expression makes no sense. It happens to work for sector small sector sizes, but for sector size 32K it gives the preposterous value of 64M and thus causes panics. A sector size of 32768 is necessary for at least some DVD-RW's (where the minimum write size is 32768 although the minimum read size is 2048). Now that the size of the fsinfo block is 512, it always fits in one sector so there is no need for a macro to express it. Just use the sector size where the old code uses 1024. Approved by: re (kensmith) Approved by: nyan (several years ago for a different version of (2))
-rw-r--r--sys/fs/msdosfs/bpb.h2
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c5
-rw-r--r--sys/fs/msdosfs/msdosfsmount.h6
4 files changed, 3 insertions, 12 deletions
diff --git a/sys/fs/msdosfs/bpb.h b/sys/fs/msdosfs/bpb.h
index c9bf27c..addacd2 100644
--- a/sys/fs/msdosfs/bpb.h
+++ b/sys/fs/msdosfs/bpb.h
@@ -167,6 +167,4 @@ struct fsinfo {
u_int8_t fsinxtfree[4];
u_int8_t fsifill2[12];
u_int8_t fsisig3[4];
- u_int8_t fsifill3[508];
- u_int8_t fsisig4[4];
};
diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
index c0b53a4..b77f2d6 100644
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -376,7 +376,7 @@ updatefats(pmp, bp, fatbn)
+ ffs(pmp->pm_inusemap[cn / N_INUSEBITS]
^ (u_int)-1) - 1;
}
- if (bread(pmp->pm_devvp, pmp->pm_fsinfo, fsi_size(pmp),
+ if (bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_bpcluster,
NOCRED, &bpn) != 0) {
/*
* Ignore the error, but turn off FSInfo update for the future.
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 3b53b0a..8c30fde 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -644,14 +644,13 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td)
if (pmp->pm_fsinfo) {
struct fsinfo *fp;
- if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp),
+ if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_bpcluster,
NOCRED, &bp)) != 0)
goto error_exit;
fp = (struct fsinfo *)bp->b_data;
if (!bcmp(fp->fsisig1, "RRaA", 4)
&& !bcmp(fp->fsisig2, "rrAa", 4)
- && !bcmp(fp->fsisig3, "\0\0\125\252", 4)
- && !bcmp(fp->fsisig4, "\0\0\125\252", 4)) {
+ && !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
pmp->pm_nxtfree = getulong(fp->fsinxtfree);
if (pmp->pm_nxtfree == 0xffffffff)
pmp->pm_nxtfree = CLUST_FIRST;
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
index f3c08d6..0884679 100644
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -210,12 +210,6 @@ struct msdosfs_fileno {
? roottobn((pmp), (dirofs)) \
: cntobn((pmp), (dirclu)))
-/*
- * Calculate fsinfo block size
- */
-#define fsi_size(pmp) \
- (1024 << ((pmp)->pm_BlkPerSec >> 2))
-
void msdosfs_fileno_init(struct mount *);
void msdosfs_fileno_free(struct mount *);
uint32_t msdosfs_fileno_map(struct mount *, uint64_t);
OpenPOWER on IntegriCloud