/* * union_create: * * a_dvp is locked on entry and remains locked on return. a_vpp is returned * locked if no error occurs, otherwise it is garbage. * * union_create(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnp, struct vattr *a_vap) */ static int union_create(struct vop_old_create_args *ap) { struct union_node *dun = VTOUNION(ap->a_dvp); struct componentname *cnp = ap->a_cnp; struct thread *td = cnp->cn_td; struct vnode *dvp; int error = EROFS; if ((dvp = union_lock_upper(dun, td)) != NULL) { struct vnode *vp; struct mount *mp; error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap); if (error == 0) { mp = ap->a_dvp->v_mount; vn_unlock(vp); UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_sysref.refcnt)); error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp, NULLVP, 1); UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_sysref.refcnt)); } union_unlock_upper(dvp, td); } return (error); }
static int xattr_dir_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl, int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct, vsecattr_t *vsecp) { vnode_t *pvp; int error; *vpp = NULL; /* * Don't allow creation of extended attributes with sysattr names. */ if (is_sattr_name(name)) { return (gfs_dir_lookup(dvp, name, vpp, cr, 0, NULL, NULL)); } error = xattr_dir_realdir(dvp, &pvp, LOOKUP_XATTR|CREATE_XATTR_DIR, cr, ct); if (error == 0) { error = VOP_CREATE(pvp, name, vap, excl, mode, vpp, cr, flag, ct, vsecp); } return (error); }
static int unionfs_create(void *v) { struct vop_create_args *ap = v; struct unionfs_node *dunp; struct componentname *cnp; struct vnode *udvp; struct vnode *vp; int error; UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n"); dunp = VTOUNIONFS(ap->a_dvp); cnp = ap->a_cnp; udvp = dunp->un_uppervp; error = EROFS; if (udvp != NULLVP) { if ((error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap)) == 0) { error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, ap->a_dvp, ap->a_vpp, cnp); if (error) { vput(vp); } else { vrele(vp); } } } UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error); return (error); }
int smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; xvattr_t xvattr; vattr_t *vap; char *np = name; char namebuf[MAXNAMELEN]; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; attr->sa_vattr.va_mask = 0; if (vfs_has_feature(dvp->v_vfsp, VFSFT_XVATTR)) { smb_vop_setup_xvattr(attr, &xvattr); vap = &xvattr.xva_vattr; } else { smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); vap = &attr->sa_vattr; } if (flags & SMB_CATIA) { np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf)); if (strchr(np, '/') != NULL) return (EILSEQ); } error = VOP_CREATE(dvp, np, vap, EXCL, attr->sa_vattr.va_mode, vpp, cr, option_flags, &smb_ct, vsap); return (error); }
int RUMP_VOP_CREATE(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { int error; rump_schedule(); error = VOP_CREATE(dvp, vpp, cnp, vap); rump_unschedule(); return error; }
static int auto_create( vnode_t *dvp, char *nm, vattr_t *va, vcexcl_t excl, int mode, vnode_t **vpp, cred_t *cred, int flag, caller_context_t *ct, vsecattr_t *vsecp) { vnode_t *newvp; int error; AUTOFS_DPRINT((4, "auto_create dvp %p nm %s\n", (void *)dvp, nm)); if (error = auto_trigger_mount(dvp, cred, &newvp)) goto done; if (newvp != NULL) { /* * Node is now mounted on. */ if (vn_is_readonly(newvp)) error = EROFS; else error = VOP_CREATE(newvp, nm, va, excl, mode, vpp, cred, flag, ct, vsecp); VN_RELE(newvp); } else error = ENOSYS; done: AUTOFS_DPRINT((5, "auto_create: error=%d\n", error)); return (error); }
errno_t sc_open(thread_t *p, syscall_result_t *r, sc_open_args *arg) { int fd; int flags = arg->flags; int error = 0; vnode_t *node; proc_t *proc = p->thr_proc; char fname[PATH_MAX+1]; if((error = copyinstr(fname, arg->fname, PATH_MAX))) return error; KASSERT(proc->p_rootdir!=NULL); error = vfs_lookup(proc->p_curdir, &node, fname, p, LKP_NORMAL); if(error) { if(!(flags & O_CREAT)) return error; vnode_t *parent; error = vfs_lookup_parent(proc->p_curdir, &parent, fname, p); if(error) return error; if((error = VOP_ACCESS(parent, W_OK, proc->p_cred))) { vrele(parent); return error; } vattr_t attr; attr.va_mode = arg->mode & ~(proc->p_umask) & 0777; attr.va_type = VNODE_TYPE_REG; attr.va_uid = proc->p_cred->p_uid; attr.va_gid = proc->p_cred->p_gid; attr.va_size = 0; attr.va_dev = NULL; error = VOP_CREATE(parent, &node, _get_last_cmpt(fname), &attr); VOP_UNLOCK(parent); if(error) return error; VOP_LOCK(node); } else { //plik istnieje if((flags & O_CREAT) && (flags & O_EXCL)) { vrele(node); return -EEXIST; } if((node->v_type == VNODE_TYPE_DIR) && (flags & (O_RDWR | O_WRONLY))) { vrele(node); return -EISDIR; } } int wmode = (flags & O_RDWR) ? (W_OK | R_OK) : (flags & O_RDONLY) ? (R_OK) : (W_OK); if((error = VOP_ACCESS(node, wmode, proc->p_cred))) { vrele(node); return error; } if((error = VOP_OPEN(node, flags, arg->mode))) { vrele(node); return error; } if(ISSET(flags, O_RDWR | O_WRONLY) && ISSET(flags, O_TRUNC) && node->v_type == VNODE_TYPE_REG) VOP_TRUNCATE(node, 0); if((error = f_alloc(proc, node, flags, &fd))) { vrele(node); // <- powinno to tutaj być, dopisałem bo nie było. return error; } VOP_UNLOCK(node); r->result = fd; return 0; }
static int zfsfuse_opencreate(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, int fflags, mode_t createmode, const char *name) { if(name && strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); cred_t cred; zfsfuse_getcred(req, &cred); /* Map flags */ int mode, flags; if(fflags & O_WRONLY) { mode = VWRITE; flags = FWRITE; } else if(fflags & O_RDWR) { mode = VREAD | VWRITE; flags = FREAD | FWRITE; } else { mode = VREAD; flags = FREAD; } if(fflags & O_CREAT) flags |= FCREAT; if(fflags & O_SYNC) flags |= FSYNC; if(fflags & O_DSYNC) flags |= FDSYNC; if(fflags & O_RSYNC) flags |= FRSYNC; if(fflags & O_APPEND) flags |= FAPPEND; if(fflags & O_LARGEFILE) flags |= FOFFMAX; if(fflags & O_NOFOLLOW) flags |= FNOFOLLOW; if(fflags & O_TRUNC) flags |= FTRUNC; if(fflags & O_EXCL) flags |= FEXCL; znode_t *znode; int error = zfs_zget(zfsvfs, ino, &znode, B_FALSE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(znode != NULL); vnode_t *vp = ZTOV(znode); ASSERT(vp != NULL); if (flags & FCREAT) { enum vcexcl excl; /* * Wish to create a file. */ vattr_t vattr; vattr.va_type = VREG; vattr.va_mode = createmode; vattr.va_mask = AT_TYPE|AT_MODE; if (flags & FTRUNC) { vattr.va_size = 0; vattr.va_mask |= AT_SIZE; } if (flags & FEXCL) excl = EXCL; else excl = NONEXCL; vnode_t *new_vp; /* FIXME: check filesystem boundaries */ error = VOP_CREATE(vp, (char *) name, &vattr, excl, mode, &new_vp, &cred, 0, NULL, NULL); if(error) goto out; VN_RELE(vp); vp = new_vp; } else { /* * Get the attributes to check whether file is large. * We do this only if the O_LARGEFILE flag is not set and * only for regular files. */ if (!(flags & FOFFMAX) && (vp->v_type == VREG)) { vattr_t vattr; vattr.va_mask = AT_SIZE; if ((error = VOP_GETATTR(vp, &vattr, 0, &cred, NULL))) goto out; if (vattr.va_size > (u_offset_t) MAXOFF32_T) { /* * Large File API - regular open fails * if FOFFMAX flag is set in file mode */ error = EOVERFLOW; goto out; } } /* * Check permissions. */ if (error = VOP_ACCESS(vp, mode, 0, &cred, NULL)) goto out; } if ((flags & FNOFOLLOW) && vp->v_type == VLNK) { error = ELOOP; goto out; } vnode_t *old_vp = vp; error = VOP_OPEN(&vp, flags, &cred, NULL); ASSERT(old_vp == vp); if(error) goto out; struct fuse_entry_param e = { 0 }; if(flags & FCREAT) { error = zfsfuse_stat(vp, &e.attr, &cred); if(error) goto out; } file_info_t *info = kmem_cache_alloc(file_info_cache, KM_NOSLEEP); if(info == NULL) { error = ENOMEM; goto out; } info->vp = vp; info->flags = flags; fi->fh = (uint64_t) (uintptr_t) info; fi->keep_cache = 1; if(flags & FCREAT) { e.attr_timeout = 0.0; e.entry_timeout = 0.0; e.ino = VTOZ(vp)->z_id; if(e.ino == 3) e.ino = 1; e.generation = VTOZ(vp)->z_phys->zp_gen; } out: if(error) { ASSERT(vp->v_count > 0); VN_RELE(vp); } ZFS_EXIT(zfsvfs); if(!error) { if(!(flags & FCREAT)) fuse_reply_open(req, fi); else fuse_reply_create(req, &e, fi); } return error; }
/* * Creates the fs cache directory. * The directory name is the ascii version of the fsid. * Also makes a symlink to the directory using the specified name. */ int fscdir_create(cachefscache_t *cachep, char *namep, fscache_t *fscp) { int error; vnode_t *fscdirvp = NULL; vnode_t *infovp = NULL; vnode_t *attrvp = NULL; struct vattr *attrp = (struct vattr *)NULL; char name[CFS_FRONTFILE_NAME_SIZE]; int files; int blocks = 0; cfs_cid_t cid; ino64_t fsid; ASSERT(MUTEX_HELD(&cachep->c_fslistlock)); ASSERT(fscp->fs_infovp == NULL); ASSERT(fscp->fs_fscdirvp == NULL); ASSERT(fscp->fs_fsattrdir == NULL); /* directory, symlink and options file + attrcache dir */ files = 0; while (files < 4) { error = cachefs_allocfile(cachep); if (error) goto out; files++; } error = cachefs_allocblocks(cachep, 4, CACHEFS_RL_NONE); if (error) goto out; blocks = 4; attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP); attrp->va_mode = S_IFDIR | 0777; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VDIR; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_MKDIR(cachep->c_dirvp, namep, attrp, &fscdirvp, kcred, NULL, 0, NULL); if (error) { cmn_err(CE_WARN, "Can't create fs cache directory"); goto out; } /* * Created the directory. Get the fileno. That'll be the cachefs_fsid. */ attrp->va_mask = AT_NODEID; error = VOP_GETATTR(fscdirvp, attrp, 0, kcred, NULL); if (error) { goto out; } fsid = attrp->va_nodeid; attrp->va_mode = S_IFREG | 0666; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VREG; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_CREATE(fscdirvp, CACHEFS_FSINFO, attrp, EXCL, 0600, &infovp, kcred, 0, NULL, NULL); if (error) { cmn_err(CE_WARN, "Can't create fs option file"); goto out; } attrp->va_size = MAXBSIZE; attrp->va_mask = AT_SIZE; error = VOP_SETATTR(infovp, attrp, 0, kcred, NULL); if (error) { cmn_err(CE_WARN, "Can't set size of fsinfo file"); goto out; } /* write out the info file */ fscp->fs_flags |= CFS_FS_DIRTYINFO; error = fscache_info_sync(fscp); if (error) goto out; /* * Install the symlink from cachefs_fsid -> directory. */ cid.cid_flags = 0; cid.cid_fileno = fsid; make_ascii_name(&cid, name); error = VOP_RENAME(cachep->c_dirvp, namep, cachep->c_dirvp, name, kcred, NULL, 0); if (error) { cmn_err(CE_WARN, "Can't rename cache directory"); goto out; } attrp->va_mask = AT_MODE | AT_TYPE; attrp->va_mode = 0777; attrp->va_type = VLNK; error = VOP_SYMLINK(cachep->c_dirvp, namep, attrp, name, kcred, NULL, 0); if (error) { cmn_err(CE_WARN, "Can't create cache directory symlink"); goto out; } /* * Finally, make the attrcache directory */ attrp->va_mode = S_IFDIR | 0777; attrp->va_uid = 0; attrp->va_gid = 0; attrp->va_type = VDIR; attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; error = VOP_MKDIR(fscdirvp, ATTRCACHE_NAME, attrp, &attrvp, kcred, NULL, 0, NULL); if (error) { cmn_err(CE_WARN, "Can't create attrcache dir for fscache"); goto out; } mutex_enter(&fscp->fs_fslock); fscp->fs_cfsid = fsid; fscp->fs_fscdirvp = fscdirvp; fscp->fs_fsattrdir = attrvp; fscp->fs_infovp = infovp; mutex_exit(&fscp->fs_fslock); out: if (error) { while (files-- > 0) cachefs_freefile(cachep); if (fscdirvp) VN_RELE(fscdirvp); if (blocks) cachefs_freeblocks(cachep, blocks, CACHEFS_RL_NONE); if (attrvp) VN_RELE(attrvp); if (infovp) VN_RELE(infovp); } if (attrp) cachefs_kmem_free(attrp, sizeof (struct vattr)); return (error); }
/* * Replay file create with optional ACL, xvattr information as well * as option FUID information. */ static int zfs_replay_create_acl(zfsvfs_t *zfsvfs, lr_acl_create_t *lracl, boolean_t byteswap) { char *name = NULL; /* location determined later */ lr_create_t *lr = (lr_create_t *)lracl; znode_t *dzp; vnode_t *vp = NULL; xvattr_t xva; int vflg = 0; vsecattr_t vsec = { 0 }; lr_attr_t *lrattr; void *aclstart; void *fuidstart; size_t xvatlen = 0; uint64_t txtype; int error; txtype = (lr->lr_common.lrc_txtype & ~TX_CI); if (byteswap) { byteswap_uint64_array(lracl, sizeof (*lracl)); if (txtype == TX_CREATE_ACL_ATTR || txtype == TX_MKDIR_ACL_ATTR) { lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); zfs_replay_swap_attrs(lrattr); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); } aclstart = (caddr_t)(lracl + 1) + xvatlen; zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); /* swap fuids */ if (lracl->lr_fuidcnt) { byteswap_uint64_array((caddr_t)aclstart + ZIL_ACE_LENGTH(lracl->lr_acl_bytes), lracl->lr_fuidcnt * sizeof (uint64_t)); } } if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) return (error); xva_init(&xva); zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) * eventually end up in zfs_mknode(), which assigns the object's * creation time and generation number. The generic VOP_CREATE() * doesn't have either concept, so we smuggle the values inside * the vattr's otherwise unused va_ctime and va_nblocks fields. */ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); xva.xva_vattr.va_nblocks = lr->lr_gen; error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); if (error != ENOENT) goto bail; if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; switch (txtype) { case TX_CREATE_ACL: aclstart = (caddr_t)(lracl + 1); fuidstart = (caddr_t)aclstart + ZIL_ACE_LENGTH(lracl->lr_acl_bytes); zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); /*FALLTHROUGH*/ case TX_CREATE_ACL_ATTR: if (name == NULL) { lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); xva.xva_vattr.va_mask |= AT_XVATTR; zfs_replay_xvattr(lrattr, &xva); } vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; vsec.vsa_aclcnt = lracl->lr_aclcnt; vsec.vsa_aclentsz = lracl->lr_acl_bytes; vsec.vsa_aclflags = lracl->lr_acl_flags; if (zfsvfs->z_fuid_replay == NULL) { fuidstart = (caddr_t)(lracl + 1) + xvatlen + ZIL_ACE_LENGTH(lracl->lr_acl_bytes); zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); } #ifdef TODO error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 0, 0, &vp, kcred, vflg, NULL, &vsec); #else panic("%s:%u: unsupported condition", __func__, __LINE__); #endif break; case TX_MKDIR_ACL: aclstart = (caddr_t)(lracl + 1); fuidstart = (caddr_t)aclstart + ZIL_ACE_LENGTH(lracl->lr_acl_bytes); zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); /*FALLTHROUGH*/ case TX_MKDIR_ACL_ATTR: if (name == NULL) { lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); zfs_replay_xvattr(lrattr, &xva); } vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; vsec.vsa_aclcnt = lracl->lr_aclcnt; vsec.vsa_aclentsz = lracl->lr_acl_bytes; vsec.vsa_aclflags = lracl->lr_acl_flags; if (zfsvfs->z_fuid_replay == NULL) { fuidstart = (caddr_t)(lracl + 1) + xvatlen + ZIL_ACE_LENGTH(lracl->lr_acl_bytes); zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); } #ifdef TODO error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, &vp, kcred, NULL, vflg, &vsec); #else panic("%s:%u: unsupported condition", __func__, __LINE__); #endif break; default: error = ENOTSUP; } bail: if (error == 0 && vp != NULL) VN_RELE(vp); VN_RELE(ZTOV(dzp)); if (zfsvfs->z_fuid_replay) zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; return (error); }
extern int vnode_iop_create( INODE_T * parent, struct dentry * dentry, int mode, struct nameidata *nd ) { int err = 0; VATTR_T *vap; VNODE_T *newvp; struct create_ctx ctx; CALL_DATA_T cd; ASSERT_I_SEM_MINE(parent); ASSERT(MDKI_INOISMVFS(parent)); vap = VATTR_ALLOC(); if (vap == NULL) return -ENOMEM; VATTR_NULL(vap); mdki_linux_init_call_data(&cd); /* * Solaris sends only type, mode, size, so we will too. */ vap->va_type = VREG; vap->va_mode = mode & ~S_IFMT; vap->va_size = 0; vap->va_mask = AT_TYPE|AT_MODE|AT_SIZE; newvp = NULL; dentry->d_inode = NULL; ctx.dentry = dentry; ctx.parent = parent; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) /* break any rcu-walk in progress */ # if defined(MRG) write_seqlock_barrier(&dentry->d_lock); # else /* defined (MRG) */ write_seqcount_barrier(&dentry->d_seq); # endif /* else defined (MRG) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) */ err = VOP_CREATE(ITOV(parent), (/* drop const */ char *) dentry->d_name.name, vap, NONEXCL, /* XXX handled by generic layer? */ mode, /* not used except for passthrough, see vap->va_mode */ &newvp, &cd, &ctx); err = mdki_errno_unix_to_linux(err); /* dentry reference uses the hold count from a successful create */ if (!err) { if (dentry->d_inode == NULL) { /* Not a shadow object */ ASSERT(newvp != NULL); ASSERT(VTOI(newvp) != NULL); VNODE_D_INSTANTIATE(dentry, VTOI(newvp)); VATTR_SET_MASK(vap, AT_ALL); if (VOP_GETATTR(newvp, vap, 0, &cd) == 0) mdki_linux_vattr_pullup(newvp, vap, AT_ALL); } else { /* drop the extra ref returned in newvp */ VN_RELE(newvp); } /* I nuked the code checking not VCHR, VREG--we are always VREG */ } else { ASSERT(!dentry->d_inode); ASSERT(!newvp); } VATTR_FREE(vap); mdki_linux_destroy_call_data(&cd); return(err); }
/* * Sets up for writing to the log files. */ int cachefs_dlog_setup(fscache_t *fscp, int createfile) { struct vattr vattr; int error = 0; int createdone = 0; int lookupdone = 0; int version = CFS_DLOG_VERSION; off_t offset; struct cfs_dlog_trailer trailer; mutex_enter(&fscp->fs_dlock); /* all done if the log files already exist */ if (fscp->fs_dlogfile) { ASSERT(fscp->fs_dmapfile); goto out; } /* see if the log file exists */ error = VOP_LOOKUP(fscp->fs_fscdirvp, CACHEFS_DLOG_FILE, &fscp->fs_dlogfile, NULL, 0, NULL, kcred, NULL, NULL, NULL); if (error && (createfile == 0)) goto out; /* if the lookup failed then create file log files */ if (error) { createdone++; vattr.va_mode = S_IFREG | 0666; vattr.va_uid = 0; vattr.va_gid = 0; vattr.va_type = VREG; vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID; error = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_DLOG_FILE, &vattr, 0, 0666, &fscp->fs_dlogfile, kcred, 0, NULL, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: log file create fail %d\n", error); #endif goto out; } /* write the version number into the log file */ error = vn_rdwr(UIO_WRITE, fscp->fs_dlogfile, (caddr_t)&version, sizeof (version), (offset_t)0, UIO_SYSSPACE, FSYNC, RLIM_INFINITY, kcred, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: log file init fail %d\n", error); #endif goto out; } vattr.va_mode = S_IFREG | 0666; vattr.va_uid = 0; vattr.va_gid = 0; vattr.va_type = VREG; vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID; error = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_DMAP_FILE, &vattr, 0, 0666, &fscp->fs_dmapfile, kcred, 0, NULL, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: map file create fail %d\n", error); #endif goto out; } fscp->fs_dlogoff = sizeof (version); fscp->fs_dlogseq = 0; fscp->fs_dmapoff = 0; fscp->fs_dmapsize = 0; } /* * Else the lookup succeeded. * Before mounting, fsck should have fixed any problems * in the log file. */ else { lookupdone++; /* find the end of the log file */ vattr.va_mask = AT_ALL; error = VOP_GETATTR(fscp->fs_dlogfile, &vattr, 0, kcred, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: log file getattr fail %d\n", error); #endif goto out; } /*LINTED alignment okay*/ ASSERT(vattr.va_size <= MAXOFF_T); fscp->fs_dlogoff = (off_t)vattr.va_size; offset = vattr.va_size - sizeof (struct cfs_dlog_trailer); /* * The last record in the dlog file is a trailer record * that contains the last sequence number used. This is * used to reset the sequence number when a logfile already * exists. */ error = vn_rdwr(UIO_READ, fscp->fs_dlogfile, (caddr_t)&trailer, sizeof (struct cfs_dlog_trailer), (offset_t)offset, UIO_SYSSPACE, FSYNC, RLIM_INFINITY, kcred, NULL); if (error == 0) { if (trailer.dl_op == CFS_DLOG_TRAILER) { fscp->fs_dlogseq = trailer.dl_seq; /* * Set the offset of the next record to be * written, to over write the current * trailer. */ fscp->fs_dlogoff = offset; } else { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) { cmn_err(CE_WARN, "cachefs: can't find dlog trailer"); cmn_err(CE_WARN, "cachefs: fsck required"); } #endif /* CFSDEBUG */ /*LINTED alignment okay*/ fscp->fs_dlogseq = (uint_t)vattr.va_size; } } else { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) cmn_err(CE_WARN, "cachefs: error reading dlog trailer"); #endif /* CFSDEBUG */ /*LINTED alignment okay*/ fscp->fs_dlogseq = (uint_t)vattr.va_size; } error = VOP_LOOKUP(fscp->fs_fscdirvp, CACHEFS_DMAP_FILE, &fscp->fs_dmapfile, NULL, 0, NULL, kcred, NULL, NULL, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: map file lookup fail %d\n", error); #endif goto out; } vattr.va_mask = AT_ALL; error = VOP_GETATTR(fscp->fs_dmapfile, &vattr, 0, kcred, NULL); if (error) { #ifdef CFSDEBUG CFS_DEBUG(CFSDEBUG_DLOG) printf("cachefs: map file getattr fail %d\n", error); #endif goto out; } fscp->fs_dmapoff = (off_t)vattr.va_size; fscp->fs_dmapsize = (off_t)vattr.va_size; }
STATIC int linvfs_mknod( struct inode *dir, struct dentry *dentry, int mode, int rdev) { struct inode *ip; vattr_t va; vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); xattr_exists_t test_default_acl = _ACL_DEFAULT_EXISTS; int have_default_acl = 0; int error = EINVAL; if (test_default_acl) have_default_acl = test_default_acl(dvp); #ifdef CONFIG_FS_POSIX_ACL /* * Conditionally compiled so that the ACL base kernel changes can be * split out into separate patches - remove this once MS_POSIXACL is * accepted, or some other way to implement this exists. */ if (IS_POSIXACL(dir) && !have_default_acl && has_fs_struct(current)) mode &= ~current->fs->umask; #endif bzero(&va, sizeof(va)); va.va_mask = AT_TYPE|AT_MODE; va.va_type = IFTOVT(mode); va.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: va.va_rdev = rdev; va.va_mask |= AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); break; case S_IFDIR: VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); break; default: error = EINVAL; break; } if (!error) { ASSERT(vp); ip = LINVFS_GET_IP(vp); if (!ip) { VN_RELE(vp); return -ENOMEM; } if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = to_kdev_t(rdev); /* linvfs_revalidate_core returns (-) errors */ error = -linvfs_revalidate_core(ip, ATTR_COMM); validate_fields(dir); d_instantiate(dentry, ip); mark_inode_dirty_sync(ip); mark_inode_dirty_sync(dir); } if (!error && have_default_acl) { _ACL_DECL (pdacl); if (!_ACL_ALLOC(pdacl)) { error = -ENOMEM; } else { if (_ACL_GET_DEFAULT(dvp, pdacl)) error = _ACL_INHERIT(vp, &va, pdacl); VMODIFY(vp); _ACL_FREE(pdacl); } } return -error; }
/* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. */ int vn_open(struct nameidata *ndp, int fmode, int cmode) { struct vnode *vp; struct proc *p = ndp->ni_cnd.cn_proc; struct ucred *cred = p->p_ucred; struct vattr va; int error; if ((fmode & (FREAD|FWRITE)) == 0) return (EINVAL); if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC) return (EINVAL); if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; if ((error = namei(ndp)) != 0) return (error); if (ndp->ni_vp == NULL) { VATTR_NULL(&va); va.va_type = VREG; va.va_mode = cmode; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); if (error) return (error); fmode &= ~O_TRUNC; vp = ndp->ni_vp; } else { VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else vput(ndp->ni_dvp); ndp->ni_dvp = NULL; vp = ndp->ni_vp; if (fmode & O_EXCL) { error = EEXIST; goto bad; } fmode &= ~O_CREAT; } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags = ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; } if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad; } if (vp->v_type == VLNK) { error = EMLINK; goto bad; } if ((fmode & O_CREAT) == 0) { if (fmode & FREAD) { if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) goto bad; } if (fmode & FWRITE) { if (vp->v_type == VDIR) { error = EISDIR; goto bad; } if ((error = vn_writechk(vp)) != 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) goto bad; } } if ((fmode & O_TRUNC) && vp->v_type == VREG) { VATTR_NULL(&va); va.va_size = 0; if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) goto bad; } if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0) goto bad; if (vp->v_flag & VCLONED) { struct cloneinfo *cip = (struct cloneinfo *) vp->v_data; vp->v_flag &= ~VCLONED; ndp->ni_vp = cip->ci_vp; /* return cloned vnode */ vp->v_data = cip->ci_data; /* restore v_data */ VOP_UNLOCK(vp, 0, p); /* keep a reference */ vp = ndp->ni_vp; /* for the increment below */ free(cip, M_TEMP); } if (fmode & FWRITE) vp->v_writecount++; return (0); bad: vput(vp); return (error); }
/* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. */ int vn_open(struct nameidata *ndp, int fmode, int cmode) { struct vnode *vp; struct lwp *l = curlwp; kauth_cred_t cred = l->l_cred; struct vattr va; int error; const char *pathstring; if ((fmode & (O_CREAT | O_DIRECTORY)) == (O_CREAT | O_DIRECTORY)) return EINVAL; ndp->ni_cnd.cn_flags &= TRYEMULROOT | NOCHROOT; if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF; if ((fmode & O_EXCL) == 0 && ((fmode & O_NOFOLLOW) == 0)) ndp->ni_cnd.cn_flags |= FOLLOW; } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags |= LOCKLEAF; if ((fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; } pathstring = pathbuf_stringcopy_get(ndp->ni_pathbuf); if (pathstring == NULL) { return ENOMEM; } error = namei(ndp); if (error) goto out; vp = ndp->ni_vp; #if NVERIEXEC > 0 error = veriexec_openchk(l, ndp->ni_vp, pathstring, fmode); if (error) goto bad; #endif /* NVERIEXEC > 0 */ if (fmode & O_CREAT) { if (ndp->ni_vp == NULL) { vattr_null(&va); va.va_type = VREG; va.va_mode = cmode; if (fmode & O_EXCL) va.va_vaflags |= VA_EXCLUSIVE; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); vput(ndp->ni_dvp); if (error) goto out; fmode &= ~O_TRUNC; vp = ndp->ni_vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); } else { VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else vput(ndp->ni_dvp); ndp->ni_dvp = NULL; vp = ndp->ni_vp; if (fmode & O_EXCL) { error = EEXIST; goto bad; } fmode &= ~O_CREAT; } } else { vp = ndp->ni_vp; } if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad; } if (ndp->ni_vp->v_type == VLNK) { error = EFTYPE; goto bad; } if ((fmode & O_CREAT) == 0) { error = vn_openchk(vp, cred, fmode); if (error != 0) goto bad; } if (fmode & O_TRUNC) { vattr_null(&va); va.va_size = 0; error = VOP_SETATTR(vp, &va, cred); if (error != 0) goto bad; } if ((error = VOP_OPEN(vp, fmode, cred)) != 0) goto bad; if (fmode & FWRITE) { mutex_enter(vp->v_interlock); vp->v_writecount++; mutex_exit(vp->v_interlock); } bad: if (error) vput(vp); out: pathbuf_stringcopy_put(ndp->ni_pathbuf, pathstring); return (error); }
STATIC int linvfs_mknod( struct inode *dir, struct dentry *dentry, int mode, int rdev) { struct inode *ip; vattr_t va; vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; if (!_ACL_GET_DEFAULT(dvp, default_acl)) { _ACL_FREE(default_acl); default_acl = NULL; } } #ifdef CONFIG_XFS_POSIX_ACL /* * Conditionally compiled so that the ACL base kernel changes can be * split out into separate patches - remove this once MS_POSIXACL is * accepted, or some other way to implement this exists. */ if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) mode &= ~current->fs->umask; #endif memset(&va, 0, sizeof(va)); va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; va.va_type = IFTOVT(mode); va.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: va.va_rdev = XFS_MKDEV(MAJOR(rdev), MINOR(rdev)); va.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); break; case S_IFDIR: VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); break; default: error = EINVAL; break; } if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); if (!error) { VMODIFY(vp); } else { struct dentry teardown = {}; int err2; /* Oh, the horror. * If we can't add the ACL we must back out. * ENOSPC can hit here, among other things. */ teardown.d_inode = ip = LINVFS_GET_IP(vp); teardown.d_name = dentry->d_name; vn_mark_bad(vp); if (S_ISDIR(mode)) VOP_RMDIR(dvp, &teardown, NULL, err2); else VOP_REMOVE(dvp, &teardown, NULL, err2); VN_RELE(vp); } } _ACL_FREE(default_acl); } if (!error) { ASSERT(vp); ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = to_kdev_t(rdev); else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); validate_fields(dir); } return -error; }
static int zfsfuse_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev) { if(strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *znode; int error = zfs_zget(zfsvfs, parent, &znode, B_FALSE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(znode != NULL); vnode_t *dvp = ZTOV(znode); ASSERT(dvp != NULL); cred_t cred; zfsfuse_getcred(req, &cred); vattr_t vattr; vattr.va_type = IFTOVT(mode); vattr.va_mode = mode & PERMMASK; vattr.va_mask = AT_TYPE | AT_MODE; if(mode & (S_IFCHR | S_IFBLK)) { vattr.va_rdev = rdev; vattr.va_mask |= AT_RDEV; } vnode_t *vp = NULL; /* FIXME: check filesystem boundaries */ error = VOP_CREATE(dvp, (char *) name, &vattr, EXCL, 0, &vp, &cred, 0, NULL, NULL); VN_RELE(dvp); if(error) goto out; ASSERT(vp != NULL); struct fuse_entry_param e = { 0 }; e.attr_timeout = 0.0; e.entry_timeout = 0.0; e.ino = VTOZ(vp)->z_id; if(e.ino == 3) e.ino = 1; e.generation = VTOZ(vp)->z_phys->zp_gen; error = zfsfuse_stat(vp, &e.attr, &cred); out: if(vp != NULL) VN_RELE(vp); ZFS_EXIT(zfsvfs); if(!error) fuse_reply_entry(req, &e); return error; }
static int zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) { char *name = NULL; /* location determined later */ char *link; /* symlink content follows name */ znode_t *dzp; vnode_t *vp = NULL; xvattr_t xva; int vflg = 0; size_t lrsize = sizeof (lr_create_t); lr_attr_t *lrattr; void *start; size_t xvatlen; uint64_t txtype; struct componentname cn; int error; txtype = (lr->lr_common.lrc_txtype & ~TX_CI); if (byteswap) { byteswap_uint64_array(lr, sizeof (*lr)); if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); } if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) return (error); xva_init(&xva); zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) * eventually end up in zfs_mknode(), which assigns the object's * creation time and generation number. The generic VOP_CREATE() * doesn't have either concept, so we smuggle the values inside * the vattr's otherwise unused va_ctime and va_nblocks fields. */ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); xva.xva_vattr.va_nblocks = lr->lr_gen; error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); if (error != ENOENT) goto out; if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; /* * Symlinks don't have fuid info, and CIFS never creates * symlinks. * * The _ATTR versions will grab the fuid info in their subcases. */ if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { start = (lr + 1); zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); } cn.cn_cred = kcred; cn.cn_thread = curthread; cn.cn_flags = SAVENAME; vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); switch (txtype) { case TX_CREATE_ATTR: lrattr = (lr_attr_t *)(caddr_t)(lr + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); start = (caddr_t)(lr + 1) + xvatlen; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); name = (char *)start; /*FALLTHROUGH*/ case TX_CREATE: if (name == NULL) name = (char *)start; cn.cn_nameptr = name; error = VOP_CREATE(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); break; case TX_MKDIR_ATTR: lrattr = (lr_attr_t *)(caddr_t)(lr + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); start = (caddr_t)(lr + 1) + xvatlen; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); name = (char *)start; /*FALLTHROUGH*/ case TX_MKDIR: if (name == NULL) name = (char *)(lr + 1); cn.cn_nameptr = name; error = VOP_MKDIR(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); break; case TX_MKXATTR: error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred); break; case TX_SYMLINK: name = (char *)(lr + 1); link = name + strlen(name) + 1; cn.cn_nameptr = name; error = VOP_SYMLINK(ZTOV(dzp), &vp, &cn, &xva.xva_vattr, link /*,vflg*/); break; default: error = ENOTSUP; } VOP_UNLOCK(ZTOV(dzp), 0); out: if (error == 0 && vp != NULL) VN_URELE(vp); VN_RELE(ZTOV(dzp)); if (zfsvfs->z_fuid_replay) zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; return (error); }
STATIC int linvfs_mknod( struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *ip; vattr_t va; vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; /* * Irix uses Missed'em'V split, but doesn't want to see * the upper 5 bits of (14bit) major. */ if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) return -EINVAL; if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; if (!_ACL_GET_DEFAULT(dvp, default_acl)) { _ACL_FREE(default_acl); default_acl = NULL; } } if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) mode &= ~current->fs->umask; memset(&va, 0, sizeof(va)); va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; va.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: va.va_rdev = sysv_encode_dev(rdev); va.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); break; case S_IFDIR: VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); break; default: error = EINVAL; break; } if (!error) { error = linvfs_init_security(vp, dir); if (error) cleanup_inode(dvp, vp, dentry, mode); } if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); if (!error) VMODIFY(vp); else cleanup_inode(dvp, vp, dentry, mode); } _ACL_FREE(default_acl); } if (!error) { ASSERT(vp); ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = rdev; else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); validate_fields(dir); } return -error; }