$(top_srcdir)/include/sys/multilist.h \
$(top_srcdir)/include/sys/nvpair.h \
$(top_srcdir)/include/sys/nvpair_impl.h \
+ $(top_srcdir)/include/sys/pathname.h \
$(top_srcdir)/include/sys/range_tree.h \
$(top_srcdir)/include/sys/refcount.h \
$(top_srcdir)/include/sys/rrwlock.h \
--- /dev/null
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * Portions of this source code were derived from Berkeley 4.3 BSD
+ * under license from the Regents of the University of California.
+ */
+
+#ifndef _SYS_PATHNAME_H
+#define _SYS_PATHNAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Pathname structure.
+ * System calls that operate on path names gather the path name
+ * from the system call into this structure and reduce it by
+ * peeling off translated components. If a symbolic link is
+ * encountered the new path name to be translated is also
+ * assembled in this structure.
+ *
+ * By convention pn_buf is not changed once it's been set to point
+ * to the underlying storage; routines which manipulate the pathname
+ * do so by changing pn_path and pn_pathlen. pn_pathlen is redundant
+ * since the path name is null-terminated, but is provided to make
+ * some computations faster.
+ */
+typedef struct pathname {
+ char *pn_buf; /* underlying storage */
+ char *pn_path; /* remaining pathname */
+ size_t pn_pathlen; /* remaining length */
+ size_t pn_bufsize; /* total size of pn_buf */
+} pathname_t;
+
+extern void pn_alloc(struct pathname *);
+extern void pn_alloc_sz(struct pathname *, size_t);
+extern void pn_free(struct pathname *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_PATHNAME_H */
int flags, cred_t *cr, int *direntflags, pathname_t *realpnp);
extern int zfs_create(struct inode *dip, char *name, vattr_t *vap, int excl,
int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp);
-extern int zfs_remove(struct inode *dip, char *name, cred_t *cr);
+extern int zfs_remove(struct inode *dip, char *name, cred_t *cr, int flags);
extern int zfs_mkdir(struct inode *dip, char *dirname, vattr_t *vap,
struct inode **ipp, cred_t *cr, int flags, vsecattr_t *vsecp);
extern int zfs_rmdir(struct inode *dip, char *name, struct inode *cwd,
extern int zfs_follow_link(struct dentry *dentry, struct nameidata *nd);
extern int zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr);
extern int zfs_link(struct inode *tdip, struct inode *sip,
- char *name, cred_t *cr);
+ char *name, cred_t *cr, int flags);
extern void zfs_inactive(struct inode *ip);
extern int zfs_space(struct inode *ip, int cmd, flock64_t *bfp, int flag,
offset_t offset, cred_t *cr);
lz4.c \
metaslab.c \
multilist.c \
+ pathname.c \
range_tree.c \
refcount.c \
rrwlock.c \
$(MODULE)-objs += lz4.o
$(MODULE)-objs += metaslab.o
$(MODULE)-objs += multilist.o
+$(MODULE)-objs += pathname.o
$(MODULE)-objs += range_tree.o
$(MODULE)-objs += refcount.o
$(MODULE)-objs += rrwlock.o
--- /dev/null
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/pathname.h>
+#include <sys/kmem.h>
+
+/*
+ * Pathname utilities.
+ *
+ * In translating file names we copy each argument file
+ * name into a pathname structure where we operate on it.
+ * Each pathname structure can hold "pn_bufsize" characters
+ * including a terminating null, and operations here support
+ * allocating and freeing pathname structures, fetching
+ * strings from user space, getting the next character from
+ * a pathname, combining two pathnames (used in symbolic
+ * link processing), and peeling off the first component
+ * of a pathname.
+ */
+
+/*
+ * Allocate contents of pathname structure. Structure is typically
+ * an automatic variable in calling routine for convenience.
+ *
+ * May sleep in the call to kmem_alloc() and so must not be called
+ * from interrupt level.
+ */
+void
+pn_alloc(struct pathname *pnp)
+{
+ pn_alloc_sz(pnp, MAXPATHLEN);
+}
+void
+pn_alloc_sz(struct pathname *pnp, size_t sz)
+{
+ pnp->pn_path = pnp->pn_buf = kmem_alloc(sz, KM_SLEEP);
+ pnp->pn_pathlen = 0;
+ pnp->pn_bufsize = sz;
+}
+
+/*
+ * Free pathname resources.
+ */
+void
+pn_free(struct pathname *pnp)
+{
+ /* pn_bufsize is usually MAXPATHLEN, but may not be */
+ kmem_free(pnp->pn_buf, pnp->pn_bufsize);
+ pnp->pn_path = pnp->pn_buf = NULL;
+ pnp->pn_pathlen = pnp->pn_bufsize = 0;
+}
switch ((int)lr->lr_common.lrc_txtype) {
case TX_REMOVE:
- error = zfs_remove(ZTOI(dzp), name, kcred);
+ error = zfs_remove(ZTOI(dzp), name, kcred, vflg);
break;
case TX_RMDIR:
error = zfs_rmdir(ZTOI(dzp), name, NULL, kcred, vflg);
if (lr->lr_common.lrc_txtype & TX_CI)
vflg |= FIGNORECASE;
- error = zfs_link(ZTOI(dzp), ZTOI(zp), name, kcred);
+ error = zfs_link(ZTOI(dzp), ZTOI(zp), name, kcred, vflg);
iput(ZTOI(zp));
iput(ZTOI(dzp));
/*ARGSUSED*/
int
-zfs_remove(struct inode *dip, char *name, cred_t *cr)
+zfs_remove(struct inode *dip, char *name, cred_t *cr, int flags)
{
znode_t *zp, *dzp = ITOZ(dip);
znode_t *xzp;
boolean_t unlinked, toobig = FALSE;
uint64_t txtype;
pathname_t *realnmp = NULL;
-#ifdef HAVE_PN_UTILS
pathname_t realnm;
-#endif /* HAVE_PN_UTILS */
int error;
int zflg = ZEXISTS;
boolean_t waited = B_FALSE;
ZFS_VERIFY_ZP(dzp);
zilog = zsb->z_log;
-#ifdef HAVE_PN_UTILS
if (flags & FIGNORECASE) {
zflg |= ZCILOOK;
pn_alloc(&realnm);
realnmp = &realnm;
}
-#endif /* HAVE_PN_UTILS */
top:
xattr_obj = 0;
*/
if ((error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
NULL, realnmp))) {
-#ifdef HAVE_PN_UTILS
if (realnmp)
pn_free(realnmp);
-#endif /* HAVE_PN_UTILS */
ZFS_EXIT(zsb);
return (error);
}
dmu_tx_abort(tx);
goto top;
}
-#ifdef HAVE_PN_UTILS
if (realnmp)
pn_free(realnmp);
-#endif /* HAVE_PN_UTILS */
dmu_tx_abort(tx);
ZFS_EXIT(zsb);
return (error);
}
txtype = TX_REMOVE;
-#ifdef HAVE_PN_UTILS
if (flags & FIGNORECASE)
txtype |= TX_CI;
-#endif /* HAVE_PN_UTILS */
zfs_log_remove(zilog, tx, txtype, dzp, name, obj);
dmu_tx_commit(tx);
out:
-#ifdef HAVE_PN_UTILS
if (realnmp)
pn_free(realnmp);
-#endif /* HAVE_PN_UTILS */
zfs_dirent_unlock(dl);
zfs_inode_update(dzp);
*/
/* ARGSUSED */
int
-zfs_link(struct inode *tdip, struct inode *sip, char *name, cred_t *cr)
+zfs_link(struct inode *tdip, struct inode *sip, char *name, cred_t *cr,
+ int flags)
{
znode_t *dzp = ITOZ(tdip);
znode_t *tzp, *szp;
ZFS_EXIT(zsb);
return (SET_ERROR(EILSEQ));
}
-#ifdef HAVE_PN_UTILS
if (flags & FIGNORECASE)
zf |= ZCILOOK;
-#endif /* HAVE_PN_UTILS */
/*
* We do not support links between attributes and non-attributes
if (error == 0) {
uint64_t txtype = TX_LINK;
-#ifdef HAVE_PN_UTILS
if (flags & FIGNORECASE)
txtype |= TX_CI;
-#endif /* HAVE_PN_UTILS */
zfs_log_link(zilog, tx, txtype, dzp, szp, name);
}
/* If we are a case insensitive fs, we need the real name */
if (zsb->z_case == ZFS_CASE_INSENSITIVE) {
zfs_flags = FIGNORECASE;
- pn.pn_bufsize = ZFS_MAXNAMELEN;
- pn.pn_buf = kmem_zalloc(ZFS_MAXNAMELEN, KM_SLEEP);
+ pn_alloc(&pn);
ppn = &pn;
}
* Fall through if the error is not ENOENT. Also free memory.
*/
if (ppn) {
- kmem_free(pn.pn_buf, ZFS_MAXNAMELEN);
+ pn_free(ppn);
if (error == -ENOENT)
return (NULL);
}
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);
+ pn_free(ppn);
return (new_dentry);
} else {
return (d_splice_alias(ip, dentry));
error = zpl_init_acl(ip, dir);
if (error)
- (void) zfs_remove(dir, dname(dentry), cr);
+ (void) zfs_remove(dir, dname(dentry), cr, 0);
}
spl_fstrans_unmark(cookie);
error = zpl_init_acl(ip, dir);
if (error)
- (void) zfs_remove(dir, dname(dentry), cr);
+ (void) zfs_remove(dir, dname(dentry), cr, 0);
}
spl_fstrans_unmark(cookie);
crhold(cr);
cookie = spl_fstrans_mark();
- error = -zfs_remove(dir, dname(dentry), cr);
+ error = -zfs_remove(dir, dname(dentry), cr, 0);
/*
* For a CI FS we must invalidate the dentry to prevent the
error = zpl_xattr_security_init(ip, dir, &dentry->d_name);
if (error)
- (void) zfs_remove(dir, dname(dentry), cr);
+ (void) zfs_remove(dir, dname(dentry), cr, 0);
}
spl_fstrans_unmark(cookie);
igrab(ip); /* Use ihold() if available */
cookie = spl_fstrans_mark();
- error = -zfs_link(dir, ip, dname(dentry), cr);
+ error = -zfs_link(dir, ip, dname(dentry), cr, 0);
if (error) {
iput(ip);
goto out;
/* Remove a specific name xattr when value is set to NULL. */
if (value == NULL) {
if (xip)
- error = -zfs_remove(dxip, (char *)name, cr);
+ error = -zfs_remove(dxip, (char *)name, cr, 0);
goto out;
}