Do not update the fsinfo block on each update of any fat block, this
is excessive. Postpone the flush of the fsinfo to VFS_SYNC(), remembering the need for update with the flag MSDOSFS_FSIMOD, stored in pm_flags. FAT32 specification describes both FSI_Free_Count and FSI_Nxt_Free as the advisory hints, not requiring them to be correct. Based on the patch from bde, modified by me. Reviewed by: bde MFC after: 2 weeks
This commit is contained in:
parent
43e1adfa05
commit
bb7ca8229d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=246921
@ -328,29 +328,6 @@ updatefats(pmp, bp, fatbn)
|
|||||||
printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
|
printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have an FSInfo block, update it.
|
|
||||||
*/
|
|
||||||
if (pmp->pm_fsinfo) {
|
|
||||||
if (bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
|
|
||||||
NOCRED, &bpn) != 0) {
|
|
||||||
/*
|
|
||||||
* Ignore the error, but turn off FSInfo update for the future.
|
|
||||||
*/
|
|
||||||
pmp->pm_fsinfo = 0;
|
|
||||||
brelse(bpn);
|
|
||||||
} else {
|
|
||||||
struct fsinfo *fp = (struct fsinfo *)bpn->b_data;
|
|
||||||
|
|
||||||
putulong(fp->fsinfree, pmp->pm_freeclustercount);
|
|
||||||
putulong(fp->fsinxtfree, pmp->pm_nxtfree);
|
|
||||||
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
|
|
||||||
bwrite(bpn);
|
|
||||||
else
|
|
||||||
bdwrite(bpn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
|
if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
|
||||||
/*
|
/*
|
||||||
* Now copy the block(s) of the modified fat to the other copies of
|
* Now copy the block(s) of the modified fat to the other copies of
|
||||||
@ -393,9 +370,6 @@ updatefats(pmp, bp, fatbn)
|
|||||||
bwrite(bp);
|
bwrite(bp);
|
||||||
else
|
else
|
||||||
bdwrite(bp);
|
bdwrite(bp);
|
||||||
/*
|
|
||||||
* Maybe update fsinfo sector here?
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -431,6 +405,7 @@ usemap_alloc(pmp, cn)
|
|||||||
pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
|
pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
|
||||||
KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little"));
|
KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little"));
|
||||||
pmp->pm_freeclustercount--;
|
pmp->pm_freeclustercount--;
|
||||||
|
pmp->pm_flags |= MSDOSFS_FSIMOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void
|
static __inline void
|
||||||
@ -441,6 +416,7 @@ usemap_free(pmp, cn)
|
|||||||
|
|
||||||
MSDOSFS_ASSERT_MP_LOCKED(pmp);
|
MSDOSFS_ASSERT_MP_LOCKED(pmp);
|
||||||
pmp->pm_freeclustercount++;
|
pmp->pm_freeclustercount++;
|
||||||
|
pmp->pm_flags |= MSDOSFS_FSIMOD;
|
||||||
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
|
KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
|
||||||
!= 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
|
!= 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
|
||||||
(unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
|
(unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
|
||||||
@ -742,7 +718,10 @@ chainalloc(pmp, start, count, fillwith, retcluster, got)
|
|||||||
|
|
||||||
for (cl = start, n = count; n-- > 0;)
|
for (cl = start, n = count; n-- > 0;)
|
||||||
usemap_alloc(pmp, cl++);
|
usemap_alloc(pmp, cl++);
|
||||||
|
pmp->pm_nxtfree = start + count;
|
||||||
|
if (pmp->pm_nxtfree > pmp->pm_maxcluster)
|
||||||
|
pmp->pm_nxtfree = CLUST_FIRST;
|
||||||
|
pmp->pm_flags |= MSDOSFS_FSIMOD;
|
||||||
error = fatchain(pmp, start, count, fillwith);
|
error = fatchain(pmp, start, count, fillwith);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@ -754,9 +733,6 @@ chainalloc(pmp, start, count, fillwith, retcluster, got)
|
|||||||
*retcluster = start;
|
*retcluster = start;
|
||||||
if (got)
|
if (got)
|
||||||
*got = count;
|
*got = count;
|
||||||
pmp->pm_nxtfree = start + count;
|
|
||||||
if (pmp->pm_nxtfree > pmp->pm_maxcluster)
|
|
||||||
pmp->pm_nxtfree = CLUST_FIRST;
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,6 +896,40 @@ msdosfs_statfs(struct mount *mp, struct statfs *sbp)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have an FSInfo block, update it.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
msdosfs_fsiflush(struct msdosfsmount *pmp, int waitfor)
|
||||||
|
{
|
||||||
|
struct fsinfo *fp;
|
||||||
|
struct buf *bp;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
MSDOSFS_LOCK_MP(pmp);
|
||||||
|
if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) {
|
||||||
|
error = 0;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
|
||||||
|
NOCRED, &bp);
|
||||||
|
if (error != 0) {
|
||||||
|
brelse(bp);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
fp = (struct fsinfo *)bp->b_data;
|
||||||
|
putulong(fp->fsinfree, pmp->pm_freeclustercount);
|
||||||
|
putulong(fp->fsinxtfree, pmp->pm_nxtfree);
|
||||||
|
pmp->pm_flags &= ~MSDOSFS_FSIMOD;
|
||||||
|
if (waitfor == MNT_WAIT)
|
||||||
|
error = bwrite(bp);
|
||||||
|
else
|
||||||
|
bawrite(bp);
|
||||||
|
unlock:
|
||||||
|
MSDOSFS_UNLOCK_MP(pmp);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
msdosfs_sync(struct mount *mp, int waitfor)
|
msdosfs_sync(struct mount *mp, int waitfor)
|
||||||
{
|
{
|
||||||
@ -958,6 +992,10 @@ msdosfs_sync(struct mount *mp, int waitfor)
|
|||||||
allerror = error;
|
allerror = error;
|
||||||
VOP_UNLOCK(pmp->pm_devvp, 0);
|
VOP_UNLOCK(pmp->pm_devvp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = msdosfs_fsiflush(pmp, waitfor);
|
||||||
|
if (error != 0)
|
||||||
|
allerror = error;
|
||||||
return (allerror);
|
return (allerror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +262,7 @@ struct msdosfs_args {
|
|||||||
#define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */
|
#define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */
|
||||||
#define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */
|
#define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */
|
||||||
#define MSDOSFS_LARGEFS 0x10000000 /* perform fileno mapping */
|
#define MSDOSFS_LARGEFS 0x10000000 /* perform fileno mapping */
|
||||||
|
#define MSDOSFS_FSIMOD 0x01000000
|
||||||
|
|
||||||
#define MSDOSFS_ARGSMAGIC 0xe4eff300
|
#define MSDOSFS_ARGSMAGIC 0xe4eff300
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user