static OSKIT_COMDECL filesystem_getroot(oskit_filesystem_t *f, struct oskit_dir **out_dir) { struct gfilesystem *fs = (struct gfilesystem *) f; oskit_dir_t *d; struct proc *p; oskit_error_t ferror; struct vnode *vp; int error; if (!fs || !fs->count || !fs->mp) return OSKIT_E_INVALIDARG; ferror = getproc(&p); if (ferror) return ferror; error = VFS_ROOT(fs->mp, &vp); if (error) { prfree(p); return errno_to_oskit_error(error); } error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) { vput(vp); prfree(p); return errno_to_oskit_error(error); } d = (oskit_dir_t *) hashtab_search(vptab, (hashtab_key_t) vp); if (d) { oskit_dir_addref(d); } else { d = (oskit_dir_t *) gfile_create(fs,vp); if (!d) { vput(vp); prfree(p); return OSKIT_ENOMEM; } } vput(vp); prfree(p); *out_dir = d; 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 OSKIT_COMDECL_U filesystem_release(oskit_filesystem_t *f) { struct gfilesystem *fs; struct proc *p; dev_t dev; int rc; unsigned newcount; fs = (struct gfilesystem*)f; if (fs == NULL) panic("%s:%d: null filesystem", __FILE__, __LINE__); if (fs->count == 0) panic("%s:%d: bad count", __FILE__, __LINE__); newcount = --fs->count; if (newcount == 0) { rc = getproc(&p); assert(rc == 0); if (fs->mp) { dev = ((struct ufsmount *)fs->mp->mnt_data)->um_dev; rc = dounmount(fs->mp, MNT_FORCE, p); assert(rc == 0); oskit_blkio_release((oskit_blkio_t *)dev); } prfree(p); free(fs,M_TEMP); } return newcount; }
static OSKIT_COMDECL filesystem_unmount(oskit_filesystem_t *f) { struct gfilesystem *fs = (struct gfilesystem *) f; struct mount *mp; dev_t dev; struct proc *p; oskit_error_t ferror; int error; if (!fs || !fs->count || !fs->mp) return OSKIT_E_INVALIDARG; ferror = getproc(&p); if (ferror) return ferror; mp = fs->mp; /* * Only root, or the user that did the original mount is * permitted to forcibly unmount it. */ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && (error = suser(p->p_ucred, 0))) { prfree(p); return errno_to_oskit_error(error); } /* Get the blkio "pointed" to by the dev_t so we can release it below. */ dev = ((struct ufsmount *)mp->mnt_data)->um_dev; error = dounmount(fs->mp, MNT_FORCE, p); fs->mp = 0; prfree(p); oskit_blkio_release((oskit_blkio_t *)dev); if (error) return errno_to_oskit_error(error); return 0; }
static OSKIT_COMDECL filesystem_statfs(oskit_filesystem_t *f, oskit_statfs_t *out_stats) { struct gfilesystem *fs = (struct gfilesystem *) f; struct statfs *sp; struct mount *mp; struct proc *p; oskit_error_t ferror; int error; if (!fs || !fs->count || !fs->mp) return OSKIT_E_INVALIDARG; ferror = getproc(&p); if (ferror) return ferror; mp = fs->mp; sp = &mp->mnt_stat; error = VFS_STATFS(fs->mp, sp, p); prfree(p); if (error) return errno_to_oskit_error(error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; out_stats->flag = 0; if (sp->f_flags & MNT_RDONLY) out_stats->flag |= OSKIT_FS_RDONLY; if (sp->f_flags & MNT_NOEXEC) out_stats->flag |= OSKIT_FS_NOEXEC; if (sp->f_flags & MNT_NOSUID) out_stats->flag |= OSKIT_FS_NOSUID; if (sp->f_flags & MNT_NODEV) out_stats->flag |= OSKIT_FS_NODEV; out_stats->bsize = sp->f_bsize; out_stats->frsize = sp->f_bsize; out_stats->blocks = sp->f_blocks; out_stats->bfree = sp->f_bfree; out_stats->bavail = sp->f_bavail; out_stats->files = sp->f_files; out_stats->ffree = sp->f_ffree; out_stats->favail = sp->f_ffree; out_stats->fsid = sp->f_fsid.val[0]; /* device number */ out_stats->namemax = NAME_MAX; return 0; }
/* * Remove zombie children from the process table. */ void freeproc(proc_t *p) { proc_t *q; task_t *tk; ASSERT(p->p_stat == SZOMB); ASSERT(p->p_tlist == NULL); ASSERT(MUTEX_HELD(&pidlock)); sigdelq(p, NULL, 0); if (p->p_killsqp) { siginfofree(p->p_killsqp); p->p_killsqp = NULL; } prfree(p); /* inform /proc */ /* * Don't free the init processes. * Other dying processes will access it. */ if (p == proc_init) return; /* * We wait until now to free the cred structure because a * zombie process's credentials may be examined by /proc. * No cred locking needed because there are no threads at this point. */ upcount_dec(crgetruid(p->p_cred), crgetzoneid(p->p_cred)); crfree(p->p_cred); if (p->p_corefile != NULL) { corectl_path_rele(p->p_corefile); p->p_corefile = NULL; } if (p->p_content != NULL) { corectl_content_rele(p->p_content); p->p_content = NULL; } if (p->p_nextofkin && !((p->p_nextofkin->p_flag & SNOWAIT) || (PTOU(p->p_nextofkin)->u_signal[SIGCLD - 1] == SIG_IGN))) { /* * This should still do the right thing since p_utime/stime * get set to the correct value on process exit, so it * should get properly updated */ p->p_nextofkin->p_cutime += p->p_utime; p->p_nextofkin->p_cstime += p->p_stime; p->p_nextofkin->p_cacct[LMS_USER] += p->p_acct[LMS_USER]; p->p_nextofkin->p_cacct[LMS_SYSTEM] += p->p_acct[LMS_SYSTEM]; p->p_nextofkin->p_cacct[LMS_TRAP] += p->p_acct[LMS_TRAP]; p->p_nextofkin->p_cacct[LMS_TFAULT] += p->p_acct[LMS_TFAULT]; p->p_nextofkin->p_cacct[LMS_DFAULT] += p->p_acct[LMS_DFAULT]; p->p_nextofkin->p_cacct[LMS_KFAULT] += p->p_acct[LMS_KFAULT]; p->p_nextofkin->p_cacct[LMS_USER_LOCK] += p->p_acct[LMS_USER_LOCK]; p->p_nextofkin->p_cacct[LMS_SLEEP] += p->p_acct[LMS_SLEEP]; p->p_nextofkin->p_cacct[LMS_WAIT_CPU] += p->p_acct[LMS_WAIT_CPU]; p->p_nextofkin->p_cacct[LMS_STOPPED] += p->p_acct[LMS_STOPPED]; p->p_nextofkin->p_cru.minflt += p->p_ru.minflt; p->p_nextofkin->p_cru.majflt += p->p_ru.majflt; p->p_nextofkin->p_cru.nswap += p->p_ru.nswap; p->p_nextofkin->p_cru.inblock += p->p_ru.inblock; p->p_nextofkin->p_cru.oublock += p->p_ru.oublock; p->p_nextofkin->p_cru.msgsnd += p->p_ru.msgsnd; p->p_nextofkin->p_cru.msgrcv += p->p_ru.msgrcv; p->p_nextofkin->p_cru.nsignals += p->p_ru.nsignals; p->p_nextofkin->p_cru.nvcsw += p->p_ru.nvcsw; p->p_nextofkin->p_cru.nivcsw += p->p_ru.nivcsw; p->p_nextofkin->p_cru.sysc += p->p_ru.sysc; p->p_nextofkin->p_cru.ioch += p->p_ru.ioch; } q = p->p_nextofkin; if (q && q->p_orphan == p) q->p_orphan = p->p_nextorph; else if (q) { for (q = q->p_orphan; q; q = q->p_nextorph) if (q->p_nextorph == p) break; ASSERT(q && q->p_nextorph == p); q->p_nextorph = p->p_nextorph; } /* * The process table slot is being freed, so it is now safe to give up * task and project membership. */ mutex_enter(&p->p_lock); tk = p->p_task; task_detach(p); mutex_exit(&p->p_lock); proc_detach(p); pid_exit(p, tk); /* frees pid and proc structure */ task_rele(tk); }
static OSKIT_COMDECL filesystem_remount(oskit_filesystem_t *f, oskit_u32_t flags) { struct gfilesystem *fs = (struct gfilesystem *) f; struct mount *mp; struct proc *p; oskit_error_t ferror; int error, oflag; if (!fs || !fs->count || !fs->mp) return OSKIT_E_INVALIDARG; ferror = getproc(&p); if (ferror) return ferror; mp = fs->mp; /* * Only root, or the user that did the original mount is * permitted to update it. */ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && (error = suser(p->p_ucred, 0))) { prfree(p); return errno_to_oskit_error(error); } if (flags & OSKIT_FS_NOEXEC) mp->mnt_flag |= MNT_NOEXEC; if (flags & OSKIT_FS_NOSUID) mp->mnt_flag |= MNT_NOSUID; if (flags & OSKIT_FS_NODEV) mp->mnt_flag |= MNT_NODEV; oflag = mp->mnt_flag; if ((flags & OSKIT_FS_RDONLY) && ((mp->mnt_flag & MNT_RDONLY) == 0)) /* rdwr -> rdonly */ mp->mnt_flag |= (MNT_UPDATE | MNT_FORCE | MNT_RDONLY); if (((flags & OSKIT_FS_RDONLY) == 0) && (mp->mnt_flag & MNT_RDONLY)) /* rdonly -> rdwr */ mp->mnt_flag |= (MNT_UPDATE | MNT_RELOAD | MNT_WANTRDWR); error = 0; if (mp->mnt_flag & MNT_UPDATE) { struct nameidata nd; /* dummy to contain cred */ struct ucred cred; /* dummy, contents not actually used */ nd.ni_cnd.cn_cred = &cred; error = VFS_MOUNT(mp, 0, 0, &nd, p); if (mp->mnt_flag & MNT_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); if (error) mp->mnt_flag = oflag; } prfree(p); if (error) return errno_to_oskit_error(error); return 0; }