usr/src/uts/common/fs/zfs/zfs_dir.c
author eschrock
Tue, 05 Sep 2006 11:37:36 -0700
changeset 2676 5cee47eddab6
parent 2597 21c0f93f2513
child 3280 e93ccc27c51d
permissions -rw-r--r--
PSARC 2006/486 ZFS canmount property PSARC 2006/497 ZFS create time properties PSARC 2006/502 ZFS get all datasets PSARC 2006/504 ZFS user properties 6269805 properties should be set via an nvlist. 6281585 user defined properties 6349494 'zfs list' output annoying for even moderately long dataset names 6366244 'canmount' option for container-like functionality 6367103 create-time properties 6416639 RFE: provide zfs get -a 6437808 ZFS module version should match on-disk version 6454551 'zfs create -b blocksize filesystem' should fail. 6457478 unrecognized character in error message with 'zpool create -R' command 6457865 missing device name in the error message of 'zpool clear' command 6458571 zfs_ioc_set_prop() doesn't validate input 6458614 zfs ACL #defines should use prefix 6458638 get_configs() accesses bogus memory 6458678 zvol functions should be moved out of zfs_ioctl.h 6458683 zfs_cmd_t could use more cleanup 6458691 common routines to manage zfs_cmd_t nvlists 6460398 zpool import cores on zfs_prop_get 6461029 zpool status -x noexisting-pool has incorrect error message. 6461223 index translations should live with property definitions 6461424 zpool_unmount_datasets() has some busted logic 6461427 zfs_realloc() would be useful 6461757 'zpool status' can report the wrong number of persistent errors 6461784 recursive zfs_snapshot() leaks memory
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
     5
 * Common Development and Distribution License (the "License").
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
/*
1231
64215f768e86 6354804 The file's ACL was changed when cp it from one ZFS file system to another one.
marks
parents: 885
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
#include <sys/types.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/param.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/time.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/systm.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/sysmacros.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/resource.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/vfs.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
#include <sys/vnode.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
#include <sys/file.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
#include <sys/mode.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
#include <sys/kmem.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
#include <sys/uio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
#include <sys/pathname.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
#include <sys/cmn_err.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
#include <sys/errno.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
#include <sys/stat.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
#include <sys/unistd.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
#include <sys/random.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
#include <sys/policy.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
#include <sys/zfs_dir.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
#include <sys/zfs_acl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
#include <sys/fs/zfs.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
#include "fs/fs_subr.h"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
#include <sys/zap.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
#include <sys/atomic.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
#include <sys/zfs_ctldir.h>
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
    55
#include <sys/dnlc.h>
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
 * Lock a directory entry.  A dirlock on <dzp, name> protects that name
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
 * in dzp's directory zap object.  As long as you hold a dirlock, you can
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
 * assume two things: (1) dzp cannot be reaped, and (2) no other thread
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
 * can change the zap entry for (i.e. link or unlink) this name.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
 * Input arguments:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
 *	dzp	- znode for directory
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
 *	name	- name of entry to lock
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
 *	flag	- ZNEW: if the entry already exists, fail with EEXIST.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
 *		  ZEXISTS: if the entry does not exist, fail with ENOENT.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
 *		  ZSHARED: allow concurrent access with other ZSHARED callers.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
 *		  ZXATTR: we want dzp's xattr directory
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
 * Output arguments:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
 *	zpp	- pointer to the znode for the entry (NULL if there isn't one)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
 *	dlpp	- pointer to the dirlock for this entry (NULL on error)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
 * Return value: 0 on success or errno on failure.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
 * NOTE: Always checks for, and rejects, '.' and '..'.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
	int flag)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	zfs_dirlock_t	*dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
	uint64_t	zoid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
	int		error;
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
    87
	vnode_t		*vp;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	*zpp = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
	*dlpp = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
	 * Verify that we are not trying to lock '.', '..', or '.zfs'
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
	if (name[0] == '.' &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
	    (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
	    zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
		return (EEXIST);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
	 * Wait until there are no locks on this name.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
	mutex_enter(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
	for (;;) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
		if (dzp->z_reap) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
			mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
			return (ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
		for (dl = dzp->z_dirlocks; dl != NULL; dl = dl->dl_next)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
			if (strcmp(name, dl->dl_name) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
		if (dl == NULL)	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
			 * Allocate a new dirlock and add it to the list.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
			dl = kmem_alloc(sizeof (zfs_dirlock_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
			cv_init(&dl->dl_cv, NULL, CV_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
			dl->dl_name = name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
			dl->dl_sharecnt = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
			dl->dl_namesize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
			dl->dl_dzp = dzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
			dl->dl_next = dzp->z_dirlocks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
			dzp->z_dirlocks = dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
		if ((flag & ZSHARED) && dl->dl_sharecnt != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
		cv_wait(&dl->dl_cv, &dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
	if ((flag & ZSHARED) && ++dl->dl_sharecnt > 1 && dl->dl_namesize == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
		 * We're the second shared reference to dl.  Make a copy of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
		 * dl_name in case the first thread goes away before we do.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
		 * Note that we initialize the new name before storing its
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
		 * pointer into dl_name, because the first thread may load
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
		 * dl->dl_name at any time.  He'll either see the old value,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
		 * which is his, or the new shared copy; either is OK.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
		dl->dl_namesize = strlen(dl->dl_name) + 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
		name = kmem_alloc(dl->dl_namesize, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
		bcopy(dl->dl_name, name, dl->dl_namesize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
		dl->dl_name = name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
	mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	 * We have a dirlock on the name.  (Note that it is the dirlock,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	 * not the dzp's z_lock, that protects the name in the zap object.)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
	 * See if there's an object by this name; if so, put a hold on it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
	if (flag & ZXATTR) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
		zoid = dzp->z_phys->zp_xattr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
		error = (zoid == 0 ? ENOENT : 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	} else {
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   157
		vp = dnlc_lookup(ZTOV(dzp), name);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   158
		if (vp == DNLC_NO_VNODE) {
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   159
			VN_RELE(vp);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   160
			error = ENOENT;
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   161
		} else if (vp) {
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   162
			if (flag & ZNEW) {
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   163
				zfs_dirent_unlock(dl);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   164
				VN_RELE(vp);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   165
				return (EEXIST);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   166
			}
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   167
			*dlpp = dl;
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   168
			*zpp = VTOZ(vp);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   169
			return (0);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   170
		} else {
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   171
			error = zap_lookup(zfsvfs->z_os, dzp->z_id, name,
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   172
			    8, 1, &zoid);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   173
			if (error == ENOENT)
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   174
				dnlc_update(ZTOV(dzp), name, DNLC_NO_VNODE);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   175
		}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
	if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
		if (error != ENOENT || (flag & ZEXISTS)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
			zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
			return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
		if (flag & ZNEW) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
			zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
			return (EEXIST);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
		error = zfs_zget(zfsvfs, zoid, zpp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
		if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
			zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
			return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
		}
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   192
		if (!(flag & ZXATTR))
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   193
			dnlc_update(ZTOV(dzp), name, ZTOV(*zpp));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	*dlpp = dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
 * Unlock this directory entry and wake anyone who was waiting for it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
zfs_dirent_unlock(zfs_dirlock_t *dl)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
	znode_t *dzp = dl->dl_dzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
	zfs_dirlock_t **prev_dl, *cur_dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
	mutex_enter(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
	if (dl->dl_sharecnt > 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
		dl->dl_sharecnt--;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
		mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
	prev_dl = &dzp->z_dirlocks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	while ((cur_dl = *prev_dl) != dl)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
		prev_dl = &cur_dl->dl_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	*prev_dl = dl->dl_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
	cv_broadcast(&dl->dl_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
	mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
	if (dl->dl_namesize != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
		kmem_free(dl->dl_name, dl->dl_namesize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
	cv_destroy(&dl->dl_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
	kmem_free(dl, sizeof (*dl));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
 * Look up an entry in a directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
 * NOTE: '.' and '..' are handled as special cases because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
 *	no directory entries are actually stored for them.  If this is
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
 *	the root of a filesystem, then '.zfs' is also treated as a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
 *	special pseudo-directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
	zfs_dirlock_t *dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
	znode_t *zp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	int error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
	if (name[0] == 0 || (name[0] == '.' && name[1] == 0)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
		*vpp = ZTOV(dzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
		VN_HOLD(*vpp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	} else if (name[0] == '.' && name[1] == '.' && name[2] == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
		zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
		 * If we are a snapshot mounted under .zfs, return
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
		 * the vp for the snapshot directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
		 */
