summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authortrhodes <trhodes@FreeBSD.org>2003-12-26 17:19:19 +0000
committertrhodes <trhodes@FreeBSD.org>2003-12-26 17:19:19 +0000
commit7dde93f1df429cf9a818bf7b716962298f489807 (patch)
tree9835c24a1c804ff149a9d1763c5619fbd69ab703 /sys/fs
parent1b287b69e9efa62bb22618045208556c1edcbff7 (diff)
downloadFreeBSD-src-7dde93f1df429cf9a818bf7b716962298f489807.zip
FreeBSD-src-7dde93f1df429cf9a818bf7b716962298f489807.tar.gz
Make msdosfs support the dirty flag in FAT16 and FAT32.
Enable lockf support. PR: 55861 Submitted by: Jun Su <junsu@m-net.arbornet.org> (original version) Reviewed by: make universe
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/msdosfs/denode.h1
-rw-r--r--sys/fs/msdosfs/fat.h1
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c67
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c18
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c20
5 files changed, 106 insertions, 1 deletions
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 <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/signalvar.h>
+#include <sys/lockf.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -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 =
OpenPOWER on IntegriCloud