mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
The fsync(2) call should sync the vnode in such way that even after
system crash which happen after successfull fsync() return, the data is accessible. For msdosfs, this means that FAT entries for the file must be written. Since we do not track the FAT blocks containing entries for the current file, just do a sloppy sync of the devvp vnode for the mount, which buffers, among other things, contain FAT blocks. Simultaneously, for deupdat(): - optimize by clearing the modified flags before short-circuiting a return, if the mount is read-only; - only ignore the rest of the function for denode with DE_MODIFIED flag clear when the waitfor argument is false. The directory buffer for the entry might be of delayed write; - microoptimize by comparing the updated directory entry with the current block content; - try to cluster the write, fall back to bawrite() if low on resources. Based on the submission by: bde MFC after: 2 weeks
This commit is contained in:
parent
57f37a2584
commit
293e4eb67d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=250193
@ -288,16 +288,20 @@ deupdat(dep, waitfor)
|
||||
struct denode *dep;
|
||||
int waitfor;
|
||||
{
|
||||
int error;
|
||||
struct direntry dir;
|
||||
struct timespec ts;
|
||||
struct buf *bp;
|
||||
struct direntry *dirp;
|
||||
struct timespec ts;
|
||||
int error;
|
||||
|
||||
if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY)
|
||||
if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY) {
|
||||
dep->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS |
|
||||
DE_MODIFIED);
|
||||
return (0);
|
||||
}
|
||||
getnanotime(&ts);
|
||||
DETIMES(dep, &ts, &ts, &ts);
|
||||
if ((dep->de_flag & DE_MODIFIED) == 0)
|
||||
if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0)
|
||||
return (0);
|
||||
dep->de_flag &= ~DE_MODIFIED;
|
||||
if (dep->de_Attributes & ATTR_DIRECTORY)
|
||||
@ -307,13 +311,23 @@ deupdat(dep, waitfor)
|
||||
error = readde(dep, &bp, &dirp);
|
||||
if (error)
|
||||
return (error);
|
||||
DE_EXTERNALIZE(dirp, dep);
|
||||
DE_EXTERNALIZE(&dir, dep);
|
||||
if (bcmp(dirp, &dir, sizeof(dir)) == 0) {
|
||||
if (waitfor == 0 || (bp->b_flags & B_DELWRI) == 0) {
|
||||
brelse(bp);
|
||||
return (0);
|
||||
}
|
||||
} else
|
||||
*dirp = dir;
|
||||
if ((DETOV(dep)->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0)
|
||||
bp->b_flags |= B_CLUSTEROK;
|
||||
if (waitfor)
|
||||
return (bwrite(bp));
|
||||
else {
|
||||
error = bwrite(bp);
|
||||
else if (vm_page_count_severe() || buf_dirty_count_severe())
|
||||
bawrite(bp);
|
||||
else
|
||||
bdwrite(bp);
|
||||
return (0);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -850,9 +850,6 @@ msdosfs_write(ap)
|
||||
|
||||
/*
|
||||
* Flush the blocks of a file to disk.
|
||||
*
|
||||
* This function is worthless for vnodes that represent directories. Maybe we
|
||||
* could just do a sync if they try an fsync on a directory file.
|
||||
*/
|
||||
static int
|
||||
msdosfs_fsync(ap)
|
||||
@ -863,9 +860,35 @@ msdosfs_fsync(ap)
|
||||
struct thread *a_td;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *devvp;
|
||||
int allerror, error;
|
||||
|
||||
vop_stdfsync(ap);
|
||||
return (deupdat(VTODE(ap->a_vp), ap->a_waitfor == MNT_WAIT));
|
||||
|
||||
/*
|
||||
* If the syncing request comes from fsync(2), sync the entire
|
||||
* FAT and any other metadata that happens to be on devvp. We
|
||||
* need this mainly for the FAT. We write the FAT sloppily, and
|
||||
* syncing it all now is the best we can easily do to get all
|
||||
* directory entries associated with the file (not just the file)
|
||||
* fully synced. The other metadata includes critical metadata
|
||||
* for all directory entries, but only in the MNT_ASYNC case. We
|
||||
* will soon sync all metadata in the file's directory entry.
|
||||
* Non-critical metadata for associated directory entries only
|
||||
* gets synced accidentally, as in most file systems.
|
||||
*/
|
||||
if (ap->a_waitfor == MNT_WAIT) {
|
||||
devvp = VTODE(ap->a_vp)->de_pmp->pm_devvp;
|
||||
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
||||
allerror = VOP_FSYNC(devvp, MNT_WAIT, ap->a_td);
|
||||
VOP_UNLOCK(devvp, 0);
|
||||
} else
|
||||
allerror = 0;
|
||||
|
||||
error = deupdat(VTODE(ap->a_vp), ap->a_waitfor == MNT_WAIT);
|
||||
if (allerror == 0)
|
||||
allerror = error;
|
||||
return (allerror);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user