1878
c22df0f5603f 6413573 deadlock between fsflush() and zfs_create()
maybee
parents: 1544
diff changeset
   253
		if (dzp->z_phys->zp_parent == dzp->z_id &&
c22df0f5603f 6413573 deadlock between fsflush() and zfs_create()
maybee
parents: 1544
diff changeset
   254
		    zfsvfs->z_parent != zfsvfs) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
			error = zfsctl_root_lookup(zfsvfs->z_parent->z_ctldir,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
			    "snapshot", vpp, NULL, 0, NULL, kcred);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
			return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
		rw_enter(&dzp->z_parent_lock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
		error = zfs_zget(zfsvfs, dzp->z_phys->zp_parent, &zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
		if (error == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
			*vpp = ZTOV(zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
		rw_exit(&dzp->z_parent_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
	} else if (zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
		*vpp = zfsctl_root(dzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
		error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS | ZSHARED);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
		if (error == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
			*vpp = ZTOV(zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
			zfs_dirent_unlock(dl);
869
dc133b87dfb3 6297285 znode prefetching in zfs_readdir causes 5x performance degradation for 'ls'
perrin
parents: 789
diff changeset
   271
			dzp->z_zn_prefetch = B_TRUE; /* enable prefetching */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
static char *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
zfs_dq_hexname(char namebuf[17], uint64_t x)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	char *name = &namebuf[16];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
	const char digits[16] = "0123456789abcdef";
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	*name = '\0';
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	do {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
		*--name = digits[x & 0xf];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		x >>= 4;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
	} while (x != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	return (name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   293
/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   294
 * Delete Queue Error Handling
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   295
 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   296
 * When dealing with the delete queue, we dmu_tx_hold_zap(), but we
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   297
 * don't specify the name of the entry that we will be manipulating.  We
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   298
 * also fib and say that we won't be adding any new entries to the
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   299
 * delete queue, even though we might (this is to lower the minimum file
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   300
 * size that can be deleted in a full filesystem).  So on the small
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   301
 * chance that the delete queue is using a fat zap (ie. has more than
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   302
 * 2000 entries), we *may* not pre-read a block that's needed.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   303
 * Therefore it is remotely possible for some of the assertions
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   304
 * regarding the delete queue below to fail due to i/o error.  On a
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   305
 * nondebug system, this will result in the space being leaked.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   306
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   307
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
zfs_dq_add(znode_t *zp, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
	char obj_name[17];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
	ASSERT(zp->z_reap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
	ASSERT3U(zp->z_phys->zp_links, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	error = zap_add(zfsvfs->z_os, zfsvfs->z_dqueue,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
	    zfs_dq_hexname(obj_name, zp->z_id), 8, 1, &zp->z_id, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
	ASSERT3U(error, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
 * Delete the entire contents of a directory.  Return a count
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
 * of the number of entries that could not be deleted.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
 * NOTE: this function assumes that the directory is inactive,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
 *	so there is no need to lock its entries before deletion.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
 *	Also, it assumes the directory contents is *only* regular
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
 *	files.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
zfs_purgedir(znode_t *dzp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
	zap_cursor_t	zc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
	zap_attribute_t	zap;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
	znode_t		*xzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
	dmu_tx_t	*tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
	zfs_dirlock_t	dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
	int skipped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
	for (zap_cursor_init(&zc, zfsvfs->z_os, dzp->z_id);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	    (error = zap_cursor_retrieve(&zc, &zap)) == 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	    zap_cursor_advance(&zc)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
		error = zfs_zget(zfsvfs, zap.za_first_integer, &xzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
		ASSERT3U(error, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
		ASSERT((ZTOV(xzp)->v_type == VREG) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
		    (ZTOV(xzp)->v_type == VLNK));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
		tx = dmu_tx_create(zfsvfs->z_os);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
		dmu_tx_hold_bonus(tx, dzp->z_id);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   356
		dmu_tx_hold_zap(tx, dzp->z_id, FALSE, zap.za_name);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
		dmu_tx_hold_bonus(tx, xzp->z_id);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   358
		dmu_tx_hold_zap(tx, zfsvfs->z_dqueue, FALSE, NULL);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
		error = dmu_tx_assign(tx, TXG_WAIT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
		if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
			dmu_tx_abort(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
			VN_RELE(ZTOV(xzp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
			skipped += 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
		bzero(&dl, sizeof (dl));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
		dl.dl_dzp = dzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
		dl.dl_name = zap.za_name;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
		error = zfs_link_destroy(&dl, xzp, tx, 0, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
		ASSERT3U(error, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
		dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
		VN_RELE(ZTOV(xzp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
	}
885
d925b21dba78 6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents: 869
diff changeset
   376
	zap_cursor_fini(&zc);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
	ASSERT(error == ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
	return (skipped);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
 * Special function to requeue the znodes for deletion that were
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
 * in progress when we either crashed or umounted the file system.
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   384
 *
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   385
 * returns 1 if queue was drained.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
 */
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   387
static int
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
zfs_drain_dq(zfsvfs_t *zfsvfs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
	zap_cursor_t	zc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
	zap_attribute_t zap;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
	dmu_object_info_t doi;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
	znode_t		*zp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
	int		error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
	 * Interate over the contents of the delete queue.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
	for (zap_cursor_init(&zc, zfsvfs->z_os, zfsvfs->z_dqueue);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
	    zap_cursor_retrieve(&zc, &zap) == 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	    zap_cursor_advance(&zc)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
		/*
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   404
		 * Create more threads if necessary to balance the load.
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   405
		 * quit if the delete threads have been shut down.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
		if (zfs_delete_thread_target(zfsvfs, -1) != 0)
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   408
			return (0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
		 * See what kind of object we have in queue
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
		error = dmu_object_info(zfsvfs->z_os,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
		    zap.za_first_integer, &doi);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
		if (error != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
		ASSERT((doi.doi_type == DMU_OT_PLAIN_FILE_CONTENTS) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
		    (doi.doi_type == DMU_OT_DIRECTORY_CONTENTS));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
		 * We need to re-mark these queue entries for reaping,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
		 * so we pull them back into core and set zp->z_reap.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
		error = zfs_zget(zfsvfs, zap.za_first_integer, &zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
		 * We may pick up znodes that are already marked for reaping.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
		 * This could happen during the purge of an extended attribute
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
		 * directory.  All we need to do is skip over them, since they
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   431
		 * are already in the system to be processed by the delete
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   432
		 * thread(s).
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
		if (error != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
		}
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   437
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
		zp->z_reap = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
		VN_RELE(ZTOV(zp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
	}
885
d925b21dba78 6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents: 869
diff changeset
   441
	zap_cursor_fini(&zc);
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   442
	return (1);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
zfs_delete_thread(void *arg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	zfsvfs_t	*zfsvfs = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
	zfs_delete_t 	*zd = &zfsvfs->z_delete_head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	znode_t		*zp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
	callb_cpr_t	cprinfo;
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   452
	int		drained;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
	CALLB_CPR_INIT(&cprinfo, &zd->z_mutex, callb_generic_cpr, "zfs_delete");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
	mutex_enter(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
	if (!zd->z_drained && !zd->z_draining) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
		zd->z_draining = B_TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
		mutex_exit(&zd->z_mutex);
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   461
		drained = zfs_drain_dq(zfsvfs);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
		mutex_enter(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
		zd->z_draining = B_FALSE;
2245
0f2733e0b56b 6436526 delete_queue thread reporting drained when it may not be true
marks
parents: 2113
diff changeset
   464
		zd->z_drained = drained;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
		cv_broadcast(&zd->z_quiesce_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
	while (zd->z_thread_count <= zd->z_thread_target) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
		zp = list_head(&zd->z_znodes);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
		if (zp == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
			ASSERT(zd->z_znode_count == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
			cv_wait(&zd->z_cv, &zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
			CALLB_CPR_SAFE_END(&cprinfo, &zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
		ASSERT(zd->z_znode_count != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
		list_remove(&zd->z_znodes, zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
		if (--zd->z_znode_count == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
			cv_broadcast(&zd->z_quiesce_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
		mutex_exit(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
		zfs_rmnode(zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
		(void) zfs_delete_thread_target(zfsvfs, -1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
		mutex_enter(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
	ASSERT(zd->z_thread_count != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
	if (--zd->z_thread_count == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
		cv_broadcast(&zd->z_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
	CALLB_CPR_EXIT(&cprinfo);	/* NB: drops z_mutex */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
	thread_exit();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
static int zfs_work_per_thread_shift = 11;	/* 2048 (2^11) per thread */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
 * Set the target number of delete threads to 'nthreads'.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
 * If nthreads == -1, choose a number based on current workload.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
 * If nthreads == 0, don't return until the threads have exited.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
zfs_delete_thread_target(zfsvfs_t *zfsvfs, int nthreads)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
	zfs_delete_t *zd = &zfsvfs->z_delete_head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
	mutex_enter(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
	if (nthreads == -1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
		if (zd->z_thread_target == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
			mutex_exit(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
			return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
		nthreads = zd->z_znode_count >> zfs_work_per_thread_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
		nthreads = MIN(nthreads, ncpus << 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
		nthreads = MAX(nthreads, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
		nthreads += !!zd->z_draining;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
	zd->z_thread_target = nthreads;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
	while (zd->z_thread_count < zd->z_thread_target) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
		(void) thread_create(NULL, 0, zfs_delete_thread, zfsvfs,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
		    0, &p0, TS_RUN, minclsyspri);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
		zd->z_thread_count++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
	while (zd->z_thread_count > zd->z_thread_target && nthreads == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
		cv_broadcast(&zd->z_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
		cv_wait(&zd->z_cv, &zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
	mutex_exit(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
 * Wait until everything that's been queued has been deleted.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
zfs_delete_wait_empty(zfsvfs_t *zfsvfs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
	zfs_delete_t *zd = &zfsvfs->z_delete_head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
	mutex_enter(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
	ASSERT(zd->z_thread_target != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
	while (!zd->z_drained || zd->z_znode_count != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
		ASSERT(zd->z_thread_target != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
		cv_wait(&zd->z_quiesce_cv, &zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
	mutex_exit(&zd->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
zfs_rmnode(znode_t *zp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
	objset_t	*os = zfsvfs->z_os;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
	znode_t		*xzp = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
	char		obj_name[17];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
	dmu_tx_t	*tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
	uint64_t	acl_obj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
	int		error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	ASSERT(ZTOV(zp)->v_count == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
	ASSERT(zp->z_phys->zp_links == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
	 * If this is an attribute directory, purge its contents.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
	if (ZTOV(zp)->v_type == VDIR && (zp->z_phys->zp_flags & ZFS_XATTR))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   573
		if (zfs_purgedir(zp) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
			zfs_delete_t *delq = &zfsvfs->z_delete_head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
			 * Add this back to the delete list to be retried later.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
			 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
			 * XXX - this could just busy loop on us...
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
			mutex_enter(&delq->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
			list_insert_tail(&delq->z_znodes, zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
			delq->z_znode_count++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
			mutex_exit(&delq->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
			return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
	 * If the file has extended attributes, unlink the xattr dir.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
	if (zp->z_phys->zp_xattr) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
		error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
		ASSERT(error == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
	acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
	 * Set up the transaction.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
	tx = dmu_tx_create(os);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
	dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   602
	dmu_tx_hold_zap(tx, zfsvfs->z_dqueue, FALSE, NULL);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
	if (xzp) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
		dmu_tx_hold_bonus(tx, xzp->z_id);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   605
		dmu_tx_hold_zap(tx, zfsvfs->z_dqueue, TRUE, NULL);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
	if (acl_obj)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
		dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
	error = dmu_tx_assign(tx, TXG_WAIT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
	if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
		zfs_delete_t *delq = &zfsvfs->z_delete_head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
		dmu_tx_abort(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
		 * Add this back to the delete list to be retried later.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
		 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
		 * XXX - this could just busy loop on us...
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
		mutex_enter(&delq->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
		list_insert_tail(&delq->z_znodes, zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
		delq->z_znode_count++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
		mutex_exit(&delq->z_mutex);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
	if (xzp) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
		dmu_buf_will_dirty(xzp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
		mutex_enter(&xzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
		xzp->z_reap = 1;		/* mark xzp for deletion */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
		xzp->z_phys->zp_links = 0;	/* no more links to it */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
		mutex_exit(&xzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
		zfs_dq_add(xzp, tx);		/* add xzp to delete queue */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
	 * Remove this znode from delete queue
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
	error = zap_remove(os, zfsvfs->z_dqueue,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
	    zfs_dq_hexname(obj_name, zp->z_id), tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
	ASSERT3U(error, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
	zfs_znode_delete(zp, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
	dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
	if (xzp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
		VN_RELE(ZTOV(xzp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
 * Link zp into dl.  Can only fail if zp has been reaped.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
	znode_t *dzp = dl->dl_dzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
	vnode_t *vp = ZTOV(zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
	int zp_is_dir = (vp->v_type == VDIR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
	dmu_buf_will_dirty(zp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
	mutex_enter(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
	if (!(flag & ZRENAMING)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
		if (zp->z_reap) {	/* no new links to reaped zp */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
			ASSERT(!(flag & (ZNEW | ZEXISTS)));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
			mutex_exit(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
			return (ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
		zp->z_phys->zp_links++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
	zp->z_phys->zp_parent = dzp->z_id;	/* dzp is now zp's parent */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
	if (!(flag & ZNEW))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
		zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
	mutex_exit(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
	dmu_buf_will_dirty(dzp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
	mutex_enter(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
	dzp->z_phys->zp_size++;			/* one dirent added */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
	dzp->z_phys->zp_links += zp_is_dir;	/* ".." link from zp */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
	zfs_time_stamper_locked(dzp, CONTENT_MODIFIED, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
	mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
	error = zap_add(zp->z_zfsvfs->z_os, dzp->z_id, dl->dl_name,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
	    8, 1, &zp->z_id, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
	ASSERT(error == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   689
	dnlc_update(ZTOV(dzp), dl->dl_name, vp);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   690
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
 * Unlink zp from dl, and mark zp for reaping if this was the last link.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
 * Can fail if zp is a mount point (EBUSY) or a non-empty directory (EEXIST).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
 * If 'reaped_ptr' is NULL, we put reaped znodes on the delete queue.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
 * If it's non-NULL, we use it to indicate whether the znode needs reaping,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
 * and it's the caller's job to do it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
	int *reaped_ptr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
	znode_t *dzp = dl->dl_dzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
	vnode_t *vp = ZTOV(zp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
	int zp_is_dir = (vp->v_type == VDIR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
	int reaped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
1484
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   711
	dnlc_remove(ZTOV(dzp), dl->dl_name);
d330e98f8ed7 6350001 ZFS lookup performance still much slower than UFS : help tar : help spec SFS
ek110237
parents: 1231
diff changeset
   712
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
	if (!(flag & ZRENAMING)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
		dmu_buf_will_dirty(zp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
		if (vn_vfswlock(vp))		/* prevent new mounts on zp */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
			return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
		if (vn_ismntpt(vp)) {		/* don't remove mount point */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
			vn_vfsunlock(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
			return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
		mutex_enter(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
		if (zp_is_dir && !zfs_dirempty(zp)) {	/* dir not empty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
			mutex_exit(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
			vn_vfsunlock(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
			return (EEXIST);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
		ASSERT(zp->z_phys->zp_links > zp_is_dir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
		if (--zp->z_phys->zp_links == zp_is_dir) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
			zp->z_reap = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
			zp->z_phys->zp_links = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
			reaped = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
			zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
		mutex_exit(&zp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
		vn_vfsunlock(vp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
	dmu_buf_will_dirty(dzp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
	mutex_enter(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
	dzp->z_phys->zp_size--;			/* one dirent removed */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
	dzp->z_phys->zp_links -= zp_is_dir;	/* ".." link from zp */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
	zfs_time_stamper_locked(dzp, CONTENT_MODIFIED, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
	mutex_exit(&dzp->z_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
	error = zap_remove(zp->z_zfsvfs->z_os, dzp->z_id, dl->dl_name, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
	ASSERT(error == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
	if (reaped_ptr != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
		*reaped_ptr = reaped;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
	else if (reaped)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
		zfs_dq_add(zp, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
 * Indicate whether the directory is empty.  Works with or without z_lock
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
 * held, but can only be consider a hint in the latter case.  Returns true
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
 * if only "." and ".." remain and there's no work in progress.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
boolean_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
zfs_dirempty(znode_t *dzp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
	return (dzp->z_phys->zp_size == 2 && dzp->z_dirlocks == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
zfs_make_xattrdir(znode_t *zp, vattr_t *vap, vnode_t **xvpp, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
	znode_t *xzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
	dmu_tx_t *tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
	uint64_t xoid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
	*xvpp = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
	if (error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, cr))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
	tx = dmu_tx_create(zfsvfs->z_os);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	dmu_tx_hold_bonus(tx, zp->z_id);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1484
diff changeset
   787
	dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
	error = dmu_tx_assign(tx, zfsvfs->z_assign);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
	if (error) {
2113
0510bb40c993 6430121 3-way deadlock involving tc_lock within zfs
ahrens
parents: 1878
diff changeset
   790
		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT)
0510bb40c993 6430121 3-way deadlock involving tc_lock within zfs
ahrens
parents: 1878
diff changeset
   791
			dmu_tx_wait(tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
		dmu_tx_abort(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
	zfs_mknode(zp, vap, &xoid, tx, cr, IS_XATTR, &xzp, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
	ASSERT(xzp->z_id == xoid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
	ASSERT(xzp->z_phys->zp_parent == zp->z_id);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
	dmu_buf_will_dirty(zp->z_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
	zp->z_phys->zp_xattr = xoid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	(void) zfs_log_create(zfsvfs->z_log, tx, TX_MKXATTR, zp, xzp, "");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	*xvpp = ZTOV(xzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
 * Return a znode for the extended attribute directory for zp.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
 * ** If the directory does not already exist, it is created **
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
 *	IN:	zp	- znode to obtain attribute directory from
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
 *		cr	- credentials of caller
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
 *	OUT:	xzpp	- pointer to extended attribute znode
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   817
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   818
 *	RETURN:	0 on success
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   819
 *		error number on failure
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   820
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
zfs_get_xattrdir(znode_t *zp, vnode_t **xvpp, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   825
	znode_t		*xzp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
	zfs_dirlock_t	*dl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   827
	vattr_t		va;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   828
	int		error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
top:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
	error = zfs_dirent_lock(&dl, zp, "", &xzp, ZXATTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
	if (error)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
	if (xzp != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
		*xvpp = ZTOV(xzp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
		zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
	ASSERT(zp->z_phys->zp_xattr == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
	if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
		zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
		return (EROFS);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   847
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   848
	 * The ability to 'create' files in an attribute
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   849
	 * directory comes from the write_xattr permission on the base file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   850
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   851
	 * The ability to 'search' an attribute directory requires
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   852
	 * read_xattr permission on the base file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   853
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   854
	 * Once in a directory the ability to read/write attributes
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   855
	 * is controlled by the permissions on the attribute file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   856
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   857
	va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
	va.va_type = VDIR;
1231
64215f768e86 6354804 The file's ACL was changed when cp it from one ZFS file system to another one.
marks
parents: 885
diff changeset
   859
	va.va_mode = S_IFDIR | S_ISVTX | 0777;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   860
	va.va_uid = (uid_t)zp->z_phys->zp_uid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   861
	va.va_gid = (gid_t)zp->z_phys->zp_gid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   862
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
	error = zfs_make_xattrdir(zp, &va, xvpp, cr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
	zfs_dirent_unlock(dl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
	if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2113
0510bb40c993 6430121 3-way deadlock involving tc_lock within zfs
ahrens
parents: 1878
diff changeset
   867
		/* NB: we already did dmu_tx_wait() if necessary */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
		goto top;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
 * Decide whether it is okay to remove within a sticky directory.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
 * In sticky directories, write access is not sufficient;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
 * you can remove entries from a directory only if:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   880
 *	you own the directory,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
 *	you own the entry,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
 *	the entry is a plain file and you have write access,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
 *	or you are privileged (checked in secpolicy...).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   884
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   885
 * The function returns 0 if remove access is granted.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
	uid_t  		uid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   891
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
	if (zdp->z_zfsvfs->z_assign >= TXG_INITIAL)	/* ZIL replay */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
	if ((zdp->z_phys->zp_mode & S_ISVTX) == 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
	    (uid = crgetuid(cr)) == zdp->z_phys->zp_uid ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
	    uid == zp->z_phys->zp_uid ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
	    (ZTOV(zp)->v_type == VREG &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
	    zfs_zaccess(zp, ACE_WRITE_DATA, cr) == 0))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   900
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   901
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
		return (secpolicy_vnode_remove(cr));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
}