static int sfs_sync(struct fs *fs) { struct sfs_fs *sfs; unsigned i, num; int result; vfs_biglock_acquire(); /* * Get the sfs_fs from the generic abstract fs. * * Note that the abstract struct fs, which is all the VFS * layer knows about, is actually a member of struct sfs_fs. * The pointer in the struct fs points back to the top of the * struct sfs_fs - essentially the same object. This can be a * little confusing at first. * * The following diagram may help: * * struct sfs_fs <-------------\ * : | * : sfs_absfs (struct fs) | <------\ * : : | | * : : various members | | * : : | | * : : fs_data ----------/ | * : : ...|... * : . VFS . * : . layer . * : other members ....... * : * : * * This construct is repeated with vnodes and devices and other * similar things all over the place in OS/161, so taking the * time to straighten it out in your mind is worthwhile. */ sfs = fs->fs_data; /* Go over the array of loaded vnodes, syncing as we go. */ num = vnodearray_num(sfs->sfs_vnodes); for (i=0; i<num; i++) { struct vnode *v = vnodearray_get(sfs->sfs_vnodes, i); VOP_FSYNC(v); } /* If the free block map needs to be written, write it. */ if (sfs->sfs_freemapdirty) { result = sfs_mapio(sfs, UIO_WRITE); if (result) { vfs_biglock_release(); return result; } sfs->sfs_freemapdirty = false; } /* If the superblock needs to be written, write it. */ if (sfs->sfs_superdirty) { result = sfs_wblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION); if (result) { vfs_biglock_release(); return result; } sfs->sfs_superdirty = false; } vfs_biglock_release(); return 0; }
static int sfs_domount(void *options, struct device *dev, struct fs **ret) { int result; struct sfs_fs *sfs; vfs_biglock_acquire(); /* We don't pass any options through mount */ (void)options; /* * Make sure our on-disk structures aren't messed up */ KASSERT(sizeof(struct sfs_super)==SFS_BLOCKSIZE); KASSERT(sizeof(struct sfs_inode)==SFS_BLOCKSIZE); KASSERT(SFS_BLOCKSIZE % sizeof(struct sfs_dir) == 0); /* * We can't mount on devices with the wrong sector size. * * (Note: for all intents and purposes here, "sector" and * "block" are interchangeable terms. Technically a filesystem * block may be composed of several hardware sectors, but we * don't do that in sfs.) */ if (dev->d_blocksize != SFS_BLOCKSIZE) { vfs_biglock_release(); return ENXIO; } /* Allocate object */ sfs = kmalloc(sizeof(struct sfs_fs)); if (sfs==NULL) { vfs_biglock_release(); return ENOMEM; } /* Allocate array */ sfs->sfs_vnodes = vnodearray_create(); if (sfs->sfs_vnodes == NULL) { kfree(sfs); vfs_biglock_release(); return ENOMEM; } /* Set the device so we can use sfs_rblock() */ sfs->sfs_device = dev; /* Load superblock */ result = sfs_rblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION); if (result) { vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return result; } /* Make some simple sanity checks */ if (sfs->sfs_super.sp_magic != SFS_MAGIC) { kprintf("sfs: Wrong magic number in superblock " "(0x%x, should be 0x%x)\n", sfs->sfs_super.sp_magic, SFS_MAGIC); vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return EINVAL; } if (sfs->sfs_super.sp_nblocks > dev->d_blocks) { kprintf("sfs: warning - fs has %u blocks, device has %u\n", sfs->sfs_super.sp_nblocks, dev->d_blocks); } /* Ensure null termination of the volume name */ sfs->sfs_super.sp_volname[sizeof(sfs->sfs_super.sp_volname)-1] = 0; /* Load free space bitmap */ sfs->sfs_freemap = bitmap_create(SFS_FS_BITMAPSIZE(sfs)); if (sfs->sfs_freemap == NULL) { vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return ENOMEM; } result = sfs_mapio(sfs, UIO_READ); if (result) { bitmap_destroy(sfs->sfs_freemap); vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return result; } /* Set up abstract fs calls */ sfs->sfs_absfs.fs_sync = sfs_sync; sfs->sfs_absfs.fs_getvolname = sfs_getvolname; sfs->sfs_absfs.fs_getroot = sfs_getroot; sfs->sfs_absfs.fs_unmount = sfs_unmount; sfs->sfs_absfs.fs_data = sfs; /* the other fields */ sfs->sfs_superdirty = false; sfs->sfs_freemapdirty = false; /* Hand back the abstract fs */ *ret = &sfs->sfs_absfs; vfs_biglock_release(); return 0; }
static int sfs_sync(struct fs *fs) { struct sfs_fs *sfs; int i, num, result; struct array *tmp; /* * Get the sfs_fs from the generic abstract fs. * * Note that the abstract struct fs, which is all the VFS * layer knows about, is actually a member of struct sfs_fs. * The pointer in the struct fs points back to the top of the * struct sfs_fs - essentially the same object. This can be a * little confusing at first. * * The following diagram may help: * * struct sfs_fs <-------------\ * : | * : sfs_absfs (struct fs) | <------\ * : : | | * : : various members | | * : : | | * : : fs_data ----------/ | * : : ...|... * : . VFS . * : . layer . * : other members ....... * : * : * * This construct is repeated with vnodes and devices and other * similar things all over the place in OS/161, so taking the * time to straighten it out in your mind is worthwhile. */ sfs = fs->fs_data; /* * This is kind of a hack. We can't acquire vnode locks while * holding sfs_vnlock, because that violates the ordering * constraints (see sfs_vnode.c) - so we *copy* the array of * loaded vnodes into a temporary array and sync those. */ tmp = array_create(); if (tmp == NULL) { return ENOMEM; } lock_acquire(sfs->sfs_vnlock); /* Go over the array of loaded vnodes. */ num = array_getnum(sfs->sfs_vnodes); for (i=0; i<num; i++) { struct sfs_vnode *sv = array_getguy(sfs->sfs_vnodes, i); VOP_INCREF(&sv->sv_v); if (array_add(tmp, sv) != 0) { // XXX panic("sfs_sync: array_add failed\n"); } } lock_release(sfs->sfs_vnlock); /* Now sync. */ num = array_getnum(tmp); for (i=0; i<num; i++) { struct sfs_vnode *sv = array_getguy(tmp, i); result = VOP_FSYNC(&sv->sv_v); if (result) { kprintf("SFS: Warning: syncing inode %d: %s\n", sv->sv_ino, strerror(result)); } VOP_DECREF(&sv->sv_v); } array_destroy(tmp); lock_acquire(sfs->sfs_bitlock); /* If the free block map needs to be written, write it. */ if (sfs->sfs_freemapdirty) { result = sfs_mapio(sfs, UIO_WRITE); if (result) { kprintf("SFS: Warning: syncing bitmap: %s\n", strerror(result)); } else { /* Only clear the dirty bit if we succeeded */ sfs->sfs_freemapdirty = 0; } } /* If the superblock needs to be written, write it. */ if (sfs->sfs_superdirty) { result = sfs_wblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION); if (result) { kprintf("SFS: Warning: syncing superblock: %s\n", strerror(result)); } else { /* Only clear the dirty bit if we succeeded */ sfs->sfs_superdirty = 0; } } lock_release(sfs->sfs_bitlock); return 0; }