Example #1
0
struct dentry *lzfs_get_parent(struct dentry *child)
{
	vnode_t *vcp = LZFS_ITOV(child->d_inode);
	vnode_t *vp;
	int error = 0;
	struct dentry *dentry = NULL;
	const struct cred *cred = get_current_cred();

	SENTRY;
	error = zfs_lookup(vcp, "..", &vp, NULL, 0 , NULL,
			(struct cred *) cred, NULL, NULL, NULL);

	put_cred(cred);
	tsd_exit();
	SEXIT;
	if (error) {
		if (error == ENOENT) {
			printk(KERN_WARNING "Try to get new dentry \n");
			return d_splice_alias(NULL, dentry);
		} else {
			printk(KERN_WARNING "Unable to get dentry \n");
			return ERR_PTR(-error);
		}
	}

	if (LZFS_VTOI(vp))
		dentry = d_obtain_alias(LZFS_VTOI(vp));
	return dentry;
}
Example #2
0
File: zfs_ctldir.c Project: EW1/zfs
/* ARGSUSED */
int
zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
    int flags, cred_t *cr, int *direntflags, pathname_t *realpnp)
{
	zfs_sb_t *zsb = ITOZSB(dip);
	struct inode *ip;
	znode_t *dzp;
	int error;

	ZFS_ENTER(zsb);

	if (zsb->z_shares_dir == 0) {
		ZFS_EXIT(zsb);
		return (ENOTSUP);
	}

	error = zfs_zget(zsb, zsb->z_shares_dir, &dzp);
	if (error) {
		ZFS_EXIT(zsb);
		return (error);
	}

	error = zfs_lookup(ZTOI(dzp), name, &ip, 0, cr, NULL, NULL);

	iput(ZTOI(dzp));
	ZFS_EXIT(zsb);

	return (error);
}
Example #3
0
File: zpl_inode.c Project: dun/zfs
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
#endif
{
	cred_t *cr = CRED();
	struct inode *ip;
	int error;
	fstrans_cookie_t cookie;

	if (dlen(dentry) > ZFS_MAXNAMELEN)
		return (ERR_PTR(-ENAMETOOLONG));

	crhold(cr);
	cookie = spl_fstrans_mark();
	error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
	spl_fstrans_unmark(cookie);
	ASSERT3S(error, <=, 0);
	crfree(cr);

	spin_lock(&dentry->d_lock);
	dentry->d_time = jiffies;
#ifndef HAVE_S_D_OP
	d_set_d_op(dentry, &zpl_dentry_operations);
#endif /* HAVE_S_D_OP */
	spin_unlock(&dentry->d_lock);

	if (error) {
		if (error == -ENOENT)
			return (d_splice_alias(NULL, dentry));
		else
			return (ERR_PTR(error));
	}

	return (d_splice_alias(ip, dentry));
}
Example #4
0
static int
zpl_xattr_get_dir(struct inode *ip, const char *name, void *value,
    size_t size, cred_t *cr)
{
	struct inode *dxip = NULL;
	struct inode *xip = NULL;
	loff_t pos = 0;
	int error;

	/* Lookup the xattr directory */
	error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, 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)
		goto out;

	if (!size) {
		error = i_size_read(xip);
		goto out;
	}

	if (size < i_size_read(xip)) {
		error = -ERANGE;
		goto out;
	}

	error = zpl_read_common(xip, value, size, &pos, UIO_SYSSPACE, 0, cr);
