static int zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) { char *name = (char *)(lr + 1); /* name follows lr_remove_t */ znode_t *dzp; int error; int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) return (error); if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; switch ((int)lr->lr_common.lrc_txtype) { case TX_REMOVE: error = zfs_remove(ZTOI(dzp), name, kcred, vflg); break; case TX_RMDIR: error = zfs_rmdir(ZTOI(dzp), name, NULL, kcred, vflg); break; default: error = SET_ERROR(ENOTSUP); } iput(ZTOI(dzp)); return (error); }
static int zpl_unlink(struct inode *dir, struct dentry *dentry) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; zfs_sb_t *zsb = dentry->d_sb->s_fs_info; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_remove(dir, dname(dentry), cr, 0); /* * For a CI FS we must invalidate the dentry to prevent the * creation of negative entries. */ if (error == 0 && zsb->z_case == ZFS_CASE_INSENSITIVE) d_invalidate(dentry); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) { cred_t *cr = CRED(); vattr_t *vap; struct inode *ip; int error; fstrans_cookie_t cookie; crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr); cookie = spl_fstrans_mark(); error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0); if (error == 0) { d_instantiate(dentry, ip); error = zpl_xattr_security_init(ip, dir, &dentry->d_name); if (error) (void) zfs_remove(dir, dname(dentry), cr, 0); } spl_fstrans_unmark(cookie); kmem_free(vap, sizeof (vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
zpl_create(struct inode *dir, struct dentry *dentry, zpl_umode_t mode, bool flag) #endif { cred_t *cr = CRED(); struct inode *ip; vattr_t *vap; int error; fstrans_cookie_t cookie; crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, mode, cr); cookie = spl_fstrans_mark(); error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL); if (error == 0) { d_instantiate(dentry, ip); error = zpl_xattr_security_init(ip, dir, &dentry->d_name); if (error == 0) error = zpl_init_acl(ip, dir); if (error) (void) zfs_remove(dir, dname(dentry), cr, 0); } spl_fstrans_unmark(cookie); kmem_free(vap, sizeof (vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_unlink(struct inode *dir, struct dentry *dentry) { cred_t *cr = CRED(); int error; crhold(cr); error = -zfs_remove(dir, dname(dentry), cr); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_unlink(struct inode *dir, struct dentry *dentry) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_remove(dir, dname(dentry), cr); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode, dev_t rdev) { cred_t *cr = CRED(); struct inode *ip; vattr_t *vap; int error; fstrans_cookie_t cookie; /* * We currently expect Linux to supply rdev=0 for all sockets * and fifos, but we want to know if this behavior ever changes. */ if (S_ISSOCK(mode) || S_ISFIFO(mode)) ASSERT(rdev == 0); crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); zpl_vap_init(vap, dir, mode, cr); vap->va_rdev = rdev; cookie = spl_fstrans_mark(); error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL); if (error == 0) { d_instantiate(dentry, ip); error = zpl_xattr_security_init(ip, dir, &dentry->d_name); if (error == 0) error = zpl_init_acl(ip, dir); if (error) (void) zfs_remove(dir, dname(dentry), cr, 0); } spl_fstrans_unmark(cookie); kmem_free(vap, sizeof (vattr_t)); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
static int zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, size_t size, int flags, cred_t *cr) { struct inode *dxip = NULL; struct inode *xip = NULL; vattr_t *vap = NULL; ssize_t wrote; int lookup_flags, error; const int xattr_mode = S_IFREG | 0644; /* * Lookup the xattr directory. When we're adding an entry pass * CREATE_XATTR_DIR to ensure the xattr directory is created. * When removing an entry this flag is not passed to avoid * unnecessarily creating a new xattr directory. */ lookup_flags = LOOKUP_XATTR; if (value != NULL) lookup_flags |= CREATE_XATTR_DIR; error = -zfs_lookup(ip, NULL, &dxip, lookup_flags, cr, NULL, NULL); if (error) goto out; /* Lookup a specific xattr name in the directory */ error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL); if (error && (error != -ENOENT)) goto out; error = 0; /* Remove a specific name xattr when value is set to NULL. */ if (value == NULL) { if (xip) error = -zfs_remove(dxip, (char *)name, cr); goto out; } /* Lookup failed create a new xattr. */ if (xip == NULL) { vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); vap->va_mode = xattr_mode; vap->va_mask = ATTR_MODE; vap->va_uid = crgetfsuid(cr); vap->va_gid = crgetfsgid(cr); error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip, cr, 0, NULL); if (error) goto out; } ASSERT(xip != NULL); error = -zfs_freesp(ITOZ(xip), 0, 0, xattr_mode, TRUE); if (error) goto out; wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr); if (wrote < 0) error = wrote; out: if (vap) kmem_free(vap, sizeof(vattr_t)); if (xip) iput(xip); if (dxip) iput(dxip); if (error == -ENOENT) error = -ENODATA; ASSERT3S(error, <=, 0); return (error); }
static int zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, size_t size, int flags, cred_t *cr) { struct inode *dxip = NULL; struct inode *xip = NULL; vattr_t *vap = NULL; ssize_t wrote; int error; const int xattr_mode = S_IFREG | 0644; /* Lookup the xattr directory and create it if required. */ error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR | CREATE_XATTR_DIR, cr, NULL, NULL); if (error) goto out; /* Lookup a specific xattr name in the directory */ error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL); if (error && (error != -ENOENT)) goto out; error = 0; /* Remove a specific name xattr when value is set to NULL. */ if (value == NULL) { if (xip) error = -zfs_remove(dxip, (char *)name, cr); goto out; } /* Lookup failed create a new xattr. */ if (xip == NULL) { vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); vap->va_mode = xattr_mode; vap->va_mask = ATTR_MODE; vap->va_uid = crgetfsuid(cr); vap->va_gid = crgetfsgid(cr); error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip, cr, 0, NULL); if (error) goto out; } ASSERT(xip != NULL); error = -zfs_freesp(ITOZ(xip), 0, 0, xattr_mode, TRUE); if (error) goto out; wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr); if (wrote < 0) error = wrote; out: if (vap) kmem_free(vap, sizeof(vattr_t)); if (xip) VN_RELE(xip); if (dxip) VN_RELE(dxip); if (error == -ENOENT) error = -ENODATA; ASSERT3S(error, <=, 0); return (error); }
static int lzfs_xattr_security_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) #endif { vnode_t *vp; vnode_t *dvp; vnode_t *xvp; vattr_t *vap; int err = 0; const struct cred *cred = get_current_cred(); struct iovec iov = { .iov_base = (void *) value, .iov_len = size, }; char *xattr_name = NULL; uio_t uio = { .uio_iov = &iov, .uio_resid = size, .uio_iovcnt = 1, .uio_loffset = (offset_t)0, .uio_limit = MAXOFFSET_T, .uio_segflg = UIO_SYSSPACE, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(inode); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(dentry->d_inode); #endif err = zfs_lookup(dvp, NULL, &vp, NULL, LOOKUP_XATTR | CREATE_XATTR_DIR, NULL, (struct cred *) cred, NULL, NULL, NULL); if(err) { return -err; } if(!value) { err =zfs_remove(vp, (char *) name, (struct cred *)cred, NULL, 0); return -err; } vap = kmalloc(sizeof(vattr_t), GFP_KERNEL); ASSERT(vap != NULL); memset(vap, 0, sizeof(vap)); vap->va_type = VREG; vap->va_mode = 0644; vap->va_mask = AT_TYPE|AT_MODE; vap->va_uid = current_fsuid(); vap->va_gid = current_fsgid(); xattr_name = kzalloc(strlen(name) + 10, GFP_KERNEL); xattr_name = strncpy(xattr_name, "security.", 9); xattr_name = strncat(xattr_name, name, strlen(name)); err = zfs_create(vp, xattr_name, vap, 0, 0644, &xvp, (struct cred *)cred, 0, NULL, NULL); kfree(vap); kfree(xattr_name); if(err) { return -err; } err = zfs_write(xvp, &uio, 0, (cred_t *)cred, NULL); put_cred(cred); if(err) { return -err; } return -err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct inode *inode, char *list, size_t list_size, const char *name, size_t name_len) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) #endif { const size_t total_len = name_len + 1; if (list && total_len <= list_size) { memcpy(list, name, name_len); list[name_len] = '\0'; } return total_len; } int lzfs_init_security(struct dentry *dentry, struct inode *dir) { int err; size_t len; void *value; char *name; err = security_inode_init_security(dentry->d_inode, dir, &name, &value, &len); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry->d_inode, name, value, len, 0); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry, name, value, len, 0, 0); #endif kfree(name); kfree(value); return err; } struct xattr_handler lzfs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .list = lzfs_xattr_security_list, .get = lzfs_xattr_security_get, .set = lzfs_xattr_security_set, };