]> granicus.if.org Git - zfs/commitdiff
Add pn_alloc()/pn_free() functions
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 13 Apr 2016 15:55:35 +0000 (08:55 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 21 Apr 2016 16:49:25 +0000 (09:49 -0700)
In order to remove the HAVE_PN_UTILS wrappers the pn_alloc() and
pn_free() functions must be implemented.  The existing illumos
implementation were used for this purpose.

The `flags` argument which was used in places wrapped by the
HAVE_PN_UTILS condition has beed added back to zfs_remove() and
zfs_link() functions.  This removes a small point of divergence
between the ZoL code and upstream.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4522

include/sys/Makefile.am
include/sys/pathname.h [new file with mode: 0644]
include/sys/zfs_vnops.h
lib/libzpool/Makefile.am
module/zfs/Makefile.in
module/zfs/pathname.c [new file with mode: 0644]
module/zfs/zfs_replay.c
module/zfs/zfs_vnops.c
module/zfs/zpl_inode.c
module/zfs/zpl_xattr.c

index 73e86d03bb38bc4986d9e462ce9f3e35d648a184..98d7ad6fb061f5416476fe7b97e45edc2c291ba7 100644 (file)
@@ -38,6 +38,7 @@ COMMON_H = \
        $(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 \
diff --git a/include/sys/pathname.h b/include/sys/pathname.h
new file mode 100644 (file)
index 0000000..5db69b1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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 */
index c331035c544a71475912be9d4beb36a75356b922..157e7f9d5ec68395b4dfb032a3393847bf530782 100644 (file)
@@ -47,7 +47,7 @@ extern int zfs_lookup(struct inode *dip, char *nm, struct inode **ipp,
     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,
@@ -64,7 +64,7 @@ extern int zfs_symlink(struct inode *dip, char *name, vattr_t *vap,
 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);
index f45a57d71fdf2c10729ad4adc389376f4faf2b8a..3e59efa5c4b1b00ef6a3b0c50b4d7f98851ba295 100644 (file)
@@ -64,6 +64,7 @@ KERNEL_C = \
        lz4.c \
        metaslab.c \
        multilist.c \
+       pathname.c \
        range_tree.c \
        refcount.c \
        rrwlock.c \
index d3a0206c9f7a9bd9b9c10958c68469740ff8c505..f33faf157cc8e80716109f132531dbf83ddaba2a 100644 (file)
@@ -42,6 +42,7 @@ $(MODULE)-objs += lzjb.o
 $(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
diff --git a/module/zfs/pathname.c b/module/zfs/pathname.c
new file mode 100644 (file)
index 0000000..4ec1320
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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;
+}
index 0ca1e03b595bc4dac27494d2ca8d764b798ad598..b97a60ed8a1d5deb876e1cb87c3aea9b3dd91565 100644 (file)
@@ -548,7 +548,7 @@ zfs_replay_remove(zfs_sb_t *zsb, lr_remove_t *lr, boolean_t byteswap)
 
        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);
@@ -584,7 +584,7 @@ zfs_replay_link(zfs_sb_t *zsb, lr_link_t *lr, boolean_t byteswap)
        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));
index 3c3d587e8addbbecda3bc7cb5c20d809aa76582b..7a8cef017a876fb5d2ef6bb245a650d6f6e44f2a 100644 (file)
@@ -1512,7 +1512,7 @@ uint64_t null_xattr = 0;
 
 /*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;
@@ -1528,9 +1528,7 @@ zfs_remove(struct inode *dip, char *name, cred_t *cr)
        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;
@@ -1539,13 +1537,11 @@ zfs_remove(struct inode *dip, char *name, cred_t *cr)
        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;
@@ -1555,10 +1551,8 @@ top:
         */
        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);
        }
@@ -1642,10 +1636,8 @@ top:
                        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);
@@ -1711,18 +1703,14 @@ top:
        }
 
        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);
@@ -3782,7 +3770,8 @@ EXPORT_SYMBOL(zfs_readlink);
  */
 /* 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;
@@ -3840,10 +3829,8 @@ zfs_link(struct inode *tdip, struct inode *sip, char *name, cred_t *cr)
                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
@@ -3900,10 +3887,8 @@ top:
 
        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);
        }
 
index 7cf62783facbcf50f547e025b760ed56321d31ba..089e3a1bcc97fad60ed3d4c869bb29e27e70d213 100644 (file)
@@ -59,8 +59,7 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
        /* 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;
        }
 
@@ -83,7 +82,7 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
                 * 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);
                }
@@ -105,7 +104,7 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
                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));
@@ -157,7 +156,7 @@ zpl_create(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
                        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);
@@ -200,7 +199,7 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
                        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);
@@ -221,7 +220,7 @@ zpl_unlink(struct inode *dir, struct dentry *dentry)
 
        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
@@ -389,7 +388,7 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
 
                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);
@@ -537,7 +536,7 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
        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;
index 420091953e20fdbba02c05547f7f747be4ecdbe9..e8623384c7d70ac6cc1cab9a20dee8af5fcb3f39 100644 (file)
@@ -465,7 +465,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
        /* 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;
        }