out:
	if (xip)
		iput(xip);

	if (dxip)
		iput(dxip);

	return (error);
}
Example #5
0
static struct dentry *
zpl_get_parent(struct dentry *child)
{
	cred_t *cr = CRED();
	struct inode *ip;
	int error;

	crhold(cr);
	error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL);
	crfree(cr);
	ASSERT3S(error, <=, 0);

	if (error)
		return ERR_PTR(error);

	return zpl_dentry_obtain_alias(ip);
}
Example #6
0
static struct dentry *
zpl_get_parent(struct dentry *child)
{
	cred_t *cr = CRED();
	fstrans_cookie_t cookie;
	struct inode *ip;
	int error;

	crhold(cr);
	cookie = spl_fstrans_mark();
	error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL);
	spl_fstrans_unmark(cookie);
	crfree(cr);
	ASSERT3S(error, <=, 0);

	if (error)
		return (ERR_PTR(error));

	return (zpl_dentry_obtain_alias(ip));
}
Example #7
0
int
main(int argc, char** argv)
{
	int i, n, off;
	int fd[99];
	spa_t *spa;
	dnode_phys_t dn;
	char buf[512];

	zfs_init();
	if (argc == 1) {
		static char *av[] = {
			"zfstest", "/dev/da0p2", "/dev/da1p2", "/dev/da2p2",
			NULL,
		};
		argc = 4;
		argv = av;
	}
	for (i = 1; i < argc; i++) {
		fd[i] = open(argv[i], O_RDONLY);
		if (fd[i] < 0)
			continue;
		if (vdev_probe(vdev_read, &fd[i], NULL) != 0)
			close(fd[i]);
	}
	spa_all_status();

	spa = STAILQ_FIRST(&zfs_pools);
	if (!spa || zfs_mount_pool(spa))
		exit(1);

	if (zfs_lookup(spa, "zfs.c", &dn))
		exit(1);

	off = 0;
	do {
		n = zfs_read(spa, &dn, buf, 512, off);
		write(1, buf, n);
		off += n;
	} while (n == 512);
}
Example #8
0
static ssize_t
zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr)
{
	struct inode *ip = xf->inode;
	struct inode *dxip = NULL;
	int error;

	/* Lookup the xattr directory */
	error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
	if (error) {
		if (error == -ENOENT)
			error = 0;

		return (error);
	}

	error = zpl_xattr_readdir(dxip, xf);
	iput(dxip);

	return (error);
}
Example #9
0
static struct dentry *
zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	cred_t *cr = CRED();
	struct inode *ip;
	int error;

	crhold(cr);
	error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
	ASSERT3S(error, <=, 0);
	crfree(cr);

	if (error) {
		if (error == -ENOENT)
			return d_splice_alias(NULL, dentry);
		else
			return ERR_PTR(error);
	}

	return d_splice_alias(ip, dentry);
}
Example #10
0
static ssize_t
zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr)
{
	struct inode *ip = xf->inode;
	struct inode *dxip = NULL;
	int error;

	/* Lookup the xattr directory */
	error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
	if (error) {
		if (error == -ENOENT)
			error = 0;

		return (error);
	}

	/* Fill provided buffer via zpl_zattr_filldir helper */
	error = -zfs_readdir(dxip, (void *)xf, zpl_xattr_filldir, &pos, cr);
	VN_RELE(dxip);

	return (error);
}
Example #11
0
int
main(int argc, char** argv)
{
	char buf[512];
	int fd[100];
	struct stat sb;
	dnode_phys_t dn;
	spa_t *spa;
	off_t off;
	ssize_t n;
	int i;

	zfs_init();
	if (argc == 1) {
		static char *av[] = {
			"zfstest", "COPYRIGHT",
			"/dev/da0p2", "/dev/da1p2", "/dev/da2p2",
			NULL,
		};
		argc = 5;
		argv = av;
	}
	for (i = 2; i < argc; i++) {
		fd[i] = open(argv[i], O_RDONLY);
		if (fd[i] < 0)
			continue;
		if (vdev_probe(vdev_read, &fd[i], NULL) != 0)
			close(fd[i]);
	}
	spa_all_status();

	spa = STAILQ_FIRST(&zfs_pools);
	if (spa == NULL) {
		fprintf(stderr, "no pools\n");
		exit(1);
	}

	if (zfs_mount_pool(spa)) {
		fprintf(stderr, "can't mount pool\n");
		exit(1);
	}

	if (zfs_lookup(spa, argv[1], &dn)) {
		fprintf(stderr, "can't lookup\n");
		exit(1);
	}

	if (zfs_dnode_stat(spa, &dn, &sb)) {
		fprintf(stderr, "can't stat\n");
		exit(1);
	}


	off = 0;
	do {
		n = sb.st_size - off;
		n = n > sizeof(buf) ? sizeof(buf) : n;
		n = zfs_read(spa, &dn, buf, n, off);
		if (n < 0) {
			fprintf(stderr, "zfs_read failed\n");
			exit(1);
		}
		write(1, buf, n);
		off += n;
	} while (off < sb.st_size);

	return (0);
}
Example #12
0
static EFI_STATUS
load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
{
	spa_t *spa;
	struct zfsmount zfsmount;
	dnode_phys_t dn;
	struct stat st;
	int err;
	void *buf;
	EFI_STATUS status;

	spa = devinfo->devdata;

	DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
	    devpath_str(devinfo->devpath));

	if ((err = zfs_spa_init(spa)) != 0) {
		DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
		return (EFI_NOT_FOUND);
	}

	if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
		DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
		return (EFI_NOT_FOUND);
	}

	if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
		if (err == ENOENT) {
			DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
			    filepath, spa->spa_name, err);
			return (EFI_NOT_FOUND);
		}
		printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
		    spa->spa_name, err);
		return (EFI_INVALID_PARAMETER);
	}

	if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
		printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
		    spa->spa_name, err);
		return (EFI_INVALID_PARAMETER);
	}

	if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
	    != EFI_SUCCESS) {
		printf("Failed to allocate load buffer %zu for pool '%s' for '%s' "
		    "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
		return (EFI_INVALID_PARAMETER);
	}

	if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
		printf("Failed to read node from %s (%d)\n", spa->spa_name,
		    err);
		(void)bs->FreePool(buf);
		return (EFI_INVALID_PARAMETER);
	}

	*bufsize = st.st_size;
	*bufp = buf;

	return (EFI_SUCCESS);
}
Example #13
0
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,
};
Example #14
0
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);
}
Example #15
0
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
#endif
{
	cred_t *cr = CRED();
	struct inode *ip;
	int error;
	fstrans_cookie_t cookie;
	pathname_t *ppn = NULL;
	pathname_t pn;
	zfs_sb_t *zsb = dentry->d_sb->s_fs_info;

	if (dlen(dentry) > ZFS_MAXNAMELEN)
		return (ERR_PTR(-ENAMETOOLONG));

	crhold(cr);
	cookie = spl_fstrans_mark();

	/* If we are a case insensitive fs, we need the real name */
	if (zsb->z_case == ZFS_CASE_INSENSITIVE) {
		pn.pn_bufsize = ZFS_MAXNAMELEN;
		pn.pn_buf = kmem_zalloc(ZFS_MAXNAMELEN, KM_SLEEP);
		ppn = &pn;
	}

	error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, ppn);
	spl_fstrans_unmark(cookie);
	ASSERT3S(error, <=, 0);
	crfree(cr);

	spin_lock(&dentry->d_lock);
	dentry->d_time = jiffies;
