mfs: clean flag
. also implement now-possible fsck -p option . allows unconditional fsck -p invocation at startup, only checking each filesystem if not marked clean . mounting unclean is allowed but is forced readonly . updating the superblock while mounted is now not allowed by mfs - must be done (e.g. by fsck.mfs) on an unmounted fs . clean flag is unset by mfs on mounting, and set by mfs on clean unmounting (if clean flag was set at mount time) Signed-off-by: Ben Gras <ben@minix3.org>
This commit is contained in:
parent
9a664b4984
commit
59ff5cbd87
13 changed files with 292 additions and 76 deletions
|
@ -146,7 +146,8 @@ int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
|
||||||
int nsock, npipe, nsyml, ztype[NLEVEL];
|
int nsock, npipe, nsyml, ztype[NLEVEL];
|
||||||
long nfreezone;
|
long nfreezone;
|
||||||
|
|
||||||
int repair, automatic, listing, listsuper; /* flags */
|
int repair, notrepaired = 0, automatic, listing, listsuper; /* flags */
|
||||||
|
int preen = 0, markdirty = 0;
|
||||||
int firstlist; /* has the listing header been printed? */
|
int firstlist; /* has the listing header been printed? */
|
||||||
unsigned part_offset; /* sector offset for this partition */
|
unsigned part_offset; /* sector offset for this partition */
|
||||||
char answer[] = "Answer questions with y or n. Then hit RETURN";
|
char answer[] = "Answer questions with y or n. Then hit RETURN";
|
||||||
|
@ -172,7 +173,9 @@ _PROTOTYPE(void lpr, (char *fmt, long cnt, char *s, char *p));
|
||||||
_PROTOTYPE(bit_nr getnumber, (char *s));
|
_PROTOTYPE(bit_nr getnumber, (char *s));
|
||||||
_PROTOTYPE(char **getlist, (char ***argv, char *type));
|
_PROTOTYPE(char **getlist, (char ***argv, char *type));
|
||||||
_PROTOTYPE(void lsuper, (void));
|
_PROTOTYPE(void lsuper, (void));
|
||||||
_PROTOTYPE(void getsuper, (void));
|
#define SUPER_GET 0
|
||||||
|
#define SUPER_PUT 1
|
||||||
|
_PROTOTYPE(void rw_super, (int mode));
|
||||||
_PROTOTYPE(void chksuper, (void));
|
_PROTOTYPE(void chksuper, (void));
|
||||||
_PROTOTYPE(void lsi, (char **clist));
|
_PROTOTYPE(void lsi, (char **clist));
|
||||||
_PROTOTYPE(bitchunk_t *allocbitmap, (int nblk));
|
_PROTOTYPE(bitchunk_t *allocbitmap, (int nblk));
|
||||||
|
@ -251,6 +254,7 @@ char *question;
|
||||||
{
|
{
|
||||||
register int c, answerchar;
|
register int c, answerchar;
|
||||||
static int note = 0;
|
static int note = 0;
|
||||||
|
int yes;
|
||||||
|
|
||||||
if (!repair) {
|
if (!repair) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -266,7 +270,9 @@ char *question;
|
||||||
if ((c = answerchar = getchar()) == 'q' || c == 'Q') exit(1);
|
if ((c = answerchar = getchar()) == 'q' || c == 'Q') exit(1);
|
||||||
if(c == 'A') { automatic = 1; c = 'y'; }
|
if(c == 'A') { automatic = 1; c = 'y'; }
|
||||||
while (!eoln(c)) c = getchar();
|
while (!eoln(c)) c = getchar();
|
||||||
return !(answerchar == 'n' || answerchar == 'N');
|
yes = !(answerchar == 'n' || answerchar == 'N');
|
||||||
|
if(!yes) notrepaired = 1;
|
||||||
|
return yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert string to integer. Representation is octal. */
|
/* Convert string to integer. Representation is octal. */
|
||||||
|
@ -373,7 +379,8 @@ int nlcr;
|
||||||
/* Open the device. */
|
/* Open the device. */
|
||||||
void devopen()
|
void devopen()
|
||||||
{
|
{
|
||||||
if ((dev = open(fsck_device, repair ? O_RDWR : O_RDONLY)) < 0) {
|
if ((dev = open(fsck_device,
|
||||||
|
(repair || markdirty) ? O_RDWR : O_RDONLY)) < 0) {
|
||||||
perror(fsck_device);
|
perror(fsck_device);
|
||||||
fatal("couldn't open device to fsck");
|
fatal("couldn't open device to fsck");
|
||||||
}
|
}
|
||||||
|
@ -540,17 +547,26 @@ void lsuper()
|
||||||
devwrite(0, OFFSET_SUPER_BLOCK, (char *) &sb, sizeof(sb));
|
devwrite(0, OFFSET_SUPER_BLOCK, (char *) &sb, sizeof(sb));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
printf("flags = ");
|
||||||
|
if(sb.s_flags & MFSFLAG_CLEAN) printf("CLEAN "); else printf("DIRTY ");
|
||||||
|
printf("\n");
|
||||||
} while (yes("Do you want to try again"));
|
} while (yes("Do you want to try again"));
|
||||||
if (repair) exit(0);
|
if (repair) exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the super block from either disk or user. Do some initial checks. */
|
/* Get the super block from either disk or user. Do some initial checks. */
|
||||||
void getsuper()
|
void rw_super(int put)
|
||||||
{
|
{
|
||||||
if(lseek(dev, OFFSET_SUPER_BLOCK, SEEK_SET) < 0) {
|
if(lseek(dev, OFFSET_SUPER_BLOCK, SEEK_SET) < 0) {
|
||||||
perror("lseek");
|
perror("lseek");
|
||||||
fatal("couldn't seek to super block.");
|
fatal("couldn't seek to super block.");
|
||||||
}
|
}
|
||||||
|
if(put == SUPER_PUT) {
|
||||||
|
if(write(dev, &sb, sizeof(sb)) != sizeof(sb)) {
|
||||||
|
fatal("couldn't write super block.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(read(dev, &sb, sizeof(sb)) != sizeof(sb)) {
|
if(read(dev, &sb, sizeof(sb)) != sizeof(sb)) {
|
||||||
fatal("couldn't read super block.");
|
fatal("couldn't read super block.");
|
||||||
}
|
}
|
||||||
|
@ -628,6 +644,10 @@ void chksuper()
|
||||||
printf("warning: expected max size to be %ld ", maxsize);
|
printf("warning: expected max size to be %ld ", maxsize);
|
||||||
printf("instead of %ld\n", sb.s_max_size);
|
printf("instead of %ld\n", sb.s_max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sb.s_flags & MFSFLAG_MANDATORY_MASK) {
|
||||||
|
fatal("unsupported feature bits - newer fsck needed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int inoblock(int inn)
|
int inoblock(int inn)
|
||||||
|
@ -795,7 +815,9 @@ char *type;
|
||||||
int w = nblk * WORDS_PER_BLOCK;
|
int w = nblk * WORDS_PER_BLOCK;
|
||||||
bit_nr phys = 0;
|
bit_nr phys = 0;
|
||||||
|
|
||||||
printf("Checking %s map\n", type);
|
printf("Checking %s map. ", type);
|
||||||
|
if(!preen) printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
loadbitmap(dmap, blkno, nblk);
|
loadbitmap(dmap, blkno, nblk);
|
||||||
do {
|
do {
|
||||||
if (*p != *q) chkword(*p, *q, bit, type, &nerr, &report, phys);
|
if (*p != *q) chkword(*p, *q, bit, type, &nerr, &report, phys);
|
||||||
|
@ -817,7 +839,9 @@ void chkilist()
|
||||||
register ino_t ino = 1;
|
register ino_t ino = 1;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
|
||||||
printf("Checking inode list\n");
|
printf("Checking inode list. ");
|
||||||
|
if(!preen) printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
do
|
do
|
||||||
if (!bitset(imap, (bit_nr) ino)) {
|
if (!bitset(imap, (bit_nr) ino)) {
|
||||||
devread(inoblock(ino), inooff(ino), (char *) &mode,
|
devread(inoblock(ino), inooff(ino), (char *) &mode,
|
||||||
|
@ -829,7 +853,7 @@ void chkilist()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (++ino <= sb.s_ninodes && ino != 0);
|
while (++ino <= sb.s_ninodes && ino != 0);
|
||||||
printf("\n");
|
if(!preen) printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate an array to maintain the inode reference counts in. */
|
/* Allocate an array to maintain the inode reference counts in. */
|
||||||
|
@ -1471,6 +1495,12 @@ void chktree()
|
||||||
/* Print the totals of all the objects found. */
|
/* Print the totals of all the objects found. */
|
||||||
void printtotal()
|
void printtotal()
|
||||||
{
|
{
|
||||||
|
if(preen) {
|
||||||
|
printf("%d files, %d directories, %d free inodes, %d free zones\n",
|
||||||
|
nregular, ndirectory, nfreeinode, nfreezone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
printf("blocksize = %5d ", block_size);
|
printf("blocksize = %5d ", block_size);
|
||||||
printf("zonesize = %5d\n", ZONE_SIZE);
|
printf("zonesize = %5d\n", ZONE_SIZE);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -1506,7 +1536,7 @@ char *f, **clist, **ilist, **zlist;
|
||||||
|
|
||||||
devopen();
|
devopen();
|
||||||
|
|
||||||
getsuper();
|
rw_super(SUPER_GET);
|
||||||
|
|
||||||
if(block_size < _MIN_BLOCK_SIZE)
|
if(block_size < _MIN_BLOCK_SIZE)
|
||||||
fatal("funny block size");
|
fatal("funny block size");
|
||||||
|
@ -1517,6 +1547,25 @@ char *f, **clist, **ilist, **zlist;
|
||||||
|
|
||||||
chksuper();
|
chksuper();
|
||||||
|
|
||||||
|
if(markdirty) {
|
||||||
|
if(sb.s_flags & MFSFLAG_CLEAN) {
|
||||||
|
sb.s_flags &= ~MFSFLAG_CLEAN;
|
||||||
|
rw_super(SUPER_PUT);
|
||||||
|
printf("\n----- FILE SYSTEM MARKED DIRTY -----\n\n");
|
||||||
|
} else {
|
||||||
|
printf("Filesystem is already dirty.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If preening, skip fsck if clean flag is on. */
|
||||||
|
if(preen) {
|
||||||
|
if(sb.s_flags & MFSFLAG_CLEAN) {
|
||||||
|
printf("%s: clean\n", f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s: dirty, performing fsck\n", f);
|
||||||
|
}
|
||||||
|
|
||||||
lsi(clist);
|
lsi(clist);
|
||||||
|
|
||||||
getbitmaps();
|
getbitmaps();
|
||||||
|
@ -1530,13 +1579,29 @@ char *f, **clist, **ilist, **zlist;
|
||||||
chkcount();
|
chkcount();
|
||||||
chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP, "inode");
|
chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP, "inode");
|
||||||
chkilist();
|
chkilist();
|
||||||
|
if(preen) printf("\n");
|
||||||
printtotal();
|
printtotal();
|
||||||
|
|
||||||
putbitmaps();
|
putbitmaps();
|
||||||
freecount();
|
freecount();
|
||||||
devclose();
|
|
||||||
|
|
||||||
if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
|
if (changed) printf("\n----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
|
||||||
|
|
||||||
|
/* If we were told to repair the FS, and the user never stopped us from
|
||||||
|
* doing it, and the FS wasn't marked clean, we can mark the FS as clean.
|
||||||
|
*/
|
||||||
|
if(repair && !(sb.s_flags & MFSFLAG_CLEAN)) {
|
||||||
|
if(notrepaired) {
|
||||||
|
printf("\n----- FILE SYSTEM STILL DIRTY -----\n\n");
|
||||||
|
} else {
|
||||||
|
sync(); /* update FS on disk before clean flag */
|
||||||
|
sb.s_flags |= MFSFLAG_CLEAN;
|
||||||
|
rw_super(SUPER_PUT);
|
||||||
|
printf("\n----- FILE SYSTEM MARKED CLEAN -----\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
devclose();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(argc, argv)
|
int main(argc, argv)
|
||||||
|
@ -1557,8 +1622,9 @@ char **argv;
|
||||||
prog = *argv++;
|
prog = *argv++;
|
||||||
while ((arg = *argv++) != 0)
|
while ((arg = *argv++) != 0)
|
||||||
if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) {
|
if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) {
|
||||||
|
case 'd': markdirty = 1; break;
|
||||||
|
case 'p': preen = repair = automatic = 1; break;
|
||||||
case 'y':
|
case 'y':
|
||||||
case 'p':
|
|
||||||
case 'a': automatic ^= 1; break;
|
case 'a': automatic ^= 1; break;
|
||||||
case 'c':
|
case 'c':
|
||||||
clist = getlist(&argv, "inode");
|
clist = getlist(&argv, "inode");
|
||||||
|
@ -1584,7 +1650,7 @@ char **argv;
|
||||||
devgiven = 1;
|
devgiven = 1;
|
||||||
}
|
}
|
||||||
if (!devgiven) {
|
if (!devgiven) {
|
||||||
printf("Usage: fsck [-yfpacilrsz] file\n");
|
printf("Usage: fsck [-dyfpacilrsz] file\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -388,6 +388,7 @@ char *device;
|
||||||
unsigned int rem;
|
unsigned int rem;
|
||||||
u64_t resize;
|
u64_t resize;
|
||||||
|
|
||||||
|
|
||||||
if ((fd = open(device, O_RDONLY)) == -1) {
|
if ((fd = open(device, O_RDONLY)) == -1) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
perror("sizeup open");
|
perror("sizeup open");
|
||||||
|
@ -403,6 +404,7 @@ char *device;
|
||||||
entry.size = cvu64(st.st_size);
|
entry.size = cvu64(st.st_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
d = div64u(entry.size, block_size);
|
d = div64u(entry.size, block_size);
|
||||||
rem = rem64u(entry.size, block_size);
|
rem = rem64u(entry.size, block_size);
|
||||||
|
@ -439,6 +441,9 @@ ino_t inodes;
|
||||||
for (cp = buf; cp < &buf[block_size]; cp++) *cp = 0;
|
for (cp = buf; cp < &buf[block_size]; cp++) *cp = 0;
|
||||||
sup = (struct super_block *) buf; /* lint - might use a union */
|
sup = (struct super_block *) buf; /* lint - might use a union */
|
||||||
|
|
||||||
|
/* The assumption is that mkfs will create a clean FS. */
|
||||||
|
sup->s_flags = MFSFLAG_CLEAN;
|
||||||
|
|
||||||
sup->s_ninodes = inodes;
|
sup->s_ninodes = inodes;
|
||||||
if (fs_version == 1) {
|
if (fs_version == 1) {
|
||||||
sup->s_nzones = zones;
|
sup->s_nzones = zones;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
PROGRAMS= at_wini bios_wini cdprobe dev2name floppy loadramdisk mount \
|
PROGRAMS= at_wini bios_wini cdprobe dev2name floppy loadramdisk mount \
|
||||||
pci procfs sh service sysenv mfs
|
pci procfs sh service sysenv mfs fsck.mfs
|
||||||
SCRIPTS=newroot
|
SCRIPTS=newroot
|
||||||
|
|
||||||
.if ${MKSMALL} != "yes"
|
.if ${MKSMALL} != "yes"
|
||||||
|
@ -43,6 +43,11 @@ bintoc: bintoc.c
|
||||||
|
|
||||||
image: proto.gen mtab rc $(EXTRA)
|
image: proto.gen mtab rc $(EXTRA)
|
||||||
mkfs.mfs image proto.gen || { rm -f image; false; }
|
mkfs.mfs image proto.gen || { rm -f image; false; }
|
||||||
|
if fsck.mfs -s image | grep -q CLEAN; \
|
||||||
|
then : ; \
|
||||||
|
else echo "CLEAN sanity check of image failed." ; \
|
||||||
|
echo "(Perhaps install current mkfs and fsck.)" ; \
|
||||||
|
fi
|
||||||
|
|
||||||
ahci: ../ahci/ahci
|
ahci: ../ahci/ahci
|
||||||
install ${STRIPFLAG} ../$@/$@ $@
|
install ${STRIPFLAG} ../$@/$@ $@
|
||||||
|
@ -104,6 +109,12 @@ mount: ../../commands/mount/mount
|
||||||
../../commands/mount/mount:
|
../../commands/mount/mount:
|
||||||
$(MAKE) -C ../../commands/mount
|
$(MAKE) -C ../../commands/mount
|
||||||
|
|
||||||
|
fsck.mfs: ../../commands/fsck.mfs/fsck.mfs
|
||||||
|
install ${STRIPFLAG} ../../commands/$@/$@ $@
|
||||||
|
|
||||||
|
../../commands/fsck.mfs/fsck.mfs:
|
||||||
|
$(MAKE) -C ../../commands/fsck.mfs
|
||||||
|
|
||||||
newroot: ../../commands/newroot/newroot.sh
|
newroot: ../../commands/newroot/newroot.sh
|
||||||
install ${STRIPFLAG} ../../commands/$@/$@.sh $@
|
install ${STRIPFLAG} ../../commands/$@/$@.sh $@
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ d--755 0 0
|
||||||
sh ---755 0 0 sh
|
sh ---755 0 0 sh
|
||||||
service ---755 0 0 service
|
service ---755 0 0 service
|
||||||
sysenv ---755 0 0 sysenv
|
sysenv ---755 0 0 sysenv
|
||||||
|
fsck.mfs ---755 0 0 fsck.mfs
|
||||||
$
|
$
|
||||||
sbin d--755 0 0
|
sbin d--755 0 0
|
||||||
@ACPI@
|
@ACPI@
|
||||||
|
|
|
@ -5,6 +5,7 @@ exec >/dev/log
|
||||||
exec 2>/dev/log
|
exec 2>/dev/log
|
||||||
exec </dev/null
|
exec </dev/null
|
||||||
|
|
||||||
|
FSCK=/bin/fsck.mfs
|
||||||
ACPI=/sbin/acpi
|
ACPI=/sbin/acpi
|
||||||
if [ -e $ACPI -a -n "`sysenv acpi`" ]
|
if [ -e $ACPI -a -n "`sysenv acpi`" ]
|
||||||
then
|
then
|
||||||
|
@ -56,6 +57,10 @@ then
|
||||||
loadramdisk "$ramimagename"
|
loadramdisk "$ramimagename"
|
||||||
fi
|
fi
|
||||||
echo "Root device name is $rootdevname"
|
echo "Root device name is $rootdevname"
|
||||||
|
if [ -e $FSCK ]
|
||||||
|
then $FSCK -p $rootdevname
|
||||||
|
fi
|
||||||
/bin/newroot $bin_img"$rootdevname"
|
/bin/newroot $bin_img"$rootdevname"
|
||||||
/bin/mount -e -t procfs none /proc || echo "WARNING: couldn't mount procfs"
|
/bin/mount -e -t procfs none /proc || echo "WARNING: couldn't mount procfs"
|
||||||
|
|
||||||
exec /bin/sh /etc/rc "$@"
|
exec /bin/sh /etc/rc "$@"
|
||||||
|
|
|
@ -38,7 +38,7 @@ install:: installpw # installpw needed to bootstrap pw db
|
||||||
install -m 644 -o root -g operator descr /usr/lib/
|
install -m 644 -o root -g operator descr /usr/lib/
|
||||||
|
|
||||||
|
|
||||||
installforce:: $(ETC)/rc $(ETC)/rs.inet $(ETC)/rs.single $(ETC)/system.conf $(USRETC)/rc $(USR)/Makefile installpw
|
installforce:: $(ETC)/rc $(ETC)/rs.inet $(ETC)/rs.single $(ETC)/system.conf $(ETC)/rc.subr.minix $(USRETC)/rc $(USR)/Makefile installpw
|
||||||
|
|
||||||
installpw::
|
installpw::
|
||||||
if [ ! -d $(ETC) ]; then mkdir $(ETC); chmod 755 $(ETC); fi
|
if [ ! -d $(ETC) ]; then mkdir $(ETC); chmod 755 $(ETC); fi
|
||||||
|
@ -57,6 +57,9 @@ $(ETC)/rs.single: rs.single .PHONY
|
||||||
$(ETC)/system.conf: system.conf .PHONY
|
$(ETC)/system.conf: system.conf .PHONY
|
||||||
install -m 644 -o root -g operator $> $@
|
install -m 644 -o root -g operator $> $@
|
||||||
|
|
||||||
|
$(ETC)/rc.subr.minix: rc.subr.minix .PHONY
|
||||||
|
install -m 644 -o root -g operator $> $@
|
||||||
|
|
||||||
$(USRETC)/rc: usr/rc .PHONY
|
$(USRETC)/rc: usr/rc .PHONY
|
||||||
install -m 755 -o root -g operator $> $@
|
install -m 755 -o root -g operator $> $@
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
mountfstab()
|
mountfstab()
|
||||||
{
|
{
|
||||||
fsck_opts=""
|
fsck_opts=""
|
||||||
fflag=""
|
fflag="-p"
|
||||||
|
|
||||||
while getopts "fo:" opt
|
while getopts "fo:" opt
|
||||||
do case $opt
|
do case $opt
|
||||||
|
@ -18,13 +18,6 @@ mountfstab()
|
||||||
|
|
||||||
shift `expr $OPTIND - 1`
|
shift `expr $OPTIND - 1`
|
||||||
|
|
||||||
# Make fsck necessary for unclean shutdown
|
|
||||||
msg="The system was not properly shut down. Checking file systems."
|
|
||||||
if shutdown -C
|
|
||||||
then echo "$msg"
|
|
||||||
fflag="-f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fstabfile="$1"
|
fstabfile="$1"
|
||||||
|
|
||||||
if [ ! -f $fstabfile ]
|
if [ ! -f $fstabfile ]
|
||||||
|
@ -44,17 +37,16 @@ mountfstab()
|
||||||
# This line's parameters
|
# This line's parameters
|
||||||
dev="$1"; mp="$2"; fstype="$3"
|
dev="$1"; mp="$2"; fstype="$3"
|
||||||
|
|
||||||
|
# Don't fsck / as it's already mounted
|
||||||
|
if [ "$mp" = "/" ]; then continue; fi
|
||||||
|
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
if [ ! -b $dev ]; then echo "$dev missing"; continue; fi
|
if [ ! -b $dev ]; then echo "$dev missing"; continue; fi
|
||||||
if [ ! -d $mp ]; then echo "$mp missing"; continue; fi
|
if [ ! -d $mp ]; then echo "$mp missing"; continue; fi
|
||||||
|
|
||||||
# Do fsck if necessary or requested
|
# Do fsck if necessary or requested
|
||||||
if [ -n "$fflag" ]
|
if [ -n "$fflag" ]
|
||||||
then echo "Checking $fstype $dev"
|
then fsck.$fstype $fflag $fsck_opts $dev
|
||||||
if ! fsck.$fstype $fflag $fsck_opts -p $dev
|
|
||||||
then echo "$dev fail"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Skip the actual mount for /, it's already mounted
|
# Skip the actual mount for /, it's already mounted
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* invalidate: remove all the cache blocks on some device
|
* invalidate: remove all the cache blocks on some device
|
||||||
*
|
*
|
||||||
* Private functions:
|
* Private functions:
|
||||||
* rw_block: read or write a block from the disk itself
|
* read_block: read or write a block from the disk itself
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
@ -27,10 +27,12 @@
|
||||||
#include "inode.h"
|
#include "inode.h"
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
|
FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
|
||||||
FORWARD _PROTOTYPE( void rw_block, (struct buf *, int) );
|
FORWARD _PROTOTYPE( void read_block, (struct buf *) );
|
||||||
|
|
||||||
PRIVATE int vmcache = 0; /* are we using vm's secondary cache? (initially not) */
|
PRIVATE int vmcache = 0; /* are we using vm's secondary cache? (initially not) */
|
||||||
|
|
||||||
|
PRIVATE block_t super_start = 0, super_end = 0;
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* get_block *
|
* get_block *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -183,7 +185,7 @@ PUBLIC struct buf *get_block(
|
||||||
/* PREFETCH: don't do i/o. */
|
/* PREFETCH: don't do i/o. */
|
||||||
bp->b_dev = NO_DEV;
|
bp->b_dev = NO_DEV;
|
||||||
} else if (only_search == NORMAL) {
|
} else if (only_search == NORMAL) {
|
||||||
rw_block(bp, READING);
|
read_block(bp);
|
||||||
} else if(only_search == NO_READ) {
|
} else if(only_search == NO_READ) {
|
||||||
/* we want this block, but its contents
|
/* we want this block, but its contents
|
||||||
* will be overwritten. VM has to forget
|
* will be overwritten. VM has to forget
|
||||||
|
@ -318,11 +320,10 @@ PUBLIC void free_zone(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* rw_block *
|
* read_block *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void rw_block(bp, rw_flag)
|
PRIVATE void read_block(bp)
|
||||||
register struct buf *bp; /* buffer pointer */
|
register struct buf *bp; /* buffer pointer */
|
||||||
int rw_flag; /* READING or WRITING */
|
|
||||||
{
|
{
|
||||||
/* Read or write a disk block. This is the only routine in which actual disk
|
/* Read or write a disk block. This is the only routine in which actual disk
|
||||||
* I/O is invoked. If an error occurs, a message is printed here, but the error
|
* I/O is invoked. If an error occurs, a message is printed here, but the error
|
||||||
|
@ -337,12 +338,8 @@ int rw_flag; /* READING or WRITING */
|
||||||
|
|
||||||
if ( (dev = bp->b_dev) != NO_DEV) {
|
if ( (dev = bp->b_dev) != NO_DEV) {
|
||||||
pos = mul64u(bp->b_blocknr, fs_block_size);
|
pos = mul64u(bp->b_blocknr, fs_block_size);
|
||||||
if (rw_flag == READING)
|
|
||||||
r = bdev_read(dev, pos, bp->b_data, fs_block_size,
|
r = bdev_read(dev, pos, bp->b_data, fs_block_size,
|
||||||
BDEV_NOFLAGS);
|
BDEV_NOFLAGS);
|
||||||
else
|
|
||||||
r = bdev_write(dev, pos, bp->b_data, fs_block_size,
|
|
||||||
BDEV_NOFLAGS);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
printf("MFS(%d) I/O error on device %d/%d, block %u\n",
|
printf("MFS(%d) I/O error on device %d/%d, block %u\n",
|
||||||
SELF_E, major(dev), minor(dev), bp->b_blocknr);
|
SELF_E, major(dev), minor(dev), bp->b_blocknr);
|
||||||
|
@ -356,11 +353,9 @@ int rw_flag; /* READING or WRITING */
|
||||||
bp->b_dev = NO_DEV; /* invalidate block */
|
bp->b_dev = NO_DEV; /* invalidate block */
|
||||||
|
|
||||||
/* Report read errors to interested parties. */
|
/* Report read errors to interested parties. */
|
||||||
if (rw_flag == READING) rdwt_err = r;
|
rdwt_err = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MARKCLEAN(bp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -380,6 +375,27 @@ PUBLIC void invalidate(
|
||||||
vm_forgetblocks();
|
vm_forgetblocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* block_write_ok *
|
||||||
|
*===========================================================================*/
|
||||||
|
int block_write_ok(struct buf *bp)
|
||||||
|
{
|
||||||
|
if(superblock.s_dev != bp->b_dev) return 1;
|
||||||
|
|
||||||
|
if(bp->b_blocknr >= super_start && bp->b_blocknr <= super_end) {
|
||||||
|
printf("MFS: blocking write to superblock on mounted filesystem dev 0x%x.\n", bp->b_dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(superblock.s_rd_only) {
|
||||||
|
printf("MFS: blocking write to mounted readonly filesystem 0x%x.\n", bp->b_dev);
|
||||||
|
printf("This shouldn't happen.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* flushall *
|
* flushall *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -404,8 +420,16 @@ PUBLIC void flushall(
|
||||||
dirtylistsize = nr_bufs;
|
dirtylistsize = nr_bufs;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bp = &buf[0], ndirty = 0; bp < &buf[nr_bufs]; bp++)
|
for (bp = &buf[0], ndirty = 0; bp < &buf[nr_bufs]; bp++) {
|
||||||
if (ISDIRTY(bp) && bp->b_dev == dev) dirty[ndirty++] = bp;
|
if (ISDIRTY(bp) && bp->b_dev == dev) {
|
||||||
|
if(!block_write_ok(bp)) {
|
||||||
|
printf("MFS: LATE: ignoring changes in block %d\n", bp->b_blocknr);
|
||||||
|
MARKCLEAN(bp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dirty[ndirty++] = bp;
|
||||||
|
}
|
||||||
|
}
|
||||||
rw_scattered(dev, dirty, ndirty, WRITING);
|
rw_scattered(dev, dirty, ndirty, WRITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,6 +580,8 @@ PRIVATE void cache_resize(unsigned int blocksize, unsigned int bufs)
|
||||||
buf_pool(bufs);
|
buf_pool(bufs);
|
||||||
|
|
||||||
fs_block_size = blocksize;
|
fs_block_size = blocksize;
|
||||||
|
super_start = SUPER_BLOCK_BYTES / fs_block_size;
|
||||||
|
super_end = (SUPER_BLOCK_BYTES + _MIN_BLOCK_SIZE - 1) / fs_block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <minix/vfsif.h>
|
#include <minix/vfsif.h>
|
||||||
#include <minix/bdev.h>
|
#include <minix/bdev.h>
|
||||||
|
|
||||||
|
PRIVATE int cleanmount = 1;
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* fs_readsuper *
|
* fs_readsuper *
|
||||||
|
@ -58,6 +59,25 @@ PUBLIC int fs_readsuper()
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remember whether we were mounted cleanly so we know what to
|
||||||
|
* do at unmount time
|
||||||
|
*/
|
||||||
|
if(superblock.s_flags & MFSFLAG_CLEAN)
|
||||||
|
cleanmount = 1;
|
||||||
|
|
||||||
|
/* clean check: if rw and not clean, switch to readonly */
|
||||||
|
if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) {
|
||||||
|
if(bdev_close(fs_dev) != OK)
|
||||||
|
panic("couldn't bdev_close after found unclean FS");
|
||||||
|
readonly = 1;
|
||||||
|
|
||||||
|
if (bdev_open(fs_dev, R_BIT) != OK) {
|
||||||
|
panic("couldn't bdev_open after found unclean FS");
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
printf("MFS: WARNING: FS 0x%x unclean, mounting readonly\n", fs_dev);
|
||||||
|
}
|
||||||
|
|
||||||
set_blocksize(&superblock);
|
set_blocksize(&superblock);
|
||||||
|
|
||||||
/* Get the root inode of the mounted file system. */
|
/* Get the root inode of the mounted file system. */
|
||||||
|
@ -88,6 +108,13 @@ PUBLIC int fs_readsuper()
|
||||||
|
|
||||||
fs_m_out.RES_CONREQS = 1; /* We can handle only 1 request at a time */
|
fs_m_out.RES_CONREQS = 1; /* We can handle only 1 request at a time */
|
||||||
|
|
||||||
|
/* Mark it dirty */
|
||||||
|
if(!superblock.s_rd_only) {
|
||||||
|
superblock.s_flags &= ~MFSFLAG_CLEAN;
|
||||||
|
if(write_super(&superblock) != OK)
|
||||||
|
panic("mounting: couldn't write dirty superblock");
|
||||||
|
}
|
||||||
|
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +178,12 @@ PUBLIC int fs_unmount()
|
||||||
/* force any cached blocks out of memory */
|
/* force any cached blocks out of memory */
|
||||||
(void) fs_sync();
|
(void) fs_sync();
|
||||||
|
|
||||||
|
/* Mark it clean if we're allowed to write _and_ it was clean originally. */
|
||||||
|
if(cleanmount && !superblock.s_rd_only) {
|
||||||
|
superblock.s_flags |= MFSFLAG_CLEAN;
|
||||||
|
write_super(&superblock);
|
||||||
|
}
|
||||||
|
|
||||||
/* Close the device the file system lives on. */
|
/* Close the device the file system lives on. */
|
||||||
bdev_close(fs_dev);
|
bdev_close(fs_dev);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ _PROTOTYPE( void put_block, (struct buf *bp, int block_type) );
|
||||||
_PROTOTYPE( void set_blocksize, (struct super_block *) );
|
_PROTOTYPE( void set_blocksize, (struct super_block *) );
|
||||||
_PROTOTYPE( void rw_scattered, (dev_t dev,
|
_PROTOTYPE( void rw_scattered, (dev_t dev,
|
||||||
struct buf **bufq, int bufqsize, int rw_flag) );
|
struct buf **bufq, int bufqsize, int rw_flag) );
|
||||||
|
_PROTOTYPE( int block_write_ok, (struct buf *bp) );
|
||||||
|
|
||||||
/* inode.c */
|
/* inode.c */
|
||||||
_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) );
|
_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) );
|
||||||
|
@ -93,6 +94,7 @@ _PROTOTYPE( void free_bit, (struct super_block *sp, int map,
|
||||||
_PROTOTYPE( unsigned int get_block_size, (dev_t dev) );
|
_PROTOTYPE( unsigned int get_block_size, (dev_t dev) );
|
||||||
_PROTOTYPE( struct super_block *get_super, (dev_t dev) );
|
_PROTOTYPE( struct super_block *get_super, (dev_t dev) );
|
||||||
_PROTOTYPE( int read_super, (struct super_block *sp) );
|
_PROTOTYPE( int read_super, (struct super_block *sp) );
|
||||||
|
_PROTOTYPE( int write_super, (struct super_block *sp) );
|
||||||
|
|
||||||
/* stats.c */
|
/* stats.c */
|
||||||
_PROTOTYPE( bit_t count_free_bits, (struct super_block *sp, int map));
|
_PROTOTYPE( bit_t count_free_bits, (struct super_block *sp, int map));
|
||||||
|
|
|
@ -282,6 +282,10 @@ int *completed; /* number of bytes copied */
|
||||||
/* Copy a chunk from the block buffer to user space. */
|
/* Copy a chunk from the block buffer to user space. */
|
||||||
r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off,
|
r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off,
|
||||||
(vir_bytes) (bp->b_data+off), (size_t) chunk, D);
|
(vir_bytes) (bp->b_data+off), (size_t) chunk, D);
|
||||||
|
} else if(!block_write_ok(bp)) {
|
||||||
|
/* Let cache layer veto writing to this block */
|
||||||
|
printf("MFS: block write not allowed\n");
|
||||||
|
r = EPERM;
|
||||||
} else {
|
} else {
|
||||||
/* Copy a chunk from user space to the block buffer. */
|
/* Copy a chunk from user space to the block buffer. */
|
||||||
r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off,
|
r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off,
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <minix/u64.h>
|
#include <minix/u64.h>
|
||||||
#include <minix/bdev.h>
|
#include <minix/bdev.h>
|
||||||
|
@ -157,7 +158,7 @@ PUBLIC struct super_block *get_super(
|
||||||
panic("request for super_block of NO_DEV");
|
panic("request for super_block of NO_DEV");
|
||||||
|
|
||||||
if(superblock.s_dev != dev)
|
if(superblock.s_dev != dev)
|
||||||
panic("wrong superblock: %d", (int) dev);
|
panic("wrong superblock: 0x%x", (int) dev);
|
||||||
|
|
||||||
return(&superblock);
|
return(&superblock);
|
||||||
}
|
}
|
||||||
|
@ -177,31 +178,62 @@ PUBLIC unsigned int get_block_size(dev_t dev)
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* read_super *
|
* rw_super *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int read_super(sp)
|
PRIVATE int rw_super(struct super_block *sp, int writing)
|
||||||
register struct super_block *sp; /* pointer to a superblock */
|
|
||||||
{
|
{
|
||||||
/* Read a superblock. */
|
/* Read/write a superblock. */
|
||||||
dev_t dev;
|
int r;
|
||||||
unsigned int magic;
|
|
||||||
int version, native, r;
|
|
||||||
static char *sbbuf;
|
static char *sbbuf;
|
||||||
block_t offset;
|
dev_t save_dev = sp->s_dev;
|
||||||
|
|
||||||
|
/* To keep the 1kb on disk clean, only read/write up to and including
|
||||||
|
* this field.
|
||||||
|
*/
|
||||||
|
#define LAST_ONDISK_FIELD s_disk_version
|
||||||
|
int ondisk_bytes = (int) ((char *) &sp->LAST_ONDISK_FIELD - (char *) sp)
|
||||||
|
+ sizeof(sp->LAST_ONDISK_FIELD);
|
||||||
|
|
||||||
STATICINIT(sbbuf, _MIN_BLOCK_SIZE);
|
STATICINIT(sbbuf, _MIN_BLOCK_SIZE);
|
||||||
|
|
||||||
dev = sp->s_dev; /* save device (will be overwritten by copy) */
|
assert(ondisk_bytes > 0);
|
||||||
if (dev == NO_DEV)
|
assert(ondisk_bytes < _MIN_BLOCK_SIZE);
|
||||||
|
assert(ondisk_bytes < sizeof(struct super_block));
|
||||||
|
|
||||||
|
if (sp->s_dev == NO_DEV)
|
||||||
panic("request for super_block of NO_DEV");
|
panic("request for super_block of NO_DEV");
|
||||||
|
|
||||||
r = bdev_read(dev, cvu64(SUPER_BLOCK_BYTES), sbbuf, _MIN_BLOCK_SIZE,
|
if(writing) {
|
||||||
|
memset(sbbuf, 0, _MIN_BLOCK_SIZE);
|
||||||
|
memcpy(sbbuf, sp, ondisk_bytes);
|
||||||
|
r = bdev_write(sp->s_dev, cvu64(SUPER_BLOCK_BYTES), sbbuf, _MIN_BLOCK_SIZE,
|
||||||
BDEV_NOFLAGS);
|
BDEV_NOFLAGS);
|
||||||
|
} else {
|
||||||
|
r = bdev_read(sp->s_dev, cvu64(SUPER_BLOCK_BYTES), sbbuf, _MIN_BLOCK_SIZE,
|
||||||
|
BDEV_NOFLAGS);
|
||||||
|
memset(sp, 0, sizeof(*sp));
|
||||||
|
memcpy(sp, sbbuf, ondisk_bytes);
|
||||||
|
sp->s_dev = save_dev;
|
||||||
|
}
|
||||||
|
|
||||||
if (r != _MIN_BLOCK_SIZE)
|
if (r != _MIN_BLOCK_SIZE)
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
|
||||||
memcpy(sp, sbbuf, sizeof(*sp));
|
return OK;
|
||||||
sp->s_dev = NO_DEV; /* restore later */
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* read_super *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int read_super(struct super_block *sp)
|
||||||
|
{
|
||||||
|
unsigned int magic;
|
||||||
|
block_t offset;
|
||||||
|
int version, native, r;
|
||||||
|
|
||||||
|
if((r=rw_super(sp, 0)) != OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
magic = sp->s_magic; /* determines file system type */
|
magic = sp->s_magic; /* determines file system type */
|
||||||
|
|
||||||
/* Get file system version and type. */
|
/* Get file system version and type. */
|
||||||
|
@ -306,7 +338,27 @@ register struct super_block *sp; /* pointer to a superblock */
|
||||||
"or invalid first data zone, or zone size too large\n");
|
"or invalid first data zone, or zone size too large\n");
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
}
|
}
|
||||||
sp->s_dev = dev; /* restore device number */
|
|
||||||
|
|
||||||
|
/* Check any flags we don't understand but are required to. Currently
|
||||||
|
* these don't exist so all such unknown bits are fatal.
|
||||||
|
*/
|
||||||
|
if(sp->s_flags & MFSFLAG_MANDATORY_MASK) {
|
||||||
|
printf("MFS: unsupported feature flags on this FS.\n"
|
||||||
|
"Please use a newer MFS to mount it.\n");
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* write_super *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int write_super(struct super_block *sp)
|
||||||
|
{
|
||||||
|
if(sp->s_rd_only)
|
||||||
|
panic("can't write superblock of readonly filesystem");
|
||||||
|
return rw_super(sp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ EXTERN struct super_block {
|
||||||
short s_zmap_blocks; /* # of blocks used by zone bit map */
|
short s_zmap_blocks; /* # of blocks used by zone bit map */
|
||||||
zone1_t s_firstdatazone_old; /* number of first data zone (small) */
|
zone1_t s_firstdatazone_old; /* number of first data zone (small) */
|
||||||
short s_log_zone_size; /* log2 of blocks/zone */
|
short s_log_zone_size; /* log2 of blocks/zone */
|
||||||
short s_pad; /* try to avoid compiler-dependent padding */
|
unsigned short s_flags; /* FS state flags */
|
||||||
off_t s_max_size; /* maximum file size on this device */
|
off_t s_max_size; /* maximum file size on this device */
|
||||||
zone_t s_zones; /* number of zones (replaces s_nzones in V2) */
|
zone_t s_zones; /* number of zones (replaces s_nzones in V2) */
|
||||||
short s_magic; /* magic number to recognize super-blocks */
|
short s_magic; /* magic number to recognize super-blocks */
|
||||||
|
@ -43,7 +43,11 @@ EXTERN struct super_block {
|
||||||
unsigned short s_block_size; /* block size in bytes. */
|
unsigned short s_block_size; /* block size in bytes. */
|
||||||
char s_disk_version; /* filesystem format sub-version */
|
char s_disk_version; /* filesystem format sub-version */
|
||||||
|
|
||||||
/* The following items are only used when the super_block is in memory. */
|
/* The following items are only used when the super_block is in memory.
|
||||||
|
* If this ever changes, i.e. more fields after s_disk_version has to go to
|
||||||
|
* disk, update LAST_ONDISK_FIELD in super.c as that controls which part of the
|
||||||
|
* struct is copied to and from disk.
|
||||||
|
*/
|
||||||
|
|
||||||
/*struct inode *s_isup;*/ /* inode for root dir of mounted file sys */
|
/*struct inode *s_isup;*/ /* inode for root dir of mounted file sys */
|
||||||
/*struct inode *s_imount;*/ /* inode mounted on */
|
/*struct inode *s_imount;*/ /* inode mounted on */
|
||||||
|
@ -63,5 +67,17 @@ EXTERN struct super_block {
|
||||||
#define IMAP 0 /* operating on the inode bit map */
|
#define IMAP 0 /* operating on the inode bit map */
|
||||||
#define ZMAP 1 /* operating on the zone bit map */
|
#define ZMAP 1 /* operating on the zone bit map */
|
||||||
|
|
||||||
|
/* s_flags contents; undefined flags are guaranteed to be zero on disk
|
||||||
|
* (not counting future versions of mfs setting them!)
|
||||||
|
*/
|
||||||
|
#define MFSFLAG_CLEAN (1L << 0) /* 0: dirty; 1: FS was unmounted cleanly */
|
||||||
|
|
||||||
|
/* Future compatability (or at least, graceful failure):
|
||||||
|
* if any of these bits are on, and the MFS or fsck
|
||||||
|
* implementation doesn't understand them, do not mount/fsck
|
||||||
|
* the FS.
|
||||||
|
*/
|
||||||
|
#define MFSFLAG_MANDATORY_MASK 0xff00
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue