STATIC int xfs_mntupdate( bhv_desc_t *bdp, int *flags, struct xfs_mount_args *args) { struct vfs *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); int pincount, error; int count = 0; if (args->flags & XFSMNT_NOATIME) mp->m_flags |= XFS_MOUNT_NOATIME; else mp->m_flags &= ~XFS_MOUNT_NOATIME; if (!(vfsp->vfs_flag & VFS_RDONLY)) { VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); } if (*flags & MS_RDONLY) { xfs_refcache_purge_mp(mp); xfs_flush_buftarg(mp->m_ddev_targp, 0); xfs_finish_reclaim_all(mp, 0); /* This loop must run at least twice. * The first instance of the loop will flush * most meta data but that will generate more * meta data (typically directory updates). * Which then must be flushed and logged before * we can write the unmount record. */ do { VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error); pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); if (!pincount) { delay(50); count++; } } while (count < 2); /* Ok now write out an unmount record */ xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); vfsp->vfs_flag |= VFS_RDONLY; } else { vfsp->vfs_flag &= ~VFS_RDONLY; } return 0; }
STATIC int syncd(void *arg) { vfs_t *vfsp = (vfs_t *) arg; int error; daemonize("xfs_syncd"); vfsp->vfs_sync_task = current; wmb(); wake_up(&vfsp->vfs_wait_sync_task); for (;;) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(xfs_syncd_interval); /* swsusp */ if (current->flags & PF_FREEZE) refrigerator(PF_IOTHREAD); if (vfsp->vfs_flag & VFS_UMOUNT) break; if (vfsp->vfs_flag & VFS_RDONLY) continue; VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error); } vfsp->vfs_sync_task = NULL; wmb(); wake_up(&vfsp->vfs_wait_sync_task); return 0; }
/* * Do a lazy sync of the filesystem. */ int sync_fsync(void *v) { struct vop_fsync_args *ap = v; struct vnode *syncvp = ap->a_vp; struct mount *mp = syncvp->v_mount; int asyncflag; /* * We only need to do something if this is a lazy evaluation. */ if (ap->a_waitfor != MNT_LAZY) return (0); /* * Move ourselves to the back of the sync list. */ vn_syncer_add_to_worklist(syncvp, syncdelay); /* * Walk the list of vnodes pushing all that are dirty and * not already on the sync list. */ if (vfs_busy(mp, VB_READ|VB_NOWAIT) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; VFS_SYNC(mp, MNT_LAZY, ap->a_cred, ap->a_p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; vfs_unbusy(mp); } return (0); }
static OSKIT_COMDECL filesystem_sync(oskit_filesystem_t *f, oskit_bool_t wait) { struct gfilesystem *fs = (struct gfilesystem *) f; struct mount *mp; struct proc *p; oskit_error_t ferror; int error, asyncflag; if (!fs || !fs->count || !fs->mp) return OSKIT_E_INVALIDARG; ferror = getproc(&p); if (ferror) return ferror; mp = fs->mp; error = 0; if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && !vfs_busy(mp)) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; error = VFS_SYNC(mp, wait ? MNT_WAIT : MNT_NOWAIT, p->p_ucred, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; vfs_unbusy(mp); } prfree(p); if (error) return errno_to_oskit_error(error); return 0; }
STATIC void linvfs_write_super( struct super_block *sb) { vfs_t *vfsp = LINVFS_GET_VFS(sb); int error; if (sb->s_flags & MS_RDONLY) { sb->s_dirt = 0; /* paranoia */ return; } /* Push the log and superblock a little */ VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error); sb->s_dirt = 0; }
STATIC int linvfs_sync_super( struct super_block *sb, int wait) { vfs_t *vfsp = LINVFS_GET_VFS(sb); int error; int flags = SYNC_FSDATA; if (wait) flags |= SYNC_WAIT; VFS_SYNC(vfsp, flags, NULL, error); sb->s_dirt = 0; return -error; }
int do_umount(vfs_t *vfs, boolean_t force) { VFS_SYNC(vfs, 0, kcred); int ret = VFS_UNMOUNT(vfs, force ? MS_FORCE : 0, kcred); if(ret != 0) return ret; ASSERT(force || vfs->vfs_count == 1); VFS_RELE(vfs); #ifdef DEBUG fprintf(stderr, "mounted filesystems: %i\n", atomic_dec_32_nv(&mounted)); #endif return 0; }
STATIC void linvfs_put_super( struct super_block *sb) { vfs_t *vfsp = LINVFS_GET_VFS(sb); int error; linvfs_stop_syncd(vfsp); VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); if (!error) VFS_UNMOUNT(vfsp, 0, NULL, error); if (error) { printk("XFS unmount got error %d\n", error); printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp); return; } vfs_deallocate(vfsp); }
void vnlayer_write_super(struct super_block *super_p) { CRED_T *cred; int err; ASSERT_SB_LOCKED(super_p); cred = MDKI_GET_UCRED(); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, cred); MDKI_CRFREE(cred); /* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; }
void vnlayer_write_super(struct super_block *super_p) { CALL_DATA_T cd; int err; ASSERT_SB_LOCKED(super_p); mdki_linux_init_call_data(&cd); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd); mdki_linux_destroy_call_data(&cd); /* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; }
/* * Do a lazy sync of the filesystem. * * sync_fsync { struct vnode *a_vp, int a_waitfor } */ static int sync_fsync(struct vop_fsync_args *ap) { struct vnode *syncvp = ap->a_vp; struct mount *mp = syncvp->v_mount; int asyncflag; /* * We only need to do something if this is a lazy evaluation. */ if ((ap->a_waitfor & MNT_LAZY) == 0) return (0); /* * Move ourselves to the back of the sync list. */ vn_syncer_add(syncvp, syncdelay); /* * Walk the list of vnodes pushing all that are dirty and * not already on the sync list, and freeing vnodes which have * no refs and whos VM objects are empty. vfs_msync() handles * the VM issues and must be called whether the mount is readonly * or not. */ if (vfs_busy(mp, LK_NOWAIT) != 0) return (0); if (mp->mnt_flag & MNT_RDONLY) { vfs_msync(mp, MNT_NOWAIT); } else { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; /* ZZZ hack */ vfs_msync(mp, MNT_NOWAIT); VFS_SYNC(mp, MNT_NOWAIT | MNT_LAZY); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; } vfs_unbusy(mp); return (0); }
/* They rewrote sync_supers so that it won't proceed through their loop * until the dirty bit is cleared. */ super_p->s_dirt = 0; if (err != 0) VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); return /* mdki_errno_unix_to_linux(err) */; } #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */ int vnlayer_sync_super( struct super_block *super_p, int wait ) { CALL_DATA_T cd; int err; /* if wait is not allowed, do nothing */ if (wait == 0) { return 0; } ASSERT_SB_LOCKED(super_p); mdki_linux_init_call_data(&cd); err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd); mdki_linux_destroy_call_data(&cd); if (err != 0) { VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n", __func__, err); } return mdki_errno_unix_to_linux(err); }
/* * ffs_mount * * Called when mounting local physical media * * PARAMETERS: * mountroot * mp mount point structure * path NULL (flag for root mount!!!) * data <unused> * p process (user credentials check [statfs]) * * mount * mp mount point structure * path path to mount point * data pointer to argument struct in user space * p process (user credentials check) * * RETURNS: 0 Success * !0 error number (errno.h) * * LOCK STATE: * * ENTRY * mount point is locked * EXIT * mount point is locked * * NOTES: * A NULL path can be used for a flag since the mount * system call will fail with EFAULT in copyinstr in * nlookup() if it is a genuine NULL from the user. */ static int ffs_mount(struct mount *mp, /* mount struct pointer */ char *path, /* path to mount point */ caddr_t data, /* arguments to FS specific mount */ struct ucred *cred) /* process requesting mount */ { size_t size; int error; struct vnode *devvp; struct ufs_args args; struct ufsmount *ump = NULL; struct fs *fs; int flags, ronly = 0; mode_t accessmode; struct nlookupdata nd; struct vnode *rootvp; devvp = NULL; error = 0; /* * Use NULL path to flag a root mount */ if (path == NULL) { /* *** * Mounting root filesystem *** */ if ((error = bdevvp(rootdev, &rootvp))) { kprintf("ffs_mountroot: can't find rootvp\n"); return (error); } if( ( error = ffs_mountfs(rootvp, mp, M_FFSNODE)) != 0) { /* fs specific cleanup (if any)*/ goto error_1; } devvp = rootvp; goto dostatfs; /* success*/ } /* *** * Mounting non-root filesystem or updating a filesystem *** */ /* copy in user arguments*/ error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); if (error) goto error_1; /* can't get arguments*/ /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOUFS(mp); fs = ump->um_fs; devvp = ump->um_devvp; error = 0; ronly = fs->fs_ronly; /* MNT_RELOAD might change this */ if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { /* * Flush any dirty data. */ VFS_SYNC(mp, MNT_WAIT); /* * Check for and optionally get rid of files open * for writing. */ flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; if (mp->mnt_flag & MNT_SOFTDEP) { error = softdep_flushfiles(mp, flags); } else { error = ffs_flushfiles(mp, flags); } ronly = 1; } if (!error && (mp->mnt_flag & MNT_RELOAD)) { error = ffs_reload(mp, NULL); } if (error) { goto error_1; } if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ if (cred->cr_uid != 0) { vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_EACCESS(devvp, VREAD | VWRITE, cred)) != 0) { vn_unlock(devvp); return (error); } vn_unlock(devvp); } fs->fs_flags &= ~FS_UNCLEAN; if (fs->fs_clean == 0) { fs->fs_flags |= FS_UNCLEAN; if (mp->mnt_flag & MNT_FORCE) { kprintf( "WARNING: %s was not properly dismounted\n", fs->fs_fsmnt); } else { kprintf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->fs_fsmnt); error = EPERM; goto error_1; } } /* check to see if we need to start softdep */ if (fs->fs_flags & FS_DOSOFTDEP) { error = softdep_mount(devvp, mp, fs); if (error) goto error_1; } ronly = 0; } /* * Soft updates is incompatible with "async", * so if we are doing softupdates stop the user * from setting the async flag in an update. * Softdep_mount() clears it in an initial mount * or ro->rw remount. */ if (mp->mnt_flag & MNT_SOFTDEP) { mp->mnt_flag &= ~MNT_ASYNC; } /* if not updating name...*/ if (args.fspec == 0) { /* * Process export requests. Jumping to "success" * will return the vfs_export() error code. */ error = vfs_export(mp, &ump->um_export, &args.export); goto success; }
/* * mp - path - addr in user space of mount point (ie /usr or whatever) * data - addr in user space of mount params including the name of the block * special file to treat as a filesystem. */ int msdosfs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; /* vnode for blk device to mount */ struct msdosfs_args args; /* will hold data from mount request */ /* msdosfs specific mount control block */ struct msdosfsmount *pmp = NULL; char fname[MNAMELEN]; char fspec[MNAMELEN]; int error, flags; mode_t accessmode; error = copyin(data, &args, sizeof(struct msdosfs_args)); if (error) return (error); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { pmp = VFSTOMSDOSFS(mp); error = 0; if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) { mp->mnt_flag &= ~MNT_RDONLY; VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p); mp->mnt_flag |= MNT_RDONLY; flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = vflush(mp, NULLVP, flags); if (!error) pmp->pm_flags |= MSDOSFSMNT_RONLY; } if (!error && (mp->mnt_flag & MNT_RELOAD)) /* not yet implemented */ error = EOPNOTSUPP; if (error) return (error); if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_WANTRDWR)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ if (suser(p, 0) != 0) { devvp = pmp->pm_devvp; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, VREAD | VWRITE, p->p_ucred); VOP_UNLOCK(devvp, 0); if (error) return (error); } pmp->pm_flags &= ~MSDOSFSMNT_RONLY; } if (args.fspec == NULL) { #ifdef __notyet__ /* doesn't work correctly with current mountd XXX */ if (args.flags & MSDOSFSMNT_MNTOPT) { pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT; pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT; if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; } #endif /* * Process export requests. */ return (vfs_export(mp, &pmp->pm_export, &args.export_info)); } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL); if (error) goto error; if (disk_map(fspec, fname, sizeof(fname), DM_OPENBLCK) == -1) bcopy(fspec, fname, sizeof(fname)); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p); if ((error = namei(ndp)) != 0) goto error; devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { error = ENOTBLK; goto error_devvp; } if (major(devvp->v_rdev) >= nblkdev) { error = ENXIO; goto error_devvp; } /* * If mount by non-root, then verify that user has necessary * permissions on the device. */ if (suser(p, 0) != 0) { accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, accessmode, p->p_ucred); VOP_UNLOCK(devvp, 0); if (error) goto error_devvp; } if ((mp->mnt_flag & MNT_UPDATE) == 0) error = msdosfs_mountfs(devvp, mp, p, &args); else { if (devvp != pmp->pm_devvp) error = EINVAL; /* XXX needs translation */ else vrele(devvp); } if (error) goto error_devvp; pmp = VFSTOMSDOSFS(mp); pmp->pm_gid = args.gid; pmp->pm_uid = args.uid; pmp->pm_mask = args.mask; pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT; if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; else if (!(pmp->pm_flags & (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) { struct vnode *rvp; /* * Try to divine whether to support Win'95 long filenames */ if (FAT32(pmp)) pmp->pm_flags |= MSDOSFSMNT_LONGNAME; else { if ((error = msdosfs_root(mp, &rvp)) != 0) { msdosfs_unmount(mp, MNT_FORCE, p); goto error; } pmp->pm_flags |= findwin95(VTODE(rvp)) ? MSDOSFSMNT_LONGNAME : MSDOSFSMNT_SHORTNAME; vput(rvp); } } bzero(mp->mnt_stat.f_mntonname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN); strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); bcopy(&args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(args)); #ifdef MSDOSFS_DEBUG printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap); #endif return (0); error_devvp: vrele(devvp); error: return (error); }
/* * mp - path - addr in user space of mount point (ie /usr or whatever) * data - addr in user space of mount params including the name of the block * special file to treat as a filesystem. */ static int msdosfs_mount(struct mount *mp) { struct vnode *devvp; /* vnode for blk device to mount */ struct thread *td; /* msdosfs specific mount control block */ struct msdosfsmount *pmp = NULL; struct nameidata ndp; int error, flags; accmode_t accmode; char *from; td = curthread; if (vfs_filteropt(mp->mnt_optnew, msdosfs_opts)) return (EINVAL); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { pmp = VFSTOMSDOSFS(mp); if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) { /* * Forbid export requests if filesystem has * MSDOSFS_LARGEFS flag set. */ if ((pmp->pm_flags & MSDOSFS_LARGEFS) != 0) { vfs_mount_error(mp, "MSDOSFS_LARGEFS flag set, cannot export"); return (EOPNOTSUPP); } } if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { error = VFS_SYNC(mp, MNT_WAIT); if (error) return (error); flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = vflush(mp, 0, flags, td); if (error) return (error); /* * Now the volume is clean. Mark it so while the * device is still rw. */ error = markvoldirty(pmp, 0); if (error) { (void)markvoldirty(pmp, 1); return (error); } /* Downgrade the device from rw to ro. */ DROP_GIANT(); g_topology_lock(); error = g_access(pmp->pm_cp, 0, -1, 0); g_topology_unlock(); PICKUP_GIANT(); if (error) { (void)markvoldirty(pmp, 1); return (error); } /* * Backing out after an error was painful in the * above. Now we are committed to succeeding. */ pmp->pm_fmod = 0; pmp->pm_flags |= MSDOSFSMNT_RONLY; MNT_ILOCK(mp); mp->mnt_flag |= MNT_RDONLY; MNT_IUNLOCK(mp); } else if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && !vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ devvp = pmp->pm_devvp; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_ACCESS(devvp, VREAD | VWRITE, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { VOP_UNLOCK(devvp, 0); return (error); } VOP_UNLOCK(devvp, 0); DROP_GIANT(); g_topology_lock(); error = g_access(pmp->pm_cp, 0, 1, 0); g_topology_unlock(); PICKUP_GIANT(); if (error) return (error); pmp->pm_fmod = 1; pmp->pm_flags &= ~MSDOSFSMNT_RONLY; MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_RDONLY; MNT_IUNLOCK(mp); /* Now that the volume is modifiable, mark it dirty. */ error = markvoldirty(pmp, 1); if (error) return (error); } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible disk device. */ if (vfs_getopt(mp->mnt_optnew, "from", (void **)&from, NULL)) return (EINVAL); NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); error = namei(&ndp); if (error) return (error); devvp = ndp.ni_vp; NDFREE(&ndp, NDF_ONLY_PNBUF); if (!vn_isdisk(devvp, &error)) { vput(devvp); return (error); } /* * If mount by non-root, then verify that user has necessary * permissions on the device. */ accmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accmode |= VWRITE; error = VOP_ACCESS(devvp, accmode, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = mountmsdosfs(devvp, mp); #ifdef MSDOSFS_DEBUG /* only needed for the printf below */ pmp = VFSTOMSDOSFS(mp); #endif } else { vput(devvp); if (devvp != pmp->pm_devvp) return (EINVAL); /* XXX needs translation */ } if (error) { vrele(devvp); return (error); } error = update_mp(mp, td); if (error) { if ((mp->mnt_flag & MNT_UPDATE) == 0) msdosfs_unmount(mp, MNT_FORCE); return error; } if (devvp->v_type == VCHR && devvp->v_rdev != NULL) devvp->v_rdev->si_mountpt = mp; vfs_mountedfrom(mp, from); #ifdef MSDOSFS_DEBUG printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap); #endif return (0); }
/* * VFS Operations. * * mount system call */ int ffs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; struct ufs_args args; struct ufsmount *ump = NULL; struct fs *fs; int error = 0, flags; int ronly; mode_t accessmode; size_t size; error = copyin(data, &args, sizeof (struct ufs_args)); if (error) return (error); #ifndef FFS_SOFTUPDATES if (mp->mnt_flag & MNT_SOFTDEP) { printf("WARNING: soft updates isn't compiled in\n"); mp->mnt_flag &= ~MNT_SOFTDEP; } #endif /* * Soft updates is incompatible with "async", * so if we are doing softupdates stop the user * from setting the async flag. */ if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) == (MNT_SOFTDEP | MNT_ASYNC)) { return (EINVAL); } /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOUFS(mp); fs = ump->um_fs; devvp = ump->um_devvp; error = 0; ronly = fs->fs_ronly; if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { /* Flush any dirty data */ mp->mnt_flag &= ~MNT_RDONLY; VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p); mp->mnt_flag |= MNT_RDONLY; /* * Get rid of files open for writing. */ flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; if (fs->fs_flags & FS_DOSOFTDEP) { error = softdep_flushfiles(mp, flags, p); mp->mnt_flag &= ~MNT_SOFTDEP; } else error = ffs_flushfiles(mp, flags, p); ronly = 1; } /* * Flush soft dependencies if disabling it via an update * mount. This may leave some items to be processed, * so don't do this yet XXX. */ if ((fs->fs_flags & FS_DOSOFTDEP) && !(mp->mnt_flag & MNT_SOFTDEP) && !(mp->mnt_flag & MNT_RDONLY) && fs->fs_ronly == 0) { #if 0 flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = softdep_flushfiles(mp, flags, p); #elif FFS_SOFTUPDATES mp->mnt_flag |= MNT_SOFTDEP; #endif } /* * When upgrading to a softdep mount, we must first flush * all vnodes. (not done yet -- see above) */ if (!(fs->fs_flags & FS_DOSOFTDEP) && (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) { #if 0 flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ffs_flushfiles(mp, flags, p); #else mp->mnt_flag &= ~MNT_SOFTDEP; #endif } if (!error && (mp->mnt_flag & MNT_RELOAD)) error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); if (error) goto error_1; if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ if (suser(p, 0)) { vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, VREAD | VWRITE, p->p_ucred, p); VOP_UNLOCK(devvp, 0, p); if (error) goto error_1; } if (fs->fs_clean == 0) { #if 0 /* * It is safe mount unclean file system * if it was previously mounted with softdep * but we may loss space and must * sometimes run fsck manually. */ if (fs->fs_flags & FS_DOSOFTDEP) printf( "WARNING: %s was not properly unmounted\n", fs->fs_fsmnt); else #endif if (mp->mnt_flag & MNT_FORCE) { printf( "WARNING: %s was not properly unmounted\n", fs->fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->fs_fsmnt); error = EROFS; goto error_1; } } if ((fs->fs_flags & FS_DOSOFTDEP)) { error = softdep_mount(devvp, mp, fs, p->p_ucred); if (error) goto error_1; } fs->fs_contigdirs=(u_int8_t*)malloc((u_long)fs->fs_ncg, M_UFSMNT, M_WAITOK); bzero(fs->fs_contigdirs, fs->fs_ncg); ronly = 0; } if (args.fspec == 0) { /* * Process export requests. */ error = vfs_export(mp, &ump->um_export, &args.export_info); if (error) goto error_1; else goto success; } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); if ((error = namei(ndp)) != 0) goto error_1; devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { error = ENOTBLK; goto error_2; } if (major(devvp->v_rdev) >= nblkdev) { error = ENXIO; goto error_2; } /* * If mount by non-root, then verify that user has necessary * permissions on the device. */ if (suser(p, 0)) { accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); VOP_UNLOCK(devvp, 0, p); if (error) goto error_2; } if (mp->mnt_flag & MNT_UPDATE) { /* * UPDATE * If it's not the same vnode, or at least the same device * then it's not correct. */ if (devvp != ump->um_devvp) { if (devvp->v_rdev == ump->um_devvp->v_rdev) { vrele(devvp); } else { error = EINVAL; /* needs translation */ } } else vrele(devvp); /* * Update device name only on success */ if (!error) { /* * Save "mounted from" info for mount point (NULL pad) */ copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); } } else { /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an * error occurs, the mountpoint is discarded by the * upper level code. */ /* Save "last mounted on" info for mount point (NULL pad)*/ copyinstr(path, /* mount point*/ mp->mnt_stat.f_mntonname, /* save area*/ MNAMELEN - 1, /* max size*/ &size); /* real size*/ bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr(args.fspec, /* device name*/ mp->mnt_stat.f_mntfromname, /* save area*/ MNAMELEN - 1, /* max size*/ &size); /* real size*/ bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); error = ffs_mountfs(devvp, mp, p); } if (error) goto error_2; /* * Initialize FS stat information in mount struct; uses both * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname * * This code is common to root and non-root mounts */ bcopy(&args, &mp->mnt_stat.mount_info.ufs_args, sizeof(args)); (void)VFS_STATFS(mp, &mp->mnt_stat, p); success: if (path && (mp->mnt_flag & MNT_UPDATE)) { /* Update clean flag after changing read-onlyness. */ fs = ump->um_fs; if (ronly != fs->fs_ronly) { fs->fs_ronly = ronly; fs->fs_clean = ronly && (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0; if (ronly) free(fs->fs_contigdirs, M_UFSMNT); } if (!ronly) { if (mp->mnt_flag & MNT_SOFTDEP) fs->fs_flags |= FS_DOSOFTDEP; else fs->fs_flags &= ~FS_DOSOFTDEP; } ffs_sbupdate(ump, MNT_WAIT); } return (0); error_2: /* error with devvp held */ vrele (devvp); error_1: /* no state to back out */ return (error); }
/* * VFS Operations. * * mount system call */ static int ext2_mount(struct mount *mp) { struct vfsoptlist *opts; struct vnode *devvp; struct thread *td; struct ext2mount *ump = NULL; struct m_ext2fs *fs; struct nameidata nd, *ndp = &nd; accmode_t accmode; char *path, *fspec; int error, flags, len; td = curthread; opts = mp->mnt_optnew; if (vfs_filteropt(opts, ext2_opts)) return (EINVAL); vfs_getopt(opts, "fspath", (void **)&path, NULL); /* Double-check the length of path.. */ if (strlen(path) >= MAXMNTLEN - 1) return (ENAMETOOLONG); fspec = NULL; error = vfs_getopt(opts, "from", (void **)&fspec, &len); if (!error && fspec[len - 1] != '\0') return (EINVAL); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOEXT2(mp); fs = ump->um_e2fs; error = 0; if (fs->e2fs_ronly == 0 && vfs_flagopt(opts, "ro", NULL, 0)) { error = VFS_SYNC(mp, MNT_WAIT); if (error) return (error); flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ext2_flushfiles(mp, flags, td); if ( error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) { fs->e2fs->e2fs_state |= E2FS_ISCLEAN; ext2_sbupdate(ump, MNT_WAIT); } fs->e2fs_ronly = 1; vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY); DROP_GIANT(); g_topology_lock(); g_access(ump->um_cp, 0, -1, 0); g_topology_unlock(); PICKUP_GIANT(); } if (!error && (mp->mnt_flag & MNT_RELOAD)) error = ext2_reload(mp, td); if (error) return (error); devvp = ump->um_devvp; if (fs->e2fs_ronly && !vfs_flagopt(opts, "ro", NULL, 0)) { if (ext2_check_sb_compat(fs->e2fs, devvp->v_rdev, 0)) return (EPERM); /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_ACCESS(devvp, VREAD | VWRITE, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { VOP_UNLOCK(devvp, 0); return (error); } VOP_UNLOCK(devvp, 0); DROP_GIANT(); g_topology_lock(); error = g_access(ump->um_cp, 0, 1, 0); g_topology_unlock(); PICKUP_GIANT(); if (error) return (error); if ((fs->e2fs->e2fs_state & E2FS_ISCLEAN) == 0 || (fs->e2fs->e2fs_state & E2FS_ERRORS)) { if (mp->mnt_flag & MNT_FORCE) { printf( "WARNING: %s was not properly dismounted\n", fs->e2fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->e2fs_fsmnt); return (EPERM); } } fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN; (void)ext2_cgupdate(ump, MNT_WAIT); fs->e2fs_ronly = 0; MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_RDONLY; MNT_IUNLOCK(mp); } if (vfs_flagopt(opts, "export", NULL, 0)) { /* Process export requests in vfs_mount.c. */ return (error); } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible disk device. */ if (fspec == NULL) return (EINVAL); NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); if ((error = namei(ndp)) != 0) return (error); NDFREE(ndp, NDF_ONLY_PNBUF); devvp = ndp->ni_vp; if (!vn_isdisk(devvp, &error)) { vput(devvp); return (error); } /* * If mount by non-root, then verify that user has necessary * permissions on the device. * * XXXRW: VOP_ACCESS() enough? */ accmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accmode |= VWRITE; error = VOP_ACCESS(devvp, accmode, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = ext2_mountfs(devvp, mp); } else { if (devvp != ump->um_devvp) { vput(devvp); return (EINVAL); /* needs translation */ } else vput(devvp); } if (error) { vrele(devvp); return (error); } ump = VFSTOEXT2(mp); fs = ump->um_e2fs; /* * Note that this strncpy() is ok because of a check at the start * of ext2_mount(). */ strncpy(fs->e2fs_fsmnt, path, MAXMNTLEN); fs->e2fs_fsmnt[MAXMNTLEN - 1] = '\0'; vfs_mountedfrom(mp, fspec); return (0); }
int cpr_alloc_statefile(int alloc_retry) { register int rc = 0; char *str; /* * Statefile size validation. If checkpoint the first time, disk blocks * allocation will be done; otherwise, just do file size check. * if statefile allocation is being retried, C_VP will be inited */ if (alloc_retry) { str = "\n-->Retrying statefile allocation..."; if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG7)) prom_printf(str); if (C_VP->v_type != VBLK) (void) VOP_DUMPCTL(C_VP, DUMP_FREE, NULL, NULL); } else { /* * Open an exiting file for writing, the state file needs to be * pre-allocated since we can't and don't want to do allocation * during checkpoint (too much of the OS is disabled). * - do a preliminary size checking here, if it is too small, * allocate more space internally and retry. * - check the vp to make sure it's the right type. */ char *path = cpr_build_statefile_path(); if (path == NULL) return (ENXIO); else if (rc = cpr_verify_statefile_path()) return (rc); if (rc = vn_open(path, UIO_SYSSPACE, FCREAT|FWRITE, 0600, &C_VP, CRCREAT, 0)) { cpr_err(CE_WARN, "cannot open statefile %s", path); return (rc); } } /* * Only ufs and block special statefiles supported */ if (C_VP->v_type != VREG && C_VP->v_type != VBLK) { cpr_err(CE_CONT, "Statefile must be regular file or block special file."); return (EACCES); } if (rc = cpr_statefile_ok(C_VP, alloc_retry)) return (rc); if (C_VP->v_type != VBLK) { /* * sync out the fs change due to the statefile reservation. */ (void) VFS_SYNC(C_VP->v_vfsp, 0, CRED()); /* * Validate disk blocks allocation for the state file. * Ask the file system prepare itself for the dump operation. */ if (rc = VOP_DUMPCTL(C_VP, DUMP_ALLOC, NULL, NULL)) { cpr_err(CE_CONT, "Error allocating " "blocks for cpr statefile."); return (rc); } } return (0); }