#ifndef HAVE_S_D_OP
	d_set_d_op(dentry, &zpl_dentry_operations);
#endif /* HAVE_S_D_OP */
	spin_unlock(&dentry->d_lock);

	if (error) {
		if (ppn)
			kmem_free(pn.pn_buf, ZFS_MAXNAMELEN);
		if (error == -ENOENT)
			return (d_splice_alias(NULL, dentry));
		else
			return (ERR_PTR(error));
	}

	/*
	 * If we are case insensitive, call the correct function
	 * to install the name.
	 */
	if (ppn) {
		struct dentry *new_dentry;
		struct qstr ci_name;

		ci_name.name = pn.pn_buf;
		ci_name.len = strlen(pn.pn_buf);
		new_dentry = d_add_ci(dentry, ip, &ci_name);
		kmem_free(pn.pn_buf, ZFS_MAXNAMELEN);
		return (new_dentry);
	} else {
		return (d_splice_alias(ip, dentry));
	}
}
Example #16
0
int
main(int argc, char** argv)
{
	char buf[512], hash[33];
	MD5_CTX ctx;
	struct stat sb;
	struct zfsmount zfsmnt;
	dnode_phys_t dn;
#if 0
	uint64_t rootobj;
#endif
	spa_t *spa;
	off_t off;
	ssize_t n;
	int i, failures, *fd;

	zfs_init();
	if (argc == 1) {
		static char *av[] = {
			"zfsboottest",
			"/dev/gpt/system0",
			"/dev/gpt/system1",
			"-",
			"/boot/zfsloader",
			"/boot/support.4th",
			"/boot/kernel/kernel",
			NULL,
		};
		argc = sizeof(av) / sizeof(av[0]) - 1;
		argv = av;
	}
	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-") == 0)
			break;
	}
	fd = malloc(sizeof(fd[0]) * (i - 1));
	if (fd == NULL)
		errx(1, "Unable to allocate memory.");
	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-") == 0)
			break;
		fd[i - 1] = open(argv[i], O_RDONLY);
		if (fd[i - 1] == -1) {
			warn("open(%s) failed", argv[i]);
			continue;
		}
		if (vdev_probe(vdev_read, &fd[i - 1], NULL) != 0) {
			warnx("vdev_probe(%s) failed", argv[i]);
			close(fd[i - 1]);
		}
	}
	spa_all_status();

	spa = STAILQ_FIRST(&zfs_pools);
	if (spa == NULL) {
		fprintf(stderr, "no pools\n");
		exit(1);
	}

	if (zfs_spa_init(spa)) {
		fprintf(stderr, "can't init pool\n");
		exit(1);
	}

