From 7dde93f1df429cf9a818bf7b716962298f489807 Mon Sep 17 00:00:00 2001 From: trhodes Date: Fri, 26 Dec 2003 17:19:19 +0000 Subject: Make msdosfs support the dirty flag in FAT16 and FAT32. Enable lockf support. PR: 55861 Submitted by: Jun Su (original version) Reviewed by: make universe --- sys/fs/msdosfs/denode.h | 1 + sys/fs/msdosfs/fat.h | 1 + sys/fs/msdosfs/msdosfs_fat.c | 67 +++++++++++++++++++++++++++++++++++++++++ sys/fs/msdosfs/msdosfs_vfsops.c | 18 ++++++++++- sys/fs/msdosfs/msdosfs_vnops.c | 20 ++++++++++++ 5 files changed, 106 insertions(+), 1 deletion(-) (limited to 'sys/fs') diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h index eed1bdc..128527e 100644 --- a/sys/fs/msdosfs/denode.h +++ b/sys/fs/msdosfs/denode.h @@ -160,6 +160,7 @@ struct denode { u_long de_FileSize; /* size of file in bytes */ struct fatcache de_fc[FC_SIZE]; /* fat cache */ u_quad_t de_modrev; /* Revision level for lease. */ + struct lockf *de_lockf; /* lockf */ }; /* diff --git a/sys/fs/msdosfs/fat.h b/sys/fs/msdosfs/fat.h index 216fde5..3b0599e 100644 --- a/sys/fs/msdosfs/fat.h +++ b/sys/fs/msdosfs/fat.h @@ -99,5 +99,6 @@ int fatentry(int function, struct msdosfsmount *pmp, u_long cluster, u_long *old int freeclusterchain(struct msdosfsmount *pmp, u_long startchain); int extendfile(struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags); void fc_purge(struct denode *dep, u_int frcn); +int markvoldirty(struct msdosfsmount *pmp, int dirty); #endif /* _KERNEL */ diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c index 1e9a3cf..1f75d7a 100644 --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -1106,3 +1106,70 @@ extendfile(dep, count, bpp, ncp, flags) return (0); } + +/* [2753891] + * Routine to mark a FAT16 or FAT32 volume as "clean" or "dirty" by manipulating the upper bit + * of the FAT entry for cluster 1. Note that this bit is not defined for FAT12 volumes, which + * are always assumed to be dirty. + * + * The fatentry() routine only works on cluster numbers that a file could occupy, so it won't + * manipulate the entry for cluster 1. So we have to do it here. The code is ripped from + * fatentry(), and tailored for cluster 1. + * + * Inputs: + * pmp The MS-DOS volume to mark + * dirty Non-zero if the volume should be marked dirty; zero if it should be marked clean. + * + * Result: + * 0 Success + * EROFS Volume is read-only + * ? (other errors from called routines) + */ +int markvoldirty(struct msdosfsmount *pmp, int dirty) +{ + int error; + u_long bn, bo, bsize, byteoffset; + u_long fatval; + struct buf *bp; + + /* FAT12 does not support a "clean" bit, so don't do anything */ + if (FAT12(pmp)) + return 0; + + /* Can't change the bit on a read-only filesystem */ + if (pmp->pm_flags & MSDOSFSMNT_RONLY) + return EROFS; + + /* Fetch the block containing the FAT entry */ + byteoffset = FATOFS(pmp, 1); /* Find the location of cluster 1 */ + fatblock(pmp, byteoffset, &bn, &bsize, &bo); + + error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); + if (error) { + brelse(bp); + return (error); + } + + /* Get the current value of the FAT entry and set/clear the high bit */ + if (FAT32(pmp)) { + /* FAT32 uses bit 27 */ + fatval = getulong(&bp->b_data[bo]); + if (dirty) + fatval &= 0xF7FFFFFF; /* dirty means clear the "clean" bit */ + else + fatval |= 0x08000000; /* clean means set the "clean" bit */ + putulong(&bp->b_data[bo], fatval); + } + else { + /* Must be FAT16; use bit 15 */ + fatval = getushort(&bp->b_data[bo]); + if (dirty) + fatval &= 0x7FFF; /* dirty means clear the "clean" bit */ + else + fatval |= 0x8000; /* clean means set the "clean" bit */ + putushort(&bp->b_data[bo], fatval); + } + + /* Write out the modified FAT block immediately */ + return bwrite(bp); +} diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 9e93ce3..31881c9 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -209,6 +209,11 @@ msdosfs_mount(mp, path, data, ndp, td) VOP_UNLOCK(devvp, 0, td); } pmp->pm_flags &= ~MSDOSFSMNT_RONLY; + + /* [2753891] Now that the volume is modifiable, mark it dirty */ + error = markvoldirty(pmp, 1); + if (error) + return error; } if (args.fspec == 0) { #ifdef __notyet__ /* doesn't work correctly with current mountd XXX */ @@ -609,8 +614,12 @@ mountmsdosfs(devvp, mp, td, argp) */ if (ronly) pmp->pm_flags |= MSDOSFSMNT_RONLY; - else + else { + /* [2753891] Mark the volume dirty while it is mounted read/write */ + if ((error = markvoldirty(pmp, 1)) != 0) + goto error_exit; pmp->pm_fmod = 1; + } mp->mnt_data = (qaddr_t) pmp; mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; @@ -667,6 +676,13 @@ msdosfs_unmount(mp, mntflags, td) msdosfs_iconv->close(pmp->pm_u2d); } pmp->pm_devvp->v_rdev->si_mountpoint = NULL; + + /* [2753891] If the volume was mounted read/write, mark it clean now */ + if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) { + error = markvoldirty(pmp, 0); + if (error && !(flags & FORCECLOSE)) + return (error); + } #ifdef MSDOSFS_DEBUG { struct vnode *vp = pmp->pm_devvp; diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index f1d0b63..885b665 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ static int msdosfs_bmap(struct vop_bmap_args *); static int msdosfs_strategy(struct vop_strategy_args *); static int msdosfs_print(struct vop_print_args *); static int msdosfs_pathconf(struct vop_pathconf_args *ap); +static int msdosfs_advlock(struct vop_advlock_args *); /* * Some general notes: @@ -1836,6 +1838,23 @@ msdosfs_pathconf(ap) /* NOTREACHED */ } +/* + * Advisory record locking support + */ +static int +msdosfs_advlock(ap) + struct vop_advlock_args /* { + struct vnode *a_vp; + u_char a_id; + int a_op; + struct flock *a_fl; + int a_flags; + } */ *ap; +{ + struct denode *ip = VTODE(ap->a_vp); + + return (lf_advlock(ap, &(ip->de_lockf), ip->de_FileSize)); +} /* Global vfs data structures for msdosfs */ vop_t **msdosfs_vnodeop_p; @@ -1865,6 +1884,7 @@ static struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = { { &vop_strategy_desc, (vop_t *) msdosfs_strategy }, { &vop_symlink_desc, (vop_t *) msdosfs_symlink }, { &vop_write_desc, (vop_t *) msdosfs_write }, + { &vop_advlock_desc, (vop_t *) msdosfs_advlock }, { NULL, NULL } }; static struct vnodeopv_desc msdosfs_vnodeop_opv_desc = -- cgit v1.1