I can not make my MTA work..... ================================ To: FreeBSD-gnats-submit_at_freebsd.org From: Jun Su <csujun_at_263.net> Reply-To: Jun Su <csujun_at_263.net> Cc: X-send-pr-version: 3.113 X-GNATS-Notify: >Submitter-Id: current-users >Originator: Jun Su >Organization: none >Confidential: no <FreeBSD PRs are public data> >Synopsis: [PATCH] MSDOSFS dirty path (importing from Darwin) >Severity: non-critical >Priority: medium >Category: kern >Class: change-request >Release: FreeBSD 5.1-CURRENT i386 >Environment: System: FreeBSD junsufr.gwbn.sh.cn 5.1-CURRENT FreeBSD 5.1-CURRENT #1: Thu Jul 17 18:01:10 CST 2003 root_at_junsufr.gwbn.sh.cn:/usr/obj/usr/src/sys/VAIO i386 >Description: A TODO item in the 5.2 Release Must Resolve List. >How-To-Repeat: >Fix: diff -u /usr/src/sys/fs/msdosfs.orig/fat.h msdosfs/fat.h --- /usr/src/sys/fs/msdosfs.orig/fat.h Tue Mar 19 22:20:10 2002 +++ msdosfs/fat.h Mon Jul 14 21:02:10 2003 _at__at_ -99,5 +99,6 _at__at_ 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 */ Only in msdosfs: fat.h.orig diff -u /usr/src/sys/fs/msdosfs.orig/msdosfs_fat.c msdosfs/msdosfs_fat.c --- /usr/src/sys/fs/msdosfs.orig/msdosfs_fat.c Tue Mar 4 00:04:42 2003 +++ msdosfs/msdosfs_fat.c Mon Jul 14 21:02:10 2003 _at__at_ -1106,3 +1106,70 _at__at_ 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); +} Only in msdosfs: msdosfs_fat.c.orig diff -u /usr/src/sys/fs/msdosfs.orig/msdosfs_vfsops.c msdosfs/msdosfs_vfsops.c --- /usr/src/sys/fs/msdosfs.orig/msdosfs_vfsops.c Sun Jun 29 03:05:59 2003 +++ msdosfs/msdosfs_vfsops.c Mon Jul 14 21:02:11 2003 _at__at_ -203,6 +203,11 _at__at_ 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 */ _at__at_ -603,8 +608,13 _at__at_ */ 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; _at__at_ -651,6 +661,14 _at__at_ return error; pmp = VFSTOMSDOSFS(mp); 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 -u /usr/src/sbin/fsck_msdosfs.orig/check.c fsck_msdosfs/check.c --- /usr/src/sbin/fsck_msdosfs.orig/check.c Wed Aug 21 18:10:33 2002 +++ fsck_msdosfs/check.c Sun Jul 13 22:00:24 2003 _at__at_ -85,6 +85,13 _at__at_ return 8; } + if (checkdirty(dosfs, &boot) && !force) { + if (preen) printf("%s: ", fname); + printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); + ret = 0; + goto out; + } + if (!preen) { if (boot.ValidFat < 0) printf("** Phase 1 - Read and Compare FATs\n"); _at__at_ -190,5 +197,51 _at__at_ if (mod & (FSFATMOD|FSDIRMOD)) pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + return ret; +} + +int checkdirty(int fs, struct bootblock *boot) +{ + off_t off; + u_char *buffer; + u_long dirtyflag; + int ret = 0; + + if (boot->ClustMask == CLUST12_MASK) + return 0; + + off = boot->ResSectors; + off *= boot->BytesPerSec; + + buffer = malloc(boot->BytesPerSec); + if (buffer == NULL) { + perror("No space for FAT"); + return 1; + } + + if (lseek(fs, off, SEEK_SET) != off) { + perror("Unable to read FAT"); + goto err; + } + + if (read(fs, buffer, boot->BytesPerSec) + != boot->BytesPerSec) { + perror("Unable to read FAT"); + goto err; + } + + if (buffer[0] == boot->Media && buffer[1] == 0xff + && buffer[2] == 0xff + && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) + || (boot->ClustMask == CLUST32_MASK + && buffer[3] == 0x0f && buffer[4] == 0xff + && buffer[5] == 0xff && buffer[6] == 0xff + && buffer[7] == 0x07))) + ret = 0; + else + ret = 1; + +err: + free(buffer); return ret; } diff -u /usr/src/sbin/fsck_msdosfs.orig/ext.h fsck_msdosfs/ext.h --- /usr/src/sbin/fsck_msdosfs.orig/ext.h Wed Aug 21 18:10:33 2002 +++ fsck_msdosfs/ext.h Sun Jul 13 17:39:14 2003 _at__at_ -48,6 +48,7 _at__at_ extern int alwaysyes; /* assume "yes" for all questions */ extern int preen; /* we are preening */ extern int rdonly; /* device is opened read only (supersedes above) */ +extern int force; extern char *fname; /* file system currently checked */ _at__at_ -85,6 +86,12 _at__at_ * Correct the FSInfo block. */ int writefsinfo(int, struct bootblock *); + +/* + * Check the dirty flag. If clean return 1, otherwise return 0. + * If it is FAT12, return 0 always. + */ +int checkdirty(int, struct bootblock *); /* * Read one of the FAT copies and return a pointer to the new diff -u /usr/src/sbin/fsck_msdosfs.orig/main.c fsck_msdosfs/main.c --- /usr/src/sbin/fsck_msdosfs.orig/main.c Tue Aug 27 00:49:22 2002 +++ fsck_msdosfs/main.c Sun Jul 13 17:39:14 2003 _at__at_ -53,6 +53,7 _at__at_ int alwaysyes; /* assume "yes" for all questions */ int preen; /* set when preening */ int rdonly; /* device is opened read only (supersedes above) */ +int force; /* force check even the fs is clean */ static void usage(void) __dead2; _at__at_ -67,14 +68,12 _at__at_ { int ret = 0, erg; int ch; - + + force = 0; while ((ch = getopt(argc, argv, "fFnpy")) != -1) { switch (ch) { case 'f': - /* - * We are always forced, since we don't - * have a clean flag - */ + force = 1; break; case 'F': /* We can never run in background */ __________________________________ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.comReceived on Fri Jul 18 2003 - 17:39:41 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:15 UTC