/* * union_mkdir(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnp, struct vattr *a_vap) */ static int union_mkdir(struct vop_old_mkdir_args *ap) { struct union_node *dun = VTOUNION(ap->a_dvp); struct componentname *cnp = ap->a_cnp; struct thread *td = cnp->cn_td; struct vnode *upperdvp; int error = EROFS; if ((upperdvp = union_lock_upper(dun, td)) != NULLVP) { struct vnode *vp; error = VOP_MKDIR(upperdvp, &vp, cnp, ap->a_vap); union_unlock_upper(upperdvp, td); if (error == 0) { vn_unlock(vp); UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_sysref.refcnt)); error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1); UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_sysref.refcnt)); } } return (error); }
int smb_vop_mkdir(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_MKDIR(dvp, np, vap, vpp, cr, &smb_ct, option_flags, vsap); return (error); }
int RUMP_VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { int error; rump_schedule(); error = VOP_MKDIR(dvp, vpp, cnp, vap); rump_unschedule(); return error; }
/* * Does most of the work for mkdir. */ int vfs_mkdir(char *path) { struct vnode *parent; char name[NAME_MAX+1]; int result; result = vfs_lookparent(path, &parent, name, sizeof(name)); if (result) { return result; } result = VOP_MKDIR(parent, name); VOP_DECREF(parent); return result; }
static int unionfs_mkdir(void *v) { struct vop_mkdir_args *ap = v; int error; struct unionfs_node *dunp; struct componentname *cnp; struct vnode *udvp; struct vnode *uvp; struct vattr va; UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n"); error = EROFS; dunp = VTOUNIONFS(ap->a_dvp); cnp = ap->a_cnp; udvp = dunp->un_uppervp; if (udvp != NULLVP) { /* check opaque */ if (!(cnp->cn_flags & ISWHITEOUT)) { error = VOP_GETATTR(udvp, &va, cnp->cn_cred); if (error != 0) return (error); if (va.va_flags & OPAQUE) cnp->cn_flags |= ISWHITEOUT; } if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, ap->a_dvp, ap->a_vpp, cnp); if (error) { vput(uvp); } else { vrele(uvp); } } } UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error); return (error); }
static void prof_getattr(struct sdev_node *dir, char *name, struct vnode *gdv, struct vattr *vap, struct vnode **avpp, int *no_fs_perm) { struct vnode *advp; /* get attribute from shadow, if present; else get default */ advp = dir->sdev_attrvp; if (advp && VOP_LOOKUP(advp, name, avpp, NULL, 0, NULL, kcred, NULL, NULL, NULL) == 0) { (void) VOP_GETATTR(*avpp, vap, 0, kcred, NULL); } else if (gdv == NULL || gdv->v_type == VDIR) { /* always create shadow directory */ *vap = sdev_vattr_dir; if (advp && VOP_MKDIR(advp, name, &sdev_vattr_dir, avpp, kcred, NULL, 0, NULL) != 0) { *avpp = NULLVP; sdcmn_err10(("prof_getattr: failed to create " "shadow directory %s/%s\n", dir->sdev_path, name)); } } else { /* * get default permission from devfs * Before calling devfs_get_defattr, we need to get * the realvp (the dv_node). If realvp is not a dv_node, * devfs_get_defattr() will return a system-wide default * attr for device nodes. */ struct vnode *rvp; if (VOP_REALVP(gdv, &rvp, NULL) != 0) rvp = gdv; devfs_get_defattr(rvp, vap, no_fs_perm); *avpp = NULLVP; } /* ignore dev_t and vtype from backing store */ if (gdv) { vap->va_type = gdv->v_type; vap->va_rdev = gdv->v_rdev; } }
static int auto_mkdir( vnode_t *dvp, char *nm, vattr_t *va, vnode_t **vpp, cred_t *cred, caller_context_t *ct, int flags, vsecattr_t *vsecp) { vnode_t *newvp; int error; AUTOFS_DPRINT((4, "auto_mkdir 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_MKDIR(newvp, nm, va, vpp, cred, ct, flags, vsecp); VN_RELE(newvp); } else error = ENOSYS; done: AUTOFS_DPRINT((5, "auto_mkdir: error=%d\n", error)); 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); }
/* * 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); }
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_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode) { 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); vnode_t *vp = NULL; vattr_t vattr = { 0 }; vattr.va_type = VDIR; vattr.va_mode = mode & PERMMASK; vattr.va_mask = AT_TYPE | AT_MODE; cred_t cred; zfsfuse_getcred(req, &cred); error = VOP_MKDIR(dvp, (char *) name, &vattr, &vp, &cred, NULL, 0, NULL); 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); VN_RELE(dvp); ZFS_EXIT(zfsvfs); if(!error) fuse_reply_entry(req, &e); 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); 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; }
/* * 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); }
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; }