X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/a3d08fcd5120d2aa8303b6349ca8b14e3f284af3..91447636331957f3d9b5ca5b508f07c526b0074d:/bsd/miscfs/synthfs/synthfs_vfsops.c?ds=sidebyside diff --git a/bsd/miscfs/synthfs/synthfs_vfsops.c b/bsd/miscfs/synthfs/synthfs_vfsops.c index 530239f61..39e8d6a6c 100644 --- a/bsd/miscfs/synthfs/synthfs_vfsops.c +++ b/bsd/miscfs/synthfs/synthfs_vfsops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,13 +31,12 @@ #include #include #include -#include +#include #include #include -#include +#include #include -#include -#include +#include #include #include #include @@ -45,6 +44,7 @@ #include #include #include +#include #include @@ -59,8 +59,8 @@ struct vfsops synthfs_vfsops = { synthfs_start, synthfs_unmount, synthfs_root, - synthfs_quotactl, - synthfs_statfs, + NULL, /* quotactl */ + synthfs_vfs_getattr, synthfs_sync, synthfs_vget, synthfs_fhtovp, @@ -71,7 +71,7 @@ struct vfsops synthfs_vfsops = { #define ROOTMPMODE 0755 #define ROOTPLACEHOLDERMODE 0700 -static char synthfs_fs_name[MFSNAMELEN] = "synthfs"; +static char synthfs_fs_name[MFSTYPENAMELEN] = "synthfs"; static char synthfs_fake_mntfromname[] = ""; @@ -91,130 +91,14 @@ int vn_symlink(struct proc *p, char *path, char *link); #if LOADABLE_FS void synthfs_load(int loadArgument) { - struct vfsconf *newvfsconf = NULL; - int j; - int (***opv_desc_vector_p)() = NULL; - int (**opv_desc_vector)(); - struct vnodeopv_entry_desc *opve_descp; - int error = 0; - -#pragma unused(loadArgument) - - /* - * This routine is responsible for all the initialization that would - * ordinarily be done as part of the system startup; it calls synthfs_init - * to do the initialization that is strictly synthfs-specific. - */ - - DBG_VOP(("load_synthfs: starting ...\n")); - - MALLOC(newvfsconf, void *, sizeof(struct vfsconf), M_SYNTHFS, M_WAITOK); - DBG_VOP(("load_synthfs: Allocated new vfsconf list entry, newvfsconf = 0x%08lx.\n", (unsigned long)newvfsconf)); - bzero(newvfsconf, sizeof(struct vfsconf)); - - if (newvfsconf) { - DBG_VOP(("load_synthfs: filling in newly allocated vfsconf entry at 0x%08lX.\n", (long)newvfsconf)); - newvfsconf->vfc_vfsops = &synthfs_vfsops; - strncpy(&newvfsconf->vfc_name[0], synthfs_fs_name, MFSNAMELEN); - newvfsconf->vfc_typenum = maxvfsconf++; - newvfsconf->vfc_refcount = 0; - newvfsconf->vfc_flags = 0; - newvfsconf->vfc_mountroot = NULL; /* Can't mount root of file system [yet] */ - - newvfsconf->vfc_next = NULL; - - /* Based on vfs_op_init and ... */ - opv_desc_vector_p = synthfs_vnodeop_opv_desc.opv_desc_vector_p; - - DBG_VOP(("load_synthfs: Allocating and initializing VNode ops vector...\n")); - - /* - * Allocate and init the vector. - * Also handle backwards compatibility. - */ - - MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_SYNTHFS, M_WAITOK); - bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); - opv_desc_vector = *opv_desc_vector_p; - for (j=0; synthfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) { - opve_descp = &(synthfs_vnodeop_opv_desc.opv_desc_ops[j]); - - /* - * Sanity check: is this operation listed - * in the list of operations? We check this - * by seeing if its offest is zero. Since - * the default routine should always be listed - * first, it should be the only one with a zero - * offset. Any other operation with a zero - * offset is probably not listed in - * vfs_op_descs, and so is probably an error. - * - * A panic here means the layer programmer - * has committed the all-too common bug - * of adding a new operation to the layer's - * list of vnode operations but - * not adding the operation to the system-wide - * list of supported operations. - */ - if (opve_descp->opve_op->vdesc_offset == 0 && - opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) { - DBG_VOP(("load_synthfs: operation %s not listed in %s.\n", - opve_descp->opve_op->vdesc_name, - "vfs_op_descs")); - panic ("load_synthfs: bad operation"); - } - /* - * Fill in this entry. - */ - opv_desc_vector[opve_descp->opve_op->vdesc_offset] = - opve_descp->opve_impl; - } - - /* - * Finally, go back and replace unfilled routines - * with their default. (Sigh, an O(n^3) algorithm. I - * could make it better, but that'd be work, and n is small.) - */ - opv_desc_vector_p = synthfs_vnodeop_opv_desc.opv_desc_vector_p; - - /* - * Force every operations vector to have a default routine. - */ - opv_desc_vector = *opv_desc_vector_p; - if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { - panic("load_vp;fs: operation vector without default routine."); - } - for (j = 0;jmnt_stat.f_fstypename, synthfs_fs_name, sizeof(mp->mnt_stat.f_fstypename)); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname) - 1, &size); - strncpy(mp->mnt_stat.f_mntfromname, synthfs_fake_mntfromname, sizeof(mp->mnt_stat.f_mntfromname)); + strncpy(mp->mnt_vfsstat.f_fstypename, synthfs_fs_name, sizeof(mp->mnt_vfsstat.f_fstypename)); + strncpy(mp->mnt_vfsstat.f_mntfromname, synthfs_fake_mntfromname, sizeof(mp->mnt_vfsstat.f_mntfromname)); priv_mnt_data->synthfs_mounteddev = (dev_t)0; priv_mnt_data->synthfs_nextid = FIRST_SYNTHFS_ID; priv_mnt_data->synthfs_filecount = 0; @@ -263,7 +146,7 @@ synthfs_mount_fs(struct mount *mp, char *path, caddr_t data, struct nameidata *n /* Drop the freshly acquired reference on the root, leaving v_usecount=1 to prevent the vnode from beeing freed: */ - vput(priv_mnt_data->synthfs_rootvp); + vnode_put(priv_mnt_data->synthfs_rootvp); return (0); } @@ -271,17 +154,15 @@ synthfs_mount_fs(struct mount *mp, char *path, caddr_t data, struct nameidata *n int -synthfs_mount(mp, path, data, ndp, p) +synthfs_mount(mp, devvp, data, context) register struct mount *mp; - char *path; - caddr_t data; - struct nameidata *ndp; - struct proc *p; + vnode_t devvp; + user_addr_t data; + vfs_context_t context; { size_t size; - (void) copyinstr(path, mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname) - 1, &size); - return (synthfs_mount_fs(mp, path, data, ndp, p)); + return (synthfs_mount_fs(mp, devvp, data, vfs_context_proc(context))); } @@ -301,10 +182,10 @@ synthfs_init(vfsp) } int -synthfs_start(mp, flags, p) +synthfs_start(mp, flags, context) struct mount * mp; int flags; -struct proc * p; +vfs_context_t context; { DBG_VOP(("synthfs_start called.\n")); return 0; @@ -314,38 +195,27 @@ struct proc * p; * Return the root of a filesystem. */ int -synthfs_root(mp, vpp) +synthfs_root(mp, vpp, context) struct mount *mp; struct vnode **vpp; + vfs_context_t context; { unsigned long root_nodeid = ROOT_DIRID; DBG_VOP(("synthfs_root called.\n")); *vpp = VFSTOSFS(mp)->synthfs_rootvp; - return vget(VFSTOSFS(mp)->synthfs_rootvp, LK_EXCLUSIVE | LK_RETRY, current_proc()); -} - -int -synthfs_quotactl(mp, cmds, uid, arg, p) -struct mount *mp; -int cmds; -uid_t uid; -caddr_t arg; -struct proc * p; -{ - DBG_VOP(("synthfs_quotactl called.\n")); - return (0); + return vnode_get(VFSTOSFS(mp)->synthfs_rootvp); } /* * unmount system call */ int -synthfs_unmount(mp, mntflags, p) +synthfs_unmount(mp, mntflags, context) struct mount *mp; int mntflags; - struct proc *p; + vfs_context_t context; { struct synthfs_mntdata *synth; struct vnode *root_vp; @@ -359,16 +229,13 @@ synthfs_unmount(mp, mntflags, p) if (retval && ((mntflags & MNT_FORCE) == 0)) goto Err_Exit; /* Free the root vnode. - Note that there's no need to vget() or vref() it before locking it here: the ref. count has been maintained at +1 ever since mount time. */ if (root_vp) { - retval = vn_lock(root_vp, LK_EXCLUSIVE | LK_RETRY, p); if ((mntflags & MNT_FORCE) == 0) { if (retval) goto Err_Exit; if (root_vp->v_usecount > 1) { DBG_VOP(("synthfs ERROR: root vnode = %x, usecount = %d\n", (int)root_vp, synth->synthfs_rootvp->v_usecount)); - VOP_UNLOCK(root_vp, 0, p); retval = EBUSY; goto Err_Exit; }; @@ -377,8 +244,10 @@ synthfs_unmount(mp, mntflags, p) synth->synthfs_rootvp = NULL; if (retval == 0) { - vput(root_vp); /* This drops synthfs's own refcount */ - vgone(root_vp); + vnode_get(root_vp); + vnode_rele(root_vp); + vnode_recycle(root_vp); + vnode_put(root_vp); /* This drops synthfs's own refcount */ }; }; @@ -398,24 +267,22 @@ Err_Exit: * Get file system statistics. */ int -synthfs_statfs(mp, sbp, p) - struct mount *mp; - register struct statfs *sbp; - struct proc *p; +synthfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t context) { - DBG_VOP(("synthfs_statfs called.\n")); - - sbp->f_bsize = 512; - sbp->f_iosize = 512; - sbp->f_blocks = 1024; // lies, darn lies and virtual file systems - sbp->f_bfree = 0; // Nope, can't write here! - sbp->f_bavail = 0; - sbp->f_files = VFSTOSFS(mp)->synthfs_filecount + VFSTOSFS(mp)->synthfs_dircount; - sbp->f_ffree = 0; - strncpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, sizeof(sbp->f_mntonname)); - strncpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, sizeof(sbp->f_mntfromname)); - - return (0); + struct synthfs_mntdata *synthfs_mp = VFSTOSFS(mp); + DBG_VOP(("synthfs_vfs_getattr called.\n")); + + VFSATTR_RETURN(fsap, f_bsize, 512); + VFSATTR_RETURN(fsap, f_iosize, 512); + VFSATTR_RETURN(fsap, f_blocks, 1024); + VFSATTR_RETURN(fsap, f_bfree, 0); + VFSATTR_RETURN(fsap, f_bavail, 0); + VFSATTR_RETURN(fsap, f_bused, 1024); + VFSATTR_RETURN(fsap, f_files, synthfs_mp->synthfs_filecount + synthfs_mp->synthfs_dircount); + VFSATTR_RETURN(fsap, f_ffree, 0); + VFSATTR_RETURN(fsap, f_fssubtype, 0); + + return 0; } /* @@ -423,11 +290,10 @@ synthfs_statfs(mp, sbp, p) * structures, so don't do anything */ int -synthfs_sync(mp, waitfor, cred, p) +synthfs_sync(mp, waitfor, context) struct mount *mp; int waitfor; - struct ucred *cred; - struct proc *p; + vfs_context_t context; { // DBG_VOP(("synthfs_sync called\n")); return 0; @@ -436,12 +302,14 @@ synthfs_sync(mp, waitfor, cred, p) * Look up a synthfs node by node number. */ int -synthfs_vget(mp, ino, vpp) +synthfs_vget(mp, ino, vpp, context) struct mount *mp; - void *ino; + ino64_t ino; struct vnode **vpp; + vfs_context_t context; { struct vnode *vp; + int vid = 0; // DBG_VOP(("synthfs_vget called\n")); @@ -452,19 +320,25 @@ synthfs_vget(mp, ino, vpp) } loop: - simple_lock(&mntvnode_slock); - LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { - if (VTOS(vp)->s_nodeid == *((unsigned long *)ino)) { - if (vget(vp, LK_EXCLUSIVE, current_proc()) != 0) { - simple_unlock(&mntvnode_slock); - goto loop; - }; - simple_unlock(&mntvnode_slock); + TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { + if (VTOS(vp)->s_nodeid == (unsigned long)ino) { + /* + * doing a vnode_getwithvid isn't technically + * necessary since synthfs is an unsafe filesystem + * and we're running behind a funnel at this point + * however, vnode_get always succeeds, which isn't + * what we want if this vnode is in the process of + * being terminated + */ + vid = vnode_vid(vp); + + if (vnode_getwithvid(vp, vid) != 0) { + goto loop; + }; *vpp = vp; return 0; }; }; - simple_unlock(&mntvnode_slock); *vpp = NULL; return -1; } @@ -473,17 +347,11 @@ loop: * fast filesystem related variables. */ int -synthfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) - int *name; - u_int namelen; - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - struct proc *p; +synthfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, + user_addr_t newp, size_t newlen, vfs_context_t context) { DBG_VOP(("synthfs_sysctl called.\n")); - return (EOPNOTSUPP); + return (ENOTSUP); } /* @@ -491,16 +359,15 @@ synthfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) * */ int -synthfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) +synthfs_fhtovp(mp, fhlen, fhp, vpp, context) register struct mount *mp; - struct fid *fhp; - struct mbuf *nam; + int fhlen; + unsigned char *fhp; struct vnode **vpp; - int *exflagsp; - struct ucred **credanonp; + vfs_context_t context; { DBG_VOP(("synthfs_fhtovp called.\n")); - return EOPNOTSUPP; + return ENOTSUP; } /* @@ -508,12 +375,14 @@ synthfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) */ /* ARGSUSED */ int -synthfs_vptofh(vp, fhp) +synthfs_vptofh(vp, fhlenp, fhp, context) struct vnode *vp; - struct fid *fhp; + int *fhlenp; + unsigned char *fhp; + vfs_context_t context; { DBG_VOP(("synthfs_vptofh called.\n")); - return EOPNOTSUPP; + return ENOTSUP; } @@ -522,38 +391,42 @@ synthfs_vptofh(vp, fhp) int -vn_mkdir(struct proc *p, char *path, int mode) { +vn_mkdir(struct proc *p, char *path, int mode) +{ struct nameidata nd; struct vnode *vp; - struct vattr vattr; + struct vnode_attr va; + struct vfs_context context; int error; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, path, p); - if (error = namei(&nd)) { + context.vc_proc = p; + context.vc_ucred = proc_ucred(p); /* XXX kauth_cred_get() ??? proxy */ + + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE32, CAST_USER_ADDR_T(path), &context); + error = namei(&nd); + if (error) { DBG_VOP(("vn_mkdir: error from namei, error = %d.\n", error)); return (error); }; vp = nd.ni_vp; - if (vp != NULL) { - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - vrele(vp); + + if (vp == NULL) { + VATTR_INIT(&va); + VATTR_SET(&va, va_type, VDIR); + VATTR_SET(&va, va_mode, (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask); + + error = vn_create(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, 0, &context); + if (error) + DBG_VOP(("vn_mkdir: error from vnop_mkdir (%d).\n", error)); + } else { DBG_VOP(("vn_mkdir: target already exists; returning EEXIST.\n")); - return (EEXIST); + error = EEXIST; } - VATTR_NULL(&vattr); - vattr.va_type = VDIR; - vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; - VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); - if (error) { - DBG_VOP(("vn_mkdir: error from VOP_MKDIR (%d).\n", error)); - } else { - vput(nd.ni_vp); - }; + vnode_put(nd.ni_dvp); + if (nd.ni_vp) + vnode_put(nd.ni_vp); + nameidone(&nd); + return (error); } @@ -562,25 +435,31 @@ vn_mkdir(struct proc *p, char *path, int mode) { int vn_symlink(struct proc *p, char *path, char *link) { struct nameidata nd; - struct vattr vattr; + struct vnode_attr va; + struct vfs_context context; int error; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, link, p); - if (error = namei(&nd)) return error; - - if (nd.ni_vp) { - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - vrele(nd.ni_vp); - return EEXIST; - } - VATTR_NULL(&vattr); - vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; - VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - return VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); + context.vc_proc = p; + context.vc_ucred = proc_ucred(p); /* XXX kauth_cred_get() ??? proxy */ + + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE32, CAST_USER_ADDR_T(link), &context); + if ((error = namei(&nd))) return error; + + if (nd.ni_vp == NULL) { + VATTR_INIT(&va); + VATTR_SET(&va, va_type, VLNK); + VATTR_SET(&va, va_mode, ACCESSPERMS &~ p->p_fd->fd_cmask); + + error = VNOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, path, &context); + } else + error = EEXIST; + + vnode_put(nd.ni_dvp); + if (nd.ni_vp) + vnode_put(nd.ni_vp); + nameidone(&nd); + + return (error); }