#if 0
	if (zfs_get_root(spa, &rootobj)) {
		fprintf(stderr, "can't get root\n");
		exit(1);
	}

	if (zfs_mount(spa, rootobj, &zfsmnt)) {
#else
	if (zfs_mount(spa, 0, &zfsmnt)) {
		fprintf(stderr, "can't mount\n");
		exit(1);
	}
#endif

	printf("\n");
	for (++i, failures = 0; i < argc; i++) {
		if (zfs_lookup(&zfsmnt, argv[i], &dn)) {
			fprintf(stderr, "%s: can't lookup\n", argv[i]);
			failures++;
			continue;
		}

		if (zfs_dnode_stat(spa, &dn, &sb)) {
			fprintf(stderr, "%s: can't stat\n", argv[i]);
			failures++;
			continue;
		}

		off = 0;
		MD5Init(&ctx);
		do {
			n = sb.st_size - off;
			n = n > sizeof(buf) ? sizeof(buf) : n;
			n = zfs_read(spa, &dn, buf, n, off);
			if (n < 0) {
				fprintf(stderr, "%s: zfs_read failed\n",
				    argv[i]);
				failures++;
				break;
			}
			MD5Update(&ctx, buf, n);
			off += n;
		} while (off < sb.st_size);
		if (off < sb.st_size)
			continue;
		MD5End(&ctx, hash);
		printf("%s %s\n", hash, argv[i]);
	}

	return (failures == 0 ? 0 : 1);
}
Example #17
0
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
#endif
{
	cred_t *cr = CRED();
	struct inode *ip;
	int error;
	fstrans_cookie_t cookie;
	pathname_t *ppn = NULL;
	pathname_t pn;
	int zfs_flags = 0;
	zfs_sb_t *zsb = dentry->d_sb->s_fs_info;

	if (dlen(dentry) > ZFS_MAX_DATASET_NAME_LEN)
		return (ERR_PTR(-ENAMETOOLONG));

	crhold(cr);
	cookie = spl_fstrans_mark();

	/* If we are a case insensitive fs, we need the real name */
	if (zsb->z_case == ZFS_CASE_INSENSITIVE) {
		zfs_flags = FIGNORECASE;
		pn_alloc(&pn);
		ppn = &pn;
	}

	error = -zfs_lookup(dir, dname(dentry), &ip, zfs_flags, cr, NULL, ppn);
	spl_fstrans_unmark(cookie);
	ASSERT3S(error, <=, 0);
	crfree(cr);

	spin_lock(&dentry->d_lock);
	dentry->d_time = jiffies;
#ifndef HAVE_S_D_OP
	d_set_d_op(dentry, &zpl_dentry_operations);
#endif /* HAVE_S_D_OP */
	spin_unlock(&dentry->d_lock);

	if (error) {
		/*
		 * If we have a case sensitive fs, we do not want to
		 * insert negative entries, so return NULL for ENOENT.
		 * Fall through if the error is not ENOENT. Also free memory.
		 */
		if (ppn) {
			pn_free(ppn);
			if (error == -ENOENT)
				return (NULL);
		}

		if (error == -ENOENT)
			return (d_splice_alias(NULL, dentry));
		else
			return (ERR_PTR(error));
	}

	/*
	 * If we are case insensitive, call the correct function
	 * to install the name.
	 */
	if (ppn) {
		struct dentry *new_dentry;
		struct qstr ci_name;

		ci_name.name = pn.pn_buf;
		ci_name.len = strlen(pn.pn_buf);
		new_dentry = d_add_ci(dentry, ip, &ci_name);
		pn_free(ppn);
		return (new_dentry);
	} else {
		return (d_splice_alias(ip, dentry));
	}
}
Example #18
0
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);
}