rdtime(&t);
mnt->m_fs.s_time = t.low;
mnt->m_fs.s_timeh = t.high;
- mnt->m_fs.s_fmod = true;
+ mnt->m_fs.s_fmod = FMOD_DIRTY;
return &mnt->m_fs;
}
}
/* We must scan the inodes, and fill up the table */
- _sync(); /* Make on-disk inodes consistent */
+ sync(); /* Make on-disk inodes consistent */
k = 0;
for(blk = 2; blk < dev->s_isize; blk++) {
buf = bread(devno, blk, 0);
return true; // failure
}
+ if (fp->s_fmod == FMOD_DIRTY) {
+ kputs("warning: mounting dirty file system, forcing r/o.\n");
+ flags |= MS_RDONLY;
+ }
+ if (!(flags & MS_RDONLY))
+ /* Dirty - and will write dirty mark back to media */
+ fp->s_fmod = FMOD_DIRTY;
+ else /* Clean in memory, don't write it back to media */
+ fp->s_fmod = FMOD_CLEAN;
fp->s_mntpt = ino;
if(ino)
++ino->c_refs;
m->m_flags = flags;
/* Makes our entry findable */
m->m_dev = dev;
+
+ /* Mark the filesystem dirty on disk */
+ sync();
+
return false; // success
}
int16_t s_ninode;
uint16_t s_inode[FILESYS_TABSIZE];
uint8_t s_fmod;
+ /* 0 is 'legacy' and never written to disk */
+#define FMOD_GO_CLEAN 0 /* Write a clean to the disk (internal) */
+#define FMOD_DIRTY 1 /* Mounted or uncleanly unmounted from r/w */
+#define FMOD_CLEAN 2 /* Clean. Used internally to mean don't
+ update the super block */
uint8_t s_timeh; /* bits 32-40: FIXME - wire up */
uint32_t s_time;
blkno_t s_tfree;
#define A_FTRACE 18 /* Unimplemented:
Hook to the syscall trace debug */
-#define AD_NOSYNC 1 /* Unimplemented */
+#define AD_NOSYNC 1
/* Process table entry */
}
for (m = fs_tab; m < fs_tab + NMOUNTS; m++) {
if (m->m_dev != NO_DEVICE &&
- m->m_fs.s_fmod) {
- m->m_fs.s_fmod = 0;
+ m->m_fs.s_fmod != FMOD_CLEAN) {
+ /* GO_CLEAN means write a CLEAN to the media */
+ if (m->m_fs.s_fmod == FMOD_GO_CLEAN)
+ m->m_fs.s_fmod = FMOD_CLEAN;
/* FIXME: I/O error handling */
buf = bread(m->m_dev, 1, 1);
blkfromk(&m->m_fs, buf, 0, sizeof(struct filesys));
_umount (spec) Function 34
char *spec;
********************************************/
+
#define spec (char *)udata.u_argn
#define flags (uint16_t)udata.u_argn1
-arg_t _umount(void)
+static int do_umount(uint16_t dev)
{
- inoptr sino;
- uint16_t dev;
- inoptr ptr;
struct mount *mnt;
- uint8_t rm;
-
- if (esuper())
- return (-1);
-
- if (!(sino = n_open(spec, NULLINOPTR)))
- return (-1);
-
- if (getmode(sino) != MODE_R(F_BDEV)) {
- udata.u_error = ENOTBLK;
- goto nogood;
- }
-
- dev = (int) sino->c_node.i_addr[0];
- if (!validdev(dev)) {
- udata.u_error = ENXIO;
- goto nogood;
- }
-
- rm = flags & MS_REMOUNT;
+ uint8_t rm = flags & MS_REMOUNT;
+ inoptr ptr;
mnt = fs_tab_get(dev);
if (mnt == NULL) {
udata.u_error = EINVAL;
- goto nogood;
+ return -1;
}
+ /* If anything on this file system is open for write then you
+ can't remount it read only */
+ if (flags & (MS_RDONLY|MS_REMOUNT) == (MS_RDONLY|MS_REMOUNT)) {
+ for (ptr = i_tab ; ptr < i_tab + ITABSIZE; ++ptr) {
+ if (ptr->c_dev == dev && ptr->c_writers) {
+ udata.u_error = EBUSY;
+ return -1;
+ }
+ }
+ }
+
+ /* Sweep the inode table. If unmounting look for any references
+ and if so fail. If remounting update the CRDONLY flags */
for (ptr = i_tab; ptr < i_tab + ITABSIZE; ++ptr) {
if (ptr->c_refs > 0 && ptr->c_dev == dev) {
if (rm) {
ptr->c_flags |= CRDONLY;
} else {
udata.u_error = EBUSY;
- goto nogood;
+ return -1;
}
}
}
+ if (!rm)
+ mnt->m_fs.s_fmod = FMOD_GO_CLEAN;
+
sync();
- if (flags & MS_REMOUNT) {
+ if (rm) {
mnt->m_flags &= ~(MS_RDONLY|MS_NOSUID);
mnt->m_flags |= flags & (MS_RDONLY|MS_NOSUID);
+ /* You can choose to remount a corrupt fs r/o in which case
+ it gets marked clean. We may want to rethink that FIXME */
+ if (mnt->m_flags & MS_RDONLY)
+ mnt->m_fs.s_fmod = FMOD_GO_CLEAN;
return 0;
}
i_deref(mnt->m_fs.s_mntpt);
/* Vanish the entry */
mnt->m_dev = NO_DEVICE;
- i_deref(sino);
return 0;
+}
- nogood:
+arg_t _umount(void)
+{
+ inoptr sino;
+ uint16_t dev;
+ arg_t ret = -1;
+
+ if (esuper())
+ return -1;
+
+ if (!(sino = n_open(spec, NULLINOPTR)))
+ return -1;
+
+ if (getmode(sino) != MODE_R(F_BDEV)) {
+ udata.u_error = ENOTBLK;
+ goto nogood;
+ }
+
+ dev = (int) sino->c_node.i_addr[0];
+ if (!validdev(dev)) {
+ udata.u_error = ENXIO;
+ goto nogood;
+ }
+ ret = do_umount(dev);
+nogood:
i_deref(sino);
- return -1;
+ return ret;
}
#undef spec
{
if (esuper())
return -1;
- sync();
+ if (func != AD_NOSYNC)
+ sync();
/* Wants moving into machine specific files */
if (cmd == A_SHUTDOWN || cmd == A_DUMP)
trap_monitor();