1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 228f2529deSMark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 234bb73804SMatthew Ahrens * Copyright (c) 2012, 2014 by Delphix. All rights reserved. 24*c3d26abcSMatthew Ahrens * Copyright (c) 2014 Integros [integros.com] 25fa9e4066Sahrens */ 26fa9e4066Sahrens 2775c76197Speteh /* Portions Copyright 2007 Jeremy Teo */ 2875c76197Speteh 2955434c77Sek #ifdef _KERNEL 30fa9e4066Sahrens #include <sys/types.h> 31fa9e4066Sahrens #include <sys/param.h> 32fa9e4066Sahrens #include <sys/time.h> 33fa9e4066Sahrens #include <sys/systm.h> 34fa9e4066Sahrens #include <sys/sysmacros.h> 35fa9e4066Sahrens #include <sys/resource.h> 36fa9e4066Sahrens #include <sys/mntent.h> 3772fc53bcSmarks #include <sys/mkdev.h> 38de8267e0Stimh #include <sys/u8_textprep.h> 39ab04eb8eStimh #include <sys/dsl_dataset.h> 40fa9e4066Sahrens #include <sys/vfs.h> 41aa59c4cbSrsb #include <sys/vfs_opreg.h> 42fa9e4066Sahrens #include <sys/vnode.h> 43fa9e4066Sahrens #include <sys/file.h> 44fa9e4066Sahrens #include <sys/kmem.h> 45fa9e4066Sahrens #include <sys/errno.h> 46fa9e4066Sahrens #include <sys/unistd.h> 47fa9e4066Sahrens #include <sys/mode.h> 48fa9e4066Sahrens #include <sys/atomic.h> 49fa9e4066Sahrens #include <vm/pvn.h> 50fa9e4066Sahrens #include "fs/fs_subr.h" 51fa9e4066Sahrens #include <sys/zfs_dir.h> 52fa9e4066Sahrens #include <sys/zfs_acl.h> 53fa9e4066Sahrens #include <sys/zfs_ioctl.h> 54104e2ed7Sperrin #include <sys/zfs_rlock.h> 55da6c28aaSamw #include <sys/zfs_fuid.h> 560a586ceaSMark Shellenbaum #include <sys/dnode.h> 57fa9e4066Sahrens #include <sys/fs/zfs.h> 58da6c28aaSamw #include <sys/kidmap.h> 5955434c77Sek #endif /* _KERNEL */ 6055434c77Sek 6155434c77Sek #include <sys/dmu.h> 62b5152584SMatthew Ahrens #include <sys/dmu_objset.h> 6355434c77Sek #include <sys/refcount.h> 6455434c77Sek #include <sys/stat.h> 6555434c77Sek #include <sys/zap.h> 6655434c77Sek #include <sys/zfs_znode.h> 670a586ceaSMark Shellenbaum #include <sys/sa.h> 680a586ceaSMark Shellenbaum #include <sys/zfs_sa.h> 6999d5e173STim Haley #include <sys/zfs_stat.h> 70fa9e4066Sahrens 71de8267e0Stimh #include "zfs_prop.h" 720a586ceaSMark Shellenbaum #include "zfs_comutil.h" 73de8267e0Stimh 74b5fca8f8Stomee /* 75b5fca8f8Stomee * Define ZNODE_STATS to turn on statistic gathering. By default, it is only 76b5fca8f8Stomee * turned on when DEBUG is also defined. 77b5fca8f8Stomee */ 78b5fca8f8Stomee #ifdef DEBUG 79b5fca8f8Stomee #define ZNODE_STATS 80b5fca8f8Stomee #endif /* DEBUG */ 81b5fca8f8Stomee 82b5fca8f8Stomee #ifdef ZNODE_STATS 83b5fca8f8Stomee #define ZNODE_STAT_ADD(stat) ((stat)++) 84b5fca8f8Stomee #else 85b5fca8f8Stomee #define ZNODE_STAT_ADD(stat) /* nothing */ 86b5fca8f8Stomee #endif /* ZNODE_STATS */ 87b5fca8f8Stomee 8855434c77Sek /* 8955434c77Sek * Functions needed for userland (ie: libzpool) are not put under 9055434c77Sek * #ifdef_KERNEL; the rest of the functions have dependencies 9155434c77Sek * (such as VFS logic) that will not compile easily in userland. 9255434c77Sek */ 9355434c77Sek #ifdef _KERNEL 944e9583b2STom Erickson /* 954e9583b2STom Erickson * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to 964e9583b2STom Erickson * be freed before it can be safely accessed. 974e9583b2STom Erickson */ 984e9583b2STom Erickson krwlock_t zfsvfs_lock; 994e9583b2STom Erickson 100b5fca8f8Stomee static kmem_cache_t *znode_cache = NULL; 101fa9e4066Sahrens 102fa9e4066Sahrens /*ARGSUSED*/ 103fa9e4066Sahrens static void 104874395d5Smaybee znode_evict_error(dmu_buf_t *dbuf, void *user_ptr) 105fa9e4066Sahrens { 106874395d5Smaybee /* 107874395d5Smaybee * We should never drop all dbuf refs without first clearing 108874395d5Smaybee * the eviction callback. 109874395d5Smaybee */ 110874395d5Smaybee panic("evicting znode %p\n", user_ptr); 111fa9e4066Sahrens } 112fa9e4066Sahrens 113fa9e4066Sahrens /*ARGSUSED*/ 114fa9e4066Sahrens static int 115b5fca8f8Stomee zfs_znode_cache_constructor(void *buf, void *arg, int kmflags) 116fa9e4066Sahrens { 117fa9e4066Sahrens znode_t *zp = buf; 118fa9e4066Sahrens 119b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 120b5fca8f8Stomee 121b5fca8f8Stomee zp->z_vnode = vn_alloc(kmflags); 122b5fca8f8Stomee if (zp->z_vnode == NULL) { 123b5fca8f8Stomee return (-1); 124b5fca8f8Stomee } 125b5fca8f8Stomee ZTOV(zp)->v_data = zp; 126b5fca8f8Stomee 127b5fca8f8Stomee list_link_init(&zp->z_link_node); 128b5fca8f8Stomee 129fa9e4066Sahrens mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL); 130104e2ed7Sperrin rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL); 131af2c4821Smaybee rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL); 132fa9e4066Sahrens mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL); 133104e2ed7Sperrin 134104e2ed7Sperrin mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL); 135104e2ed7Sperrin avl_create(&zp->z_range_avl, zfs_range_compare, 136104e2ed7Sperrin sizeof (rl_t), offsetof(rl_t, r_node)); 137104e2ed7Sperrin 138b5fca8f8Stomee zp->z_dirlocks = NULL; 139d47621a4STim Haley zp->z_acl_cached = NULL; 140744947dcSTom Erickson zp->z_moved = 0; 141fa9e4066Sahrens return (0); 142fa9e4066Sahrens } 143fa9e4066Sahrens 144fa9e4066Sahrens /*ARGSUSED*/ 145fa9e4066Sahrens static void 146b5fca8f8Stomee zfs_znode_cache_destructor(void *buf, void *arg) 147fa9e4066Sahrens { 148fa9e4066Sahrens znode_t *zp = buf; 149fa9e4066Sahrens 150b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 151b5fca8f8Stomee ASSERT(ZTOV(zp)->v_data == zp); 152b5fca8f8Stomee vn_free(ZTOV(zp)); 153b5fca8f8Stomee ASSERT(!list_link_active(&zp->z_link_node)); 154fa9e4066Sahrens mutex_destroy(&zp->z_lock); 155104e2ed7Sperrin rw_destroy(&zp->z_parent_lock); 156af2c4821Smaybee rw_destroy(&zp->z_name_lock); 157fa9e4066Sahrens mutex_destroy(&zp->z_acl_lock); 158104e2ed7Sperrin avl_destroy(&zp->z_range_avl); 159c25056deSgw mutex_destroy(&zp->z_range_lock); 160fa9e4066Sahrens 161b5fca8f8Stomee ASSERT(zp->z_dirlocks == NULL); 1624929fd5eSTim Haley ASSERT(zp->z_acl_cached == NULL); 163b5fca8f8Stomee } 164b5fca8f8Stomee 165b5fca8f8Stomee #ifdef ZNODE_STATS 166b5fca8f8Stomee static struct { 167b5fca8f8Stomee uint64_t zms_zfsvfs_invalid; 1684e9583b2STom Erickson uint64_t zms_zfsvfs_recheck1; 169b5fca8f8Stomee uint64_t zms_zfsvfs_unmounted; 1704e9583b2STom Erickson uint64_t zms_zfsvfs_recheck2; 171a66b2b35STom Erickson uint64_t zms_obj_held; 172b5fca8f8Stomee uint64_t zms_vnode_locked; 173a66b2b35STom Erickson uint64_t zms_not_only_dnlc; 174b5fca8f8Stomee } znode_move_stats; 175b5fca8f8Stomee #endif /* ZNODE_STATS */ 176b5fca8f8Stomee 177b5fca8f8Stomee static void 178b5fca8f8Stomee zfs_znode_move_impl(znode_t *ozp, znode_t *nzp) 179b5fca8f8Stomee { 180b5fca8f8Stomee vnode_t *vp; 181b5fca8f8Stomee 182b5fca8f8Stomee /* Copy fields. */ 183b5fca8f8Stomee nzp->z_zfsvfs = ozp->z_zfsvfs; 184b5fca8f8Stomee 185b5fca8f8Stomee /* Swap vnodes. */ 186b5fca8f8Stomee vp = nzp->z_vnode; 187b5fca8f8Stomee nzp->z_vnode = ozp->z_vnode; 188b5fca8f8Stomee ozp->z_vnode = vp; /* let destructor free the overwritten vnode */ 189b5fca8f8Stomee ZTOV(ozp)->v_data = ozp; 190b5fca8f8Stomee ZTOV(nzp)->v_data = nzp; 191b5fca8f8Stomee 192b5fca8f8Stomee nzp->z_id = ozp->z_id; 193b5fca8f8Stomee ASSERT(ozp->z_dirlocks == NULL); /* znode not in use */ 194b5fca8f8Stomee ASSERT(avl_numnodes(&ozp->z_range_avl) == 0); 195b5fca8f8Stomee nzp->z_unlinked = ozp->z_unlinked; 196b5fca8f8Stomee nzp->z_atime_dirty = ozp->z_atime_dirty; 197b5fca8f8Stomee nzp->z_zn_prefetch = ozp->z_zn_prefetch; 198b5fca8f8Stomee nzp->z_blksz = ozp->z_blksz; 199b5fca8f8Stomee nzp->z_seq = ozp->z_seq; 200b5fca8f8Stomee nzp->z_mapcnt = ozp->z_mapcnt; 201b5fca8f8Stomee nzp->z_gen = ozp->z_gen; 202b5fca8f8Stomee nzp->z_sync_cnt = ozp->z_sync_cnt; 2030a586ceaSMark Shellenbaum nzp->z_is_sa = ozp->z_is_sa; 2040a586ceaSMark Shellenbaum nzp->z_sa_hdl = ozp->z_sa_hdl; 2050a586ceaSMark Shellenbaum bcopy(ozp->z_atime, nzp->z_atime, sizeof (uint64_t) * 2); 2060a586ceaSMark Shellenbaum nzp->z_links = ozp->z_links; 2070a586ceaSMark Shellenbaum nzp->z_size = ozp->z_size; 2080a586ceaSMark Shellenbaum nzp->z_pflags = ozp->z_pflags; 2090a586ceaSMark Shellenbaum nzp->z_uid = ozp->z_uid; 2100a586ceaSMark Shellenbaum nzp->z_gid = ozp->z_gid; 2110a586ceaSMark Shellenbaum nzp->z_mode = ozp->z_mode; 212d98a6232SMark Shellenbaum 213d98a6232SMark Shellenbaum /* 2146638ae1dSMark Shellenbaum * Since this is just an idle znode and kmem is already dealing with 2156638ae1dSMark Shellenbaum * memory pressure, release any cached ACL. 216d98a6232SMark Shellenbaum */ 217d98a6232SMark Shellenbaum if (ozp->z_acl_cached) { 218d98a6232SMark Shellenbaum zfs_acl_free(ozp->z_acl_cached); 219d98a6232SMark Shellenbaum ozp->z_acl_cached = NULL; 220d98a6232SMark Shellenbaum } 221b5fca8f8Stomee 2220a586ceaSMark Shellenbaum sa_set_userp(nzp->z_sa_hdl, nzp); 223b5fca8f8Stomee 224b5fca8f8Stomee /* 225b5fca8f8Stomee * Invalidate the original znode by clearing fields that provide a 226b5fca8f8Stomee * pointer back to the znode. Set the low bit of the vfs pointer to 227b5fca8f8Stomee * ensure that zfs_znode_move() recognizes the znode as invalid in any 228b5fca8f8Stomee * subsequent callback. 229b5fca8f8Stomee */ 2300a586ceaSMark Shellenbaum ozp->z_sa_hdl = NULL; 231b5fca8f8Stomee POINTER_INVALIDATE(&ozp->z_zfsvfs); 232744947dcSTom Erickson 233744947dcSTom Erickson /* 234744947dcSTom Erickson * Mark the znode. 235744947dcSTom Erickson */ 236744947dcSTom Erickson nzp->z_moved = 1; 237744947dcSTom Erickson ozp->z_moved = (uint8_t)-1; 238b5fca8f8Stomee } 239b5fca8f8Stomee 240b5fca8f8Stomee /*ARGSUSED*/ 241b5fca8f8Stomee static kmem_cbrc_t 242b5fca8f8Stomee zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg) 243b5fca8f8Stomee { 244b5fca8f8Stomee znode_t *ozp = buf, *nzp = newbuf; 245b5fca8f8Stomee zfsvfs_t *zfsvfs; 246b5fca8f8Stomee vnode_t *vp; 247b5fca8f8Stomee 248b5fca8f8Stomee /* 249b5fca8f8Stomee * The znode is on the file system's list of known znodes if the vfs 250b5fca8f8Stomee * pointer is valid. We set the low bit of the vfs pointer when freeing 251b5fca8f8Stomee * the znode to invalidate it, and the memory patterns written by kmem 252b5fca8f8Stomee * (baddcafe and deadbeef) set at least one of the two low bits. A newly 253b5fca8f8Stomee * created znode sets the vfs pointer last of all to indicate that the 254b5fca8f8Stomee * znode is known and in a valid state to be moved by this function. 255b5fca8f8Stomee */ 256b5fca8f8Stomee zfsvfs = ozp->z_zfsvfs; 257b5fca8f8Stomee if (!POINTER_IS_VALID(zfsvfs)) { 258b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_invalid); 259b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 260b5fca8f8Stomee } 261b5fca8f8Stomee 262b5fca8f8Stomee /* 2634e9583b2STom Erickson * Close a small window in which it's possible that the filesystem could 2644e9583b2STom Erickson * be unmounted and freed, and zfsvfs, though valid in the previous 2654e9583b2STom Erickson * statement, could point to unrelated memory by the time we try to 2664e9583b2STom Erickson * prevent the filesystem from being unmounted. 2674e9583b2STom Erickson */ 2684e9583b2STom Erickson rw_enter(&zfsvfs_lock, RW_WRITER); 2694e9583b2STom Erickson if (zfsvfs != ozp->z_zfsvfs) { 2704e9583b2STom Erickson rw_exit(&zfsvfs_lock); 2714e9583b2STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1); 2724e9583b2STom Erickson return (KMEM_CBRC_DONT_KNOW); 2734e9583b2STom Erickson } 2744e9583b2STom Erickson 2754e9583b2STom Erickson /* 2764e9583b2STom Erickson * If the znode is still valid, then so is the file system. We know that 2774e9583b2STom Erickson * no valid file system can be freed while we hold zfsvfs_lock, so we 2784e9583b2STom Erickson * can safely ensure that the filesystem is not and will not be 2794e9583b2STom Erickson * unmounted. The next statement is equivalent to ZFS_ENTER(). 280b5fca8f8Stomee */ 281c9030f6cSAlexander Motin rrm_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG); 28214843421SMatthew Ahrens if (zfsvfs->z_unmounted) { 28314843421SMatthew Ahrens ZFS_EXIT(zfsvfs); 2844e9583b2STom Erickson rw_exit(&zfsvfs_lock); 285b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted); 286b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 287b5fca8f8Stomee } 2884e9583b2STom Erickson rw_exit(&zfsvfs_lock); 289b5fca8f8Stomee 290b5fca8f8Stomee mutex_enter(&zfsvfs->z_znodes_lock); 291b5fca8f8Stomee /* 292b5fca8f8Stomee * Recheck the vfs pointer in case the znode was removed just before 293b5fca8f8Stomee * acquiring the lock. 294b5fca8f8Stomee */ 295b5fca8f8Stomee if (zfsvfs != ozp->z_zfsvfs) { 296b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 297b5fca8f8Stomee ZFS_EXIT(zfsvfs); 2984e9583b2STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2); 299b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 300b5fca8f8Stomee } 301b5fca8f8Stomee 302b5fca8f8Stomee /* 303b5fca8f8Stomee * At this point we know that as long as we hold z_znodes_lock, the 304b5fca8f8Stomee * znode cannot be freed and fields within the znode can be safely 305a66b2b35STom Erickson * accessed. Now, prevent a race with zfs_zget(). 306b5fca8f8Stomee */ 307a66b2b35STom Erickson if (ZFS_OBJ_HOLD_TRYENTER(zfsvfs, ozp->z_id) == 0) { 308a66b2b35STom Erickson mutex_exit(&zfsvfs->z_znodes_lock); 309a66b2b35STom Erickson ZFS_EXIT(zfsvfs); 310a66b2b35STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_obj_held); 311a66b2b35STom Erickson return (KMEM_CBRC_LATER); 312a66b2b35STom Erickson } 313a66b2b35STom Erickson 314b5fca8f8Stomee vp = ZTOV(ozp); 315b5fca8f8Stomee if (mutex_tryenter(&vp->v_lock) == 0) { 316a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 317b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 318b5fca8f8Stomee ZFS_EXIT(zfsvfs); 319b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_vnode_locked); 320b5fca8f8Stomee return (KMEM_CBRC_LATER); 321b5fca8f8Stomee } 322a66b2b35STom Erickson 323b5fca8f8Stomee /* Only move znodes that are referenced _only_ by the DNLC. */ 324b5fca8f8Stomee if (vp->v_count != 1 || !vn_in_dnlc(vp)) { 325b5fca8f8Stomee mutex_exit(&vp->v_lock); 326a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 327b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 328b5fca8f8Stomee ZFS_EXIT(zfsvfs); 329a66b2b35STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_not_only_dnlc); 330b5fca8f8Stomee return (KMEM_CBRC_LATER); 331b5fca8f8Stomee } 332b5fca8f8Stomee 333b5fca8f8Stomee /* 334b5fca8f8Stomee * The znode is known and in a valid state to move. We're holding the 335b5fca8f8Stomee * locks needed to execute the critical section. 336b5fca8f8Stomee */ 337b5fca8f8Stomee zfs_znode_move_impl(ozp, nzp); 338b5fca8f8Stomee mutex_exit(&vp->v_lock); 339a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 340b5fca8f8Stomee 341b5fca8f8Stomee list_link_replace(&ozp->z_link_node, &nzp->z_link_node); 342b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 343b5fca8f8Stomee ZFS_EXIT(zfsvfs); 344b5fca8f8Stomee 345b5fca8f8Stomee return (KMEM_CBRC_YES); 346fa9e4066Sahrens } 347fa9e4066Sahrens 348fa9e4066Sahrens void 349fa9e4066Sahrens zfs_znode_init(void) 350fa9e4066Sahrens { 351fa9e4066Sahrens /* 352fa9e4066Sahrens * Initialize zcache 353fa9e4066Sahrens */ 3544e9583b2STom Erickson rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL); 355fa9e4066Sahrens ASSERT(znode_cache == NULL); 356fa9e4066Sahrens znode_cache = kmem_cache_create("zfs_znode_cache", 357fa9e4066Sahrens sizeof (znode_t), 0, zfs_znode_cache_constructor, 358fa9e4066Sahrens zfs_znode_cache_destructor, NULL, NULL, NULL, 0); 359b5fca8f8Stomee kmem_cache_set_move(znode_cache, zfs_znode_move); 360fa9e4066Sahrens } 361fa9e4066Sahrens 362fa9e4066Sahrens void 363fa9e4066Sahrens zfs_znode_fini(void) 364fa9e4066Sahrens { 365fa9e4066Sahrens /* 366fa9e4066Sahrens * Cleanup vfs & vnode ops 367fa9e4066Sahrens */ 368fa9e4066Sahrens zfs_remove_op_tables(); 369fa9e4066Sahrens 370fa9e4066Sahrens /* 371fa9e4066Sahrens * Cleanup zcache 372fa9e4066Sahrens */ 373fa9e4066Sahrens if (znode_cache) 374fa9e4066Sahrens kmem_cache_destroy(znode_cache); 375fa9e4066Sahrens znode_cache = NULL; 3764e9583b2STom Erickson rw_destroy(&zfsvfs_lock); 377fa9e4066Sahrens } 378fa9e4066Sahrens 379fa9e4066Sahrens struct vnodeops *zfs_dvnodeops; 380fa9e4066Sahrens struct vnodeops *zfs_fvnodeops; 381fa9e4066Sahrens struct vnodeops *zfs_symvnodeops; 382fa9e4066Sahrens struct vnodeops *zfs_xdvnodeops; 383fa9e4066Sahrens struct vnodeops *zfs_evnodeops; 384743a77edSAlan Wright struct vnodeops *zfs_sharevnodeops; 385fa9e4066Sahrens 386fa9e4066Sahrens void 387fa9e4066Sahrens zfs_remove_op_tables() 388fa9e4066Sahrens { 389fa9e4066Sahrens /* 390fa9e4066Sahrens * Remove vfs ops 391fa9e4066Sahrens */ 392fa9e4066Sahrens ASSERT(zfsfstype); 393fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 394fa9e4066Sahrens zfsfstype = 0; 395fa9e4066Sahrens 396fa9e4066Sahrens /* 397fa9e4066Sahrens * Remove vnode ops 398fa9e4066Sahrens */ 399fa9e4066Sahrens if (zfs_dvnodeops) 400fa9e4066Sahrens vn_freevnodeops(zfs_dvnodeops); 401fa9e4066Sahrens if (zfs_fvnodeops) 402fa9e4066Sahrens vn_freevnodeops(zfs_fvnodeops); 403fa9e4066Sahrens if (zfs_symvnodeops) 404fa9e4066Sahrens vn_freevnodeops(zfs_symvnodeops); 405fa9e4066Sahrens if (zfs_xdvnodeops) 406fa9e4066Sahrens vn_freevnodeops(zfs_xdvnodeops); 407fa9e4066Sahrens if (zfs_evnodeops) 408fa9e4066Sahrens vn_freevnodeops(zfs_evnodeops); 409743a77edSAlan Wright if (zfs_sharevnodeops) 410743a77edSAlan Wright vn_freevnodeops(zfs_sharevnodeops); 411fa9e4066Sahrens 412fa9e4066Sahrens zfs_dvnodeops = NULL; 413fa9e4066Sahrens zfs_fvnodeops = NULL; 414fa9e4066Sahrens zfs_symvnodeops = NULL; 415fa9e4066Sahrens zfs_xdvnodeops = NULL; 416fa9e4066Sahrens zfs_evnodeops = NULL; 417743a77edSAlan Wright zfs_sharevnodeops = NULL; 418fa9e4066Sahrens } 419fa9e4066Sahrens 420fa9e4066Sahrens extern const fs_operation_def_t zfs_dvnodeops_template[]; 421fa9e4066Sahrens extern const fs_operation_def_t zfs_fvnodeops_template[]; 422fa9e4066Sahrens extern const fs_operation_def_t zfs_xdvnodeops_template[]; 423fa9e4066Sahrens extern const fs_operation_def_t zfs_symvnodeops_template[]; 424fa9e4066Sahrens extern const fs_operation_def_t zfs_evnodeops_template[]; 425743a77edSAlan Wright extern const fs_operation_def_t zfs_sharevnodeops_template[]; 426fa9e4066Sahrens 427fa9e4066Sahrens int 428fa9e4066Sahrens zfs_create_op_tables() 429fa9e4066Sahrens { 430fa9e4066Sahrens int error; 431fa9e4066Sahrens 432fa9e4066Sahrens /* 433fa9e4066Sahrens * zfs_dvnodeops can be set if mod_remove() calls mod_installfs() 434fa9e4066Sahrens * due to a failure to remove the the 2nd modlinkage (zfs_modldrv). 435fa9e4066Sahrens * In this case we just return as the ops vectors are already set up. 436fa9e4066Sahrens */ 437fa9e4066Sahrens if (zfs_dvnodeops) 438fa9e4066Sahrens return (0); 439fa9e4066Sahrens 440fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template, 441fa9e4066Sahrens &zfs_dvnodeops); 442fa9e4066Sahrens if (error) 443fa9e4066Sahrens return (error); 444fa9e4066Sahrens 445fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template, 446fa9e4066Sahrens &zfs_fvnodeops); 447fa9e4066Sahrens if (error) 448fa9e4066Sahrens return (error); 449fa9e4066Sahrens 450fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template, 451fa9e4066Sahrens &zfs_symvnodeops); 452fa9e4066Sahrens if (error) 453fa9e4066Sahrens return (error); 454fa9e4066Sahrens 455fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template, 456fa9e4066Sahrens &zfs_xdvnodeops); 457fa9e4066Sahrens if (error) 458fa9e4066Sahrens return (error); 459fa9e4066Sahrens 460fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template, 461fa9e4066Sahrens &zfs_evnodeops); 462743a77edSAlan Wright if (error) 463743a77edSAlan Wright return (error); 464743a77edSAlan Wright 465743a77edSAlan Wright error = vn_make_ops(MNTTYPE_ZFS, zfs_sharevnodeops_template, 466743a77edSAlan Wright &zfs_sharevnodeops); 467743a77edSAlan Wright 468743a77edSAlan Wright return (error); 469743a77edSAlan Wright } 470743a77edSAlan Wright 4719e1320c0SMark Shellenbaum int 472743a77edSAlan Wright zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) 473743a77edSAlan Wright { 47489459e17SMark Shellenbaum zfs_acl_ids_t acl_ids; 475743a77edSAlan Wright vattr_t vattr; 476743a77edSAlan Wright znode_t *sharezp; 477743a77edSAlan Wright vnode_t *vp; 478743a77edSAlan Wright znode_t *zp; 479743a77edSAlan Wright int error; 480743a77edSAlan Wright 481743a77edSAlan Wright vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; 482743a77edSAlan Wright vattr.va_type = VDIR; 483743a77edSAlan Wright vattr.va_mode = S_IFDIR|0555; 484743a77edSAlan Wright vattr.va_uid = crgetuid(kcred); 485743a77edSAlan Wright vattr.va_gid = crgetgid(kcred); 486743a77edSAlan Wright 487743a77edSAlan Wright sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP); 488744947dcSTom Erickson ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs)); 489744947dcSTom Erickson sharezp->z_moved = 0; 490743a77edSAlan Wright sharezp->z_unlinked = 0; 491743a77edSAlan Wright sharezp->z_atime_dirty = 0; 492743a77edSAlan Wright sharezp->z_zfsvfs = zfsvfs; 4930a586ceaSMark Shellenbaum sharezp->z_is_sa = zfsvfs->z_use_sa; 494743a77edSAlan Wright 495743a77edSAlan Wright vp = ZTOV(sharezp); 496743a77edSAlan Wright vn_reinit(vp); 497743a77edSAlan Wright vp->v_type = VDIR; 498743a77edSAlan Wright 49989459e17SMark Shellenbaum VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, 50089459e17SMark Shellenbaum kcred, NULL, &acl_ids)); 5010a586ceaSMark Shellenbaum zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); 502743a77edSAlan Wright ASSERT3P(zp, ==, sharezp); 503743a77edSAlan Wright ASSERT(!vn_in_dnlc(ZTOV(sharezp))); /* not valid to move */ 504743a77edSAlan Wright POINTER_INVALIDATE(&sharezp->z_zfsvfs); 505743a77edSAlan Wright error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 506743a77edSAlan Wright ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx); 507743a77edSAlan Wright zfsvfs->z_shares_dir = sharezp->z_id; 508743a77edSAlan Wright 50989459e17SMark Shellenbaum zfs_acl_ids_free(&acl_ids); 510743a77edSAlan Wright ZTOV(sharezp)->v_count = 0; 5110a586ceaSMark Shellenbaum sa_handle_destroy(sharezp->z_sa_hdl); 512743a77edSAlan Wright kmem_cache_free(znode_cache, sharezp); 513fa9e4066Sahrens 514fa9e4066Sahrens return (error); 515fa9e4066Sahrens } 516fa9e4066Sahrens 51772fc53bcSmarks /* 51872fc53bcSmarks * define a couple of values we need available 51972fc53bcSmarks * for both 64 and 32 bit environments. 52072fc53bcSmarks */ 52172fc53bcSmarks #ifndef NBITSMINOR64 52272fc53bcSmarks #define NBITSMINOR64 32 52372fc53bcSmarks #endif 52472fc53bcSmarks #ifndef MAXMAJ64 52572fc53bcSmarks #define MAXMAJ64 0xffffffffUL 52672fc53bcSmarks #endif 52772fc53bcSmarks #ifndef MAXMIN64 52872fc53bcSmarks #define MAXMIN64 0xffffffffUL 52972fc53bcSmarks #endif 53072fc53bcSmarks 53172fc53bcSmarks /* 53272fc53bcSmarks * Create special expldev for ZFS private use. 53372fc53bcSmarks * Can't use standard expldev since it doesn't do 53472fc53bcSmarks * what we want. The standard expldev() takes a 53572fc53bcSmarks * dev32_t in LP64 and expands it to a long dev_t. 53672fc53bcSmarks * We need an interface that takes a dev32_t in ILP32 53772fc53bcSmarks * and expands it to a long dev_t. 53872fc53bcSmarks */ 53972fc53bcSmarks static uint64_t 54072fc53bcSmarks zfs_expldev(dev_t dev) 54172fc53bcSmarks { 54272fc53bcSmarks #ifndef _LP64 54372fc53bcSmarks major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32; 54472fc53bcSmarks return (((uint64_t)major << NBITSMINOR64) | 54572fc53bcSmarks ((minor_t)dev & MAXMIN32)); 54672fc53bcSmarks #else 54772fc53bcSmarks return (dev); 54872fc53bcSmarks #endif 54972fc53bcSmarks } 55072fc53bcSmarks 55172fc53bcSmarks /* 55272fc53bcSmarks * Special cmpldev for ZFS private use. 55372fc53bcSmarks * Can't use standard cmpldev since it takes 55472fc53bcSmarks * a long dev_t and compresses it to dev32_t in 55572fc53bcSmarks * LP64. We need to do a compaction of a long dev_t 55672fc53bcSmarks * to a dev32_t in ILP32. 55772fc53bcSmarks */ 55872fc53bcSmarks dev_t 55972fc53bcSmarks zfs_cmpldev(uint64_t dev) 56072fc53bcSmarks { 56172fc53bcSmarks #ifndef _LP64 56272fc53bcSmarks minor_t minor = (minor_t)dev & MAXMIN64; 56372fc53bcSmarks major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64; 56472fc53bcSmarks 56572fc53bcSmarks if (major > MAXMAJ32 || minor > MAXMIN32) 56672fc53bcSmarks return (NODEV32); 56772fc53bcSmarks 56872fc53bcSmarks return (((dev32_t)major << NBITSMINOR32) | minor); 56972fc53bcSmarks #else 57072fc53bcSmarks return (dev); 57172fc53bcSmarks #endif 57272fc53bcSmarks } 57372fc53bcSmarks 5744ccbb6e7Sahrens static void 5750a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp, 5760a586ceaSMark Shellenbaum dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl) 5774ccbb6e7Sahrens { 578b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs)); 579b5fca8f8Stomee ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id))); 5804ccbb6e7Sahrens 5814ccbb6e7Sahrens mutex_enter(&zp->z_lock); 5824ccbb6e7Sahrens 5830a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl == NULL); 5846638ae1dSMark Shellenbaum ASSERT(zp->z_acl_cached == NULL); 5850a586ceaSMark Shellenbaum if (sa_hdl == NULL) { 5860a586ceaSMark Shellenbaum VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, zp, 5870a586ceaSMark Shellenbaum SA_HDL_SHARED, &zp->z_sa_hdl)); 5880a586ceaSMark Shellenbaum } else { 5890a586ceaSMark Shellenbaum zp->z_sa_hdl = sa_hdl; 5900a586ceaSMark Shellenbaum sa_set_userp(sa_hdl, zp); 5910a586ceaSMark Shellenbaum } 5924ccbb6e7Sahrens 5930a586ceaSMark Shellenbaum zp->z_is_sa = (obj_type == DMU_OT_SA) ? B_TRUE : B_FALSE; 5944ccbb6e7Sahrens 5954ccbb6e7Sahrens /* 5964ccbb6e7Sahrens * Slap on VROOT if we are the root znode 5974ccbb6e7Sahrens */ 5984ccbb6e7Sahrens if (zp->z_id == zfsvfs->z_root) 5994ccbb6e7Sahrens ZTOV(zp)->v_flag |= VROOT; 6004ccbb6e7Sahrens 6014ccbb6e7Sahrens mutex_exit(&zp->z_lock); 6024ccbb6e7Sahrens vn_exists(ZTOV(zp)); 6034ccbb6e7Sahrens } 6044ccbb6e7Sahrens 605874395d5Smaybee void 6064ccbb6e7Sahrens zfs_znode_dmu_fini(znode_t *zp) 6074ccbb6e7Sahrens { 608b5fca8f8Stomee ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) || 609b5fca8f8Stomee zp->z_unlinked || 610874395d5Smaybee RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock)); 6110a586ceaSMark Shellenbaum 6120a586ceaSMark Shellenbaum sa_handle_destroy(zp->z_sa_hdl); 6130a586ceaSMark Shellenbaum zp->z_sa_hdl = NULL; 6144ccbb6e7Sahrens } 6154ccbb6e7Sahrens 616fa9e4066Sahrens /* 617fa9e4066Sahrens * Construct a new znode/vnode and intialize. 618fa9e4066Sahrens * 619fa9e4066Sahrens * This does not do a call to dmu_set_user() that is 620fa9e4066Sahrens * up to the caller to do, in case you don't want to 621fa9e4066Sahrens * return the znode 622fa9e4066Sahrens */ 623ea8dc4b6Seschrock static znode_t * 6240a586ceaSMark Shellenbaum zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, 6250a586ceaSMark Shellenbaum dmu_object_type_t obj_type, sa_handle_t *hdl) 626fa9e4066Sahrens { 627fa9e4066Sahrens znode_t *zp; 628fa9e4066Sahrens vnode_t *vp; 6290a586ceaSMark Shellenbaum uint64_t mode; 6300a586ceaSMark Shellenbaum uint64_t parent; 6310a586ceaSMark Shellenbaum sa_bulk_attr_t bulk[9]; 6320a586ceaSMark Shellenbaum int count = 0; 633fa9e4066Sahrens 634fa9e4066Sahrens zp = kmem_cache_alloc(znode_cache, KM_SLEEP); 635fa9e4066Sahrens 636fa9e4066Sahrens ASSERT(zp->z_dirlocks == NULL); 637b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 638744947dcSTom Erickson zp->z_moved = 0; 639fa9e4066Sahrens 640b5fca8f8Stomee /* 641b5fca8f8Stomee * Defer setting z_zfsvfs until the znode is ready to be a candidate for 642b5fca8f8Stomee * the zfs_znode_move() callback. 643b5fca8f8Stomee */ 6440a586ceaSMark Shellenbaum zp->z_sa_hdl = NULL; 645893a6d32Sahrens zp->z_unlinked = 0; 646fa9e4066Sahrens zp->z_atime_dirty = 0; 647fa9e4066Sahrens zp->z_mapcnt = 0; 6484ccbb6e7Sahrens zp->z_id = db->db_object; 649fa9e4066Sahrens zp->z_blksz = blksz; 650fa9e4066Sahrens zp->z_seq = 0x7A4653; 65167bd71c6Sperrin zp->z_sync_cnt = 0; 6524ccbb6e7Sahrens 6534ccbb6e7Sahrens vp = ZTOV(zp); 6544ccbb6e7Sahrens vn_reinit(vp); 6554ccbb6e7Sahrens 6560a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl); 6570a586ceaSMark Shellenbaum 6580a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8); 6590a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8); 6600a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, 6610a586ceaSMark Shellenbaum &zp->z_size, 8); 6620a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL, 6630a586ceaSMark Shellenbaum &zp->z_links, 8); 6640a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 6650a586ceaSMark Shellenbaum &zp->z_pflags, 8); 6660a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8); 6670a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, 6680a586ceaSMark Shellenbaum &zp->z_atime, 16); 6690a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, 670f1696b23SMark Shellenbaum &zp->z_uid, 8); 6710a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, 672f1696b23SMark Shellenbaum &zp->z_gid, 8); 6730a586ceaSMark Shellenbaum 6740a586ceaSMark Shellenbaum if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { 6750a586ceaSMark Shellenbaum if (hdl == NULL) 6760a586ceaSMark Shellenbaum sa_handle_destroy(zp->z_sa_hdl); 6770a586ceaSMark Shellenbaum kmem_cache_free(znode_cache, zp); 6780a586ceaSMark Shellenbaum return (NULL); 6790a586ceaSMark Shellenbaum } 680fa9e4066Sahrens 6810a586ceaSMark Shellenbaum zp->z_mode = mode; 682fa9e4066Sahrens vp->v_vfsp = zfsvfs->z_parent->z_vfs; 6830a586ceaSMark Shellenbaum 6840a586ceaSMark Shellenbaum vp->v_type = IFTOVT((mode_t)mode); 685fa9e4066Sahrens 686fa9e4066Sahrens switch (vp->v_type) { 687fa9e4066Sahrens case VDIR: 6880a586ceaSMark Shellenbaum if (zp->z_pflags & ZFS_XATTR) { 689fa9e4066Sahrens vn_setops(vp, zfs_xdvnodeops); 690fa9e4066Sahrens vp->v_flag |= V_XATTRDIR; 6914ccbb6e7Sahrens } else { 692fa9e4066Sahrens vn_setops(vp, zfs_dvnodeops); 6934ccbb6e7Sahrens } 6947f6e3e7dSperrin zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */ 695fa9e4066Sahrens break; 696fa9e4066Sahrens case VBLK: 697fa9e4066Sahrens case VCHR: 6980a586ceaSMark Shellenbaum { 6990a586ceaSMark Shellenbaum uint64_t rdev; 7000a586ceaSMark Shellenbaum VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs), 7010a586ceaSMark Shellenbaum &rdev, sizeof (rdev)) == 0); 7020a586ceaSMark Shellenbaum 7030a586ceaSMark Shellenbaum vp->v_rdev = zfs_cmpldev(rdev); 7040a586ceaSMark Shellenbaum } 705fa9e4066Sahrens /*FALLTHROUGH*/ 706fa9e4066Sahrens case VFIFO: 707fa9e4066Sahrens case VSOCK: 708fa9e4066Sahrens case VDOOR: 709fa9e4066Sahrens vn_setops(vp, zfs_fvnodeops); 710fa9e4066Sahrens break; 711fa9e4066Sahrens case VREG: 712fa9e4066Sahrens vp->v_flag |= VMODSORT; 7130a586ceaSMark Shellenbaum if (parent == zfsvfs->z_shares_dir) { 714f1696b23SMark Shellenbaum ASSERT(zp->z_uid == 0 && zp->z_gid == 0); 715743a77edSAlan Wright vn_setops(vp, zfs_sharevnodeops); 7160a586ceaSMark Shellenbaum } else { 717743a77edSAlan Wright vn_setops(vp, zfs_fvnodeops); 7180a586ceaSMark Shellenbaum } 719fa9e4066Sahrens break; 720fa9e4066Sahrens case VLNK: 721fa9e4066Sahrens vn_setops(vp, zfs_symvnodeops); 722fa9e4066Sahrens break; 723fa9e4066Sahrens default: 724fa9e4066Sahrens vn_setops(vp, zfs_evnodeops); 725fa9e4066Sahrens break; 726fa9e4066Sahrens } 727fa9e4066Sahrens 728b5fca8f8Stomee mutex_enter(&zfsvfs->z_znodes_lock); 729b5fca8f8Stomee list_insert_tail(&zfsvfs->z_all_znodes, zp); 730b5fca8f8Stomee membar_producer(); 731b5fca8f8Stomee /* 732b5fca8f8Stomee * Everything else must be valid before assigning z_zfsvfs makes the 733b5fca8f8Stomee * znode eligible for zfs_znode_move(). 734b5fca8f8Stomee */ 735b5fca8f8Stomee zp->z_zfsvfs = zfsvfs; 736b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 737b5fca8f8Stomee 738874395d5Smaybee VFS_HOLD(zfsvfs->z_vfs); 739fa9e4066Sahrens return (zp); 740fa9e4066Sahrens } 741fa9e4066Sahrens 7420a586ceaSMark Shellenbaum static uint64_t empty_xattr; 7430a586ceaSMark Shellenbaum static uint64_t pad[4]; 7440a586ceaSMark Shellenbaum static zfs_acl_phys_t acl_phys; 745fa9e4066Sahrens /* 746fa9e4066Sahrens * Create a new DMU object to hold a zfs znode. 747fa9e4066Sahrens * 748fa9e4066Sahrens * IN: dzp - parent directory for new znode 749fa9e4066Sahrens * vap - file attributes for new znode 750fa9e4066Sahrens * tx - dmu transaction id for zap operations 751fa9e4066Sahrens * cr - credentials of caller 752fa9e4066Sahrens * flag - flags: 753fa9e4066Sahrens * IS_ROOT_NODE - new object will be root 754fa9e4066Sahrens * IS_XATTR - new object is an attribute 755da6c28aaSamw * bonuslen - length of bonus buffer 756da6c28aaSamw * setaclp - File/Dir initial ACL 757da6c28aaSamw * fuidp - Tracks fuid allocation. 758fa9e4066Sahrens * 7594ccbb6e7Sahrens * OUT: zpp - allocated znode 760fa9e4066Sahrens * 761fa9e4066Sahrens */ 762fa9e4066Sahrens void 7634ccbb6e7Sahrens zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, 7640a586ceaSMark Shellenbaum uint_t flag, znode_t **zpp, zfs_acl_ids_t *acl_ids) 765fa9e4066Sahrens { 7660a586ceaSMark Shellenbaum uint64_t crtime[2], atime[2], mtime[2], ctime[2]; 7670a586ceaSMark Shellenbaum uint64_t mode, size, links, parent, pflags; 768744947dcSTom Erickson uint64_t dzp_pflags = 0; 7690a586ceaSMark Shellenbaum uint64_t rdev = 0; 770fa9e4066Sahrens zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 7710a586ceaSMark Shellenbaum dmu_buf_t *db; 772fa9e4066Sahrens timestruc_t now; 7734ccbb6e7Sahrens uint64_t gen, obj; 7740a586ceaSMark Shellenbaum int bonuslen; 7750a586ceaSMark Shellenbaum sa_handle_t *sa_hdl; 7760a586ceaSMark Shellenbaum dmu_object_type_t obj_type; 7770a586ceaSMark Shellenbaum sa_bulk_attr_t sa_attrs[ZPL_END]; 7780a586ceaSMark Shellenbaum int cnt = 0; 7790a586ceaSMark Shellenbaum zfs_acl_locator_cb_t locate = { 0 }; 780fa9e4066Sahrens 781fa9e4066Sahrens ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); 782fa9e4066Sahrens 7831209a471SNeil Perrin if (zfsvfs->z_replay) { 7844ccbb6e7Sahrens obj = vap->va_nodeid; 785fa9e4066Sahrens now = vap->va_ctime; /* see zfs_replay_create() */ 786fa9e4066Sahrens gen = vap->va_nblocks; /* ditto */ 787fa9e4066Sahrens } else { 7884ccbb6e7Sahrens obj = 0; 789fa9e4066Sahrens gethrestime(&now); 790fa9e4066Sahrens gen = dmu_tx_get_txg(tx); 791fa9e4066Sahrens } 792fa9e4066Sahrens 7930a586ceaSMark Shellenbaum obj_type = zfsvfs->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE; 7940a586ceaSMark Shellenbaum bonuslen = (obj_type == DMU_OT_SA) ? 7950a586ceaSMark Shellenbaum DN_MAX_BONUSLEN : ZFS_OLD_ZNODE_PHYS_SIZE; 7960a586ceaSMark Shellenbaum 797fa9e4066Sahrens /* 798fa9e4066Sahrens * Create a new DMU object. 799fa9e4066Sahrens */ 800ea8dc4b6Seschrock /* 801ea8dc4b6Seschrock * There's currently no mechanism for pre-reading the blocks that will 802744947dcSTom Erickson * be needed to allocate a new object, so we accept the small chance 803ea8dc4b6Seschrock * that there will be an i/o error and we will fail one of the 804ea8dc4b6Seschrock * assertions below. 805ea8dc4b6Seschrock */ 806fa9e4066Sahrens if (vap->va_type == VDIR) { 8074a1f0cc9SMark Shellenbaum if (zfsvfs->z_replay) { 80843466aaeSMax Grossman VERIFY0(zap_create_claim_norm(zfsvfs->z_os, obj, 809da6c28aaSamw zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS, 81043466aaeSMax Grossman obj_type, bonuslen, tx)); 811fa9e4066Sahrens } else { 8124ccbb6e7Sahrens obj = zap_create_norm(zfsvfs->z_os, 813da6c28aaSamw zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS, 8140a586ceaSMark Shellenbaum obj_type, bonuslen, tx); 815fa9e4066Sahrens } 816fa9e4066Sahrens } else { 8174a1f0cc9SMark Shellenbaum if (zfsvfs->z_replay) { 81843466aaeSMax Grossman VERIFY0(dmu_object_claim(zfsvfs->z_os, obj, 819fa9e4066Sahrens DMU_OT_PLAIN_FILE_CONTENTS, 0, 82043466aaeSMax Grossman obj_type, bonuslen, tx)); 821fa9e4066Sahrens } else { 8224ccbb6e7Sahrens obj = dmu_object_alloc(zfsvfs->z_os, 823fa9e4066Sahrens DMU_OT_PLAIN_FILE_CONTENTS, 0, 8240a586ceaSMark Shellenbaum obj_type, bonuslen, tx); 825fa9e4066Sahrens } 826fa9e4066Sahrens } 82759e7834dSMark Shellenbaum 82859e7834dSMark Shellenbaum ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); 8290a586ceaSMark Shellenbaum VERIFY(0 == sa_buf_hold(zfsvfs->z_os, obj, NULL, &db)); 830fa9e4066Sahrens 831fa9e4066Sahrens /* 832fa9e4066Sahrens * If this is the root, fix up the half-initialized parent pointer 833fa9e4066Sahrens * to reference the just-allocated physical data area. 834fa9e4066Sahrens */ 835fa9e4066Sahrens if (flag & IS_ROOT_NODE) { 8364ccbb6e7Sahrens dzp->z_id = obj; 8370a586ceaSMark Shellenbaum } else { 8380a586ceaSMark Shellenbaum dzp_pflags = dzp->z_pflags; 839fa9e4066Sahrens } 840fa9e4066Sahrens 841fa9e4066Sahrens /* 842fa9e4066Sahrens * If parent is an xattr, so am I. 843fa9e4066Sahrens */ 8440a586ceaSMark Shellenbaum if (dzp_pflags & ZFS_XATTR) { 845fa9e4066Sahrens flag |= IS_XATTR; 846fa9e4066Sahrens } 847fa9e4066Sahrens 848da6c28aaSamw if (zfsvfs->z_use_fuids) 8490a586ceaSMark Shellenbaum pflags = ZFS_ARCHIVE | ZFS_AV_MODIFIED; 8500a586ceaSMark Shellenbaum else 8510a586ceaSMark Shellenbaum pflags = 0; 852da6c28aaSamw 853fa9e4066Sahrens if (vap->va_type == VDIR) { 8540a586ceaSMark Shellenbaum size = 2; /* contents ("." and "..") */ 8550a586ceaSMark Shellenbaum links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1; 8560a586ceaSMark Shellenbaum } else { 8570a586ceaSMark Shellenbaum size = links = 0; 8580a586ceaSMark Shellenbaum } 8590a586ceaSMark Shellenbaum 8600a586ceaSMark Shellenbaum if (vap->va_type == VBLK || vap->va_type == VCHR) { 8610a586ceaSMark Shellenbaum rdev = zfs_expldev(vap->va_rdev); 862fa9e4066Sahrens } 863fa9e4066Sahrens 8640a586ceaSMark Shellenbaum parent = dzp->z_id; 8650a586ceaSMark Shellenbaum mode = acl_ids->z_mode; 866fa9e4066Sahrens if (flag & IS_XATTR) 8670a586ceaSMark Shellenbaum pflags |= ZFS_XATTR; 868fa9e4066Sahrens 8690a586ceaSMark Shellenbaum /* 8700a586ceaSMark Shellenbaum * No execs denied will be deterimed when zfs_mode_compute() is called. 8710a586ceaSMark Shellenbaum */ 8720a586ceaSMark Shellenbaum pflags |= acl_ids->z_aclp->z_hints & 8730a586ceaSMark Shellenbaum (ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|ZFS_ACL_AUTO_INHERIT| 8740a586ceaSMark Shellenbaum ZFS_ACL_DEFAULTED|ZFS_ACL_PROTECTED); 875fa9e4066Sahrens 8760a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, crtime); 8770a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, ctime); 878fa9e4066Sahrens 879fa9e4066Sahrens if (vap->va_mask & AT_ATIME) { 8800a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&vap->va_atime, atime); 881fa9e4066Sahrens } else { 8820a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, atime); 883fa9e4066Sahrens } 884fa9e4066Sahrens 885fa9e4066Sahrens if (vap->va_mask & AT_MTIME) { 8860a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&vap->va_mtime, mtime); 8870a586ceaSMark Shellenbaum } else { 8880a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, mtime); 8890a586ceaSMark Shellenbaum } 8900a586ceaSMark Shellenbaum 8910a586ceaSMark Shellenbaum /* Now add in all of the "SA" attributes */ 8920a586ceaSMark Shellenbaum VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, NULL, SA_HDL_SHARED, 8930a586ceaSMark Shellenbaum &sa_hdl)); 8940a586ceaSMark Shellenbaum 8950a586ceaSMark Shellenbaum /* 8960a586ceaSMark Shellenbaum * Setup the array of attributes to be replaced/set on the new file 8970a586ceaSMark Shellenbaum * 8980a586ceaSMark Shellenbaum * order for DMU_OT_ZNODE is critical since it needs to be constructed 8990a586ceaSMark Shellenbaum * in the old znode_phys_t format. Don't change this ordering 9000a586ceaSMark Shellenbaum */ 9010a586ceaSMark Shellenbaum 9020a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9030a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs), 9040a586ceaSMark Shellenbaum NULL, &atime, 16); 9050a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs), 9060a586ceaSMark Shellenbaum NULL, &mtime, 16); 9070a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs), 9080a586ceaSMark Shellenbaum NULL, &ctime, 16); 9090a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs), 9100a586ceaSMark Shellenbaum NULL, &crtime, 16); 9110a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs), 9120a586ceaSMark Shellenbaum NULL, &gen, 8); 9130a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs), 9140a586ceaSMark Shellenbaum NULL, &mode, 8); 9150a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs), 9160a586ceaSMark Shellenbaum NULL, &size, 8); 9170a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs), 9180a586ceaSMark Shellenbaum NULL, &parent, 8); 919fa9e4066Sahrens } else { 9200a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs), 9210a586ceaSMark Shellenbaum NULL, &mode, 8); 9220a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs), 9230a586ceaSMark Shellenbaum NULL, &size, 8); 9240a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs), 9250a586ceaSMark Shellenbaum NULL, &gen, 8); 9260a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL, 9270a586ceaSMark Shellenbaum &acl_ids->z_fuid, 8); 9280a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL, 9290a586ceaSMark Shellenbaum &acl_ids->z_fgid, 8); 9300a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs), 9310a586ceaSMark Shellenbaum NULL, &parent, 8); 9320a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs), 9330a586ceaSMark Shellenbaum NULL, &pflags, 8); 9340a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs), 9350a586ceaSMark Shellenbaum NULL, &atime, 16); 9360a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs), 9370a586ceaSMark Shellenbaum NULL, &mtime, 16); 9380a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs), 9390a586ceaSMark Shellenbaum NULL, &ctime, 16); 9400a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs), 9410a586ceaSMark Shellenbaum NULL, &crtime, 16); 9420a586ceaSMark Shellenbaum } 9430a586ceaSMark Shellenbaum 9440a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zfsvfs), NULL, &links, 8); 9450a586ceaSMark Shellenbaum 9460a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9470a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zfsvfs), NULL, 9480a586ceaSMark Shellenbaum &empty_xattr, 8); 9490a586ceaSMark Shellenbaum } 9500a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE || 9510a586ceaSMark Shellenbaum (vap->va_type == VBLK || vap->va_type == VCHR)) { 9520a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zfsvfs), 9530a586ceaSMark Shellenbaum NULL, &rdev, 8); 9540a586ceaSMark Shellenbaum 955fa9e4066Sahrens } 9560a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9570a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs), 9580a586ceaSMark Shellenbaum NULL, &pflags, 8); 9590a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL, 9600a586ceaSMark Shellenbaum &acl_ids->z_fuid, 8); 9610a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL, 9620a586ceaSMark Shellenbaum &acl_ids->z_fgid, 8); 9630a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zfsvfs), NULL, pad, 9640a586ceaSMark Shellenbaum sizeof (uint64_t) * 4); 9650a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zfsvfs), NULL, 9660a586ceaSMark Shellenbaum &acl_phys, sizeof (zfs_acl_phys_t)); 9670a586ceaSMark Shellenbaum } else if (acl_ids->z_aclp->z_version >= ZFS_ACL_VERSION_FUID) { 9680a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zfsvfs), NULL, 9690a586ceaSMark Shellenbaum &acl_ids->z_aclp->z_acl_count, 8); 9700a586ceaSMark Shellenbaum locate.cb_aclp = acl_ids->z_aclp; 9710a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs), 9720a586ceaSMark Shellenbaum zfs_acl_data_locator, &locate, 9730a586ceaSMark Shellenbaum acl_ids->z_aclp->z_acl_bytes); 97427dd1e87SMark Shellenbaum mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags, 97527dd1e87SMark Shellenbaum acl_ids->z_fuid, acl_ids->z_fgid); 9760a586ceaSMark Shellenbaum } 9770a586ceaSMark Shellenbaum 9780a586ceaSMark Shellenbaum VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0); 9790a586ceaSMark Shellenbaum 980874395d5Smaybee if (!(flag & IS_ROOT_NODE)) { 9810a586ceaSMark Shellenbaum *zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, sa_hdl); 9820a586ceaSMark Shellenbaum ASSERT(*zpp != NULL); 983874395d5Smaybee } else { 984874395d5Smaybee /* 985874395d5Smaybee * If we are creating the root node, the "parent" we 986874395d5Smaybee * passed in is the znode for the root. 987874395d5Smaybee */ 988874395d5Smaybee *zpp = dzp; 9890a586ceaSMark Shellenbaum 9900a586ceaSMark Shellenbaum (*zpp)->z_sa_hdl = sa_hdl; 991874395d5Smaybee } 9920a586ceaSMark Shellenbaum 9930a586ceaSMark Shellenbaum (*zpp)->z_pflags = pflags; 9940a586ceaSMark Shellenbaum (*zpp)->z_mode = mode; 99559e7834dSMark Shellenbaum 9968f2529deSMark Shellenbaum if (vap->va_mask & AT_XVATTR) 9978f2529deSMark Shellenbaum zfs_xvattr_set(*zpp, (xvattr_t *)vap, tx); 9988f2529deSMark Shellenbaum 9990a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE || 10000a586ceaSMark Shellenbaum acl_ids->z_aclp->z_version < ZFS_ACL_VERSION_FUID) { 100143466aaeSMax Grossman VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx)); 10020a586ceaSMark Shellenbaum } 100359e7834dSMark Shellenbaum ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); 1004fa9e4066Sahrens } 1005fa9e4066Sahrens 10060a586ceaSMark Shellenbaum /* 1007f7170741SWill Andrews * Update in-core attributes. It is assumed the caller will be doing an 1008f7170741SWill Andrews * sa_bulk_update to push the changes out. 10090a586ceaSMark Shellenbaum */ 1010da6c28aaSamw void 10110a586ceaSMark Shellenbaum zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) 1012da6c28aaSamw { 1013da6c28aaSamw xoptattr_t *xoap; 1014da6c28aaSamw 1015da6c28aaSamw xoap = xva_getxoptattr(xvap); 1016da6c28aaSamw ASSERT(xoap); 1017da6c28aaSamw 1018da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { 10190a586ceaSMark Shellenbaum uint64_t times[2]; 10200a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&xoap->xoa_createtime, times); 10210a586ceaSMark Shellenbaum (void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), 10220a586ceaSMark Shellenbaum ×, sizeof (times), tx); 1023da6c28aaSamw XVA_SET_RTN(xvap, XAT_CREATETIME); 1024da6c28aaSamw } 1025da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 10260a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly, 10270a586ceaSMark Shellenbaum zp->z_pflags, tx); 1028da6c28aaSamw XVA_SET_RTN(xvap, XAT_READONLY); 1029da6c28aaSamw } 1030da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 10310a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden, 10320a586ceaSMark Shellenbaum zp->z_pflags, tx); 1033da6c28aaSamw XVA_SET_RTN(xvap, XAT_HIDDEN); 1034da6c28aaSamw } 1035da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 10360a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system, 10370a586ceaSMark Shellenbaum zp->z_pflags, tx); 1038da6c28aaSamw XVA_SET_RTN(xvap, XAT_SYSTEM); 1039da6c28aaSamw } 1040da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 10410a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive, 10420a586ceaSMark Shellenbaum zp->z_pflags, tx); 1043da6c28aaSamw XVA_SET_RTN(xvap, XAT_ARCHIVE); 1044da6c28aaSamw } 1045da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { 10460a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable, 10470a586ceaSMark Shellenbaum zp->z_pflags, tx); 1048da6c28aaSamw XVA_SET_RTN(xvap, XAT_IMMUTABLE); 1049da6c28aaSamw } 1050da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { 10510a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink, 10520a586ceaSMark Shellenbaum zp->z_pflags, tx); 1053da6c28aaSamw XVA_SET_RTN(xvap, XAT_NOUNLINK); 1054da6c28aaSamw } 1055da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { 10560a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly, 10570a586ceaSMark Shellenbaum zp->z_pflags, tx); 1058da6c28aaSamw XVA_SET_RTN(xvap, XAT_APPENDONLY); 1059da6c28aaSamw } 1060da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { 10610a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump, 10620a586ceaSMark Shellenbaum zp->z_pflags, tx); 1063da6c28aaSamw XVA_SET_RTN(xvap, XAT_NODUMP); 1064da6c28aaSamw } 1065da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { 10660a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque, 10670a586ceaSMark Shellenbaum zp->z_pflags, tx); 1068da6c28aaSamw XVA_SET_RTN(xvap, XAT_OPAQUE); 1069da6c28aaSamw } 1070da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { 1071da6c28aaSamw ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED, 10720a586ceaSMark Shellenbaum xoap->xoa_av_quarantined, zp->z_pflags, tx); 1073da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); 1074da6c28aaSamw } 1075da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { 10760a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified, 10770a586ceaSMark Shellenbaum zp->z_pflags, tx); 1078da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_MODIFIED); 1079da6c28aaSamw } 1080da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { 10810a586ceaSMark Shellenbaum zfs_sa_set_scanstamp(zp, xvap, tx); 1082da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP); 1083da6c28aaSamw } 10847a286c47SDai Ngo if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { 10850a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse, 10860a586ceaSMark Shellenbaum zp->z_pflags, tx); 10877a286c47SDai Ngo XVA_SET_RTN(xvap, XAT_REPARSE); 10887a286c47SDai Ngo } 1089fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { 1090fd9ee8b5Sjoyce mcintosh ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline, 1091fd9ee8b5Sjoyce mcintosh zp->z_pflags, tx); 1092fd9ee8b5Sjoyce mcintosh XVA_SET_RTN(xvap, XAT_OFFLINE); 1093fd9ee8b5Sjoyce mcintosh } 1094fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { 1095fd9ee8b5Sjoyce mcintosh ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse, 1096fd9ee8b5Sjoyce mcintosh zp->z_pflags, tx); 1097fd9ee8b5Sjoyce mcintosh XVA_SET_RTN(xvap, XAT_SPARSE); 1098fd9ee8b5Sjoyce mcintosh } 1099da6c28aaSamw } 1100da6c28aaSamw 1101fa9e4066Sahrens int 1102fa9e4066Sahrens zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp) 1103fa9e4066Sahrens { 1104fa9e4066Sahrens dmu_object_info_t doi; 1105fa9e4066Sahrens dmu_buf_t *db; 1106fa9e4066Sahrens znode_t *zp; 1107ea8dc4b6Seschrock int err; 11080a586ceaSMark Shellenbaum sa_handle_t *hdl; 1109fa9e4066Sahrens 1110fa9e4066Sahrens *zpp = NULL; 1111fa9e4066Sahrens 1112fa9e4066Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); 1113fa9e4066Sahrens 11140a586ceaSMark Shellenbaum err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db); 1115ea8dc4b6Seschrock if (err) { 1116fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1117ea8dc4b6Seschrock return (err); 1118fa9e4066Sahrens } 1119fa9e4066Sahrens 1120fa9e4066Sahrens dmu_object_info_from_db(db, &doi); 11210a586ceaSMark Shellenbaum if (doi.doi_bonus_type != DMU_OT_SA && 11220a586ceaSMark Shellenbaum (doi.doi_bonus_type != DMU_OT_ZNODE || 11230a586ceaSMark Shellenbaum (doi.doi_bonus_type == DMU_OT_ZNODE && 11240a586ceaSMark Shellenbaum doi.doi_bonus_size < sizeof (znode_phys_t)))) { 11250a586ceaSMark Shellenbaum sa_buf_rele(db, NULL); 1126fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1127be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1128fa9e4066Sahrens } 1129fa9e4066Sahrens 11300a586ceaSMark Shellenbaum hdl = dmu_buf_get_user(db); 11310a586ceaSMark Shellenbaum if (hdl != NULL) { 11320a586ceaSMark Shellenbaum zp = sa_get_userdata(hdl); 11330a586ceaSMark Shellenbaum 1134fa9e4066Sahrens 11354ccbb6e7Sahrens /* 11360a586ceaSMark Shellenbaum * Since "SA" does immediate eviction we 11370a586ceaSMark Shellenbaum * should never find a sa handle that doesn't 11380a586ceaSMark Shellenbaum * know about the znode. 11394ccbb6e7Sahrens */ 11400a586ceaSMark Shellenbaum 11410a586ceaSMark Shellenbaum ASSERT3P(zp, !=, NULL); 11420a586ceaSMark Shellenbaum 11430a586ceaSMark Shellenbaum mutex_enter(&zp->z_lock); 1144fa9e4066Sahrens ASSERT3U(zp->z_id, ==, obj_num); 1145893a6d32Sahrens if (zp->z_unlinked) { 1146be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 1147fa9e4066Sahrens } else { 11484ccbb6e7Sahrens VN_HOLD(ZTOV(zp)); 11494ccbb6e7Sahrens *zpp = zp; 11504ccbb6e7Sahrens err = 0; 1151fa9e4066Sahrens } 1152fa9e4066Sahrens mutex_exit(&zp->z_lock); 1153eaef6a96SRichard Yao sa_buf_rele(db, NULL); 1154ea8dc4b6Seschrock ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 11554ccbb6e7Sahrens return (err); 1156fa9e4066Sahrens } 1157fa9e4066Sahrens 1158fa9e4066Sahrens /* 1159fa9e4066Sahrens * Not found create new znode/vnode 116059e7834dSMark Shellenbaum * but only if file exists. 116159e7834dSMark Shellenbaum * 116259e7834dSMark Shellenbaum * There is a small window where zfs_vget() could 116359e7834dSMark Shellenbaum * find this object while a file create is still in 11640a586ceaSMark Shellenbaum * progress. This is checked for in zfs_znode_alloc() 11650a586ceaSMark Shellenbaum * 11660a586ceaSMark Shellenbaum * if zfs_znode_alloc() fails it will drop the hold on the 11670a586ceaSMark Shellenbaum * bonus buffer. 1168fa9e4066Sahrens */ 11690a586ceaSMark Shellenbaum zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size, 11700a586ceaSMark Shellenbaum doi.doi_bonus_type, NULL); 11710a586ceaSMark Shellenbaum if (zp == NULL) { 1172be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 11730a586ceaSMark Shellenbaum } else { 11740a586ceaSMark Shellenbaum *zpp = zp; 117559e7834dSMark Shellenbaum } 1176ea8dc4b6Seschrock ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 117759e7834dSMark Shellenbaum return (err); 1178fa9e4066Sahrens } 1179fa9e4066Sahrens 1180f18faf3fSek int 1181f18faf3fSek zfs_rezget(znode_t *zp) 1182f18faf3fSek { 1183f18faf3fSek zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1184f18faf3fSek dmu_object_info_t doi; 1185f18faf3fSek dmu_buf_t *db; 1186f18faf3fSek uint64_t obj_num = zp->z_id; 11870a586ceaSMark Shellenbaum uint64_t mode; 11880a586ceaSMark Shellenbaum sa_bulk_attr_t bulk[8]; 1189f18faf3fSek int err; 11900a586ceaSMark Shellenbaum int count = 0; 11910a586ceaSMark Shellenbaum uint64_t gen; 1192f18faf3fSek 1193f18faf3fSek ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); 1194f18faf3fSek 11950a586ceaSMark Shellenbaum mutex_enter(&zp->z_acl_lock); 11960a586ceaSMark Shellenbaum if (zp->z_acl_cached) { 11970a586ceaSMark Shellenbaum zfs_acl_free(zp->z_acl_cached); 11980a586ceaSMark Shellenbaum zp->z_acl_cached = NULL; 11990a586ceaSMark Shellenbaum } 12000a586ceaSMark Shellenbaum 12010a586ceaSMark Shellenbaum mutex_exit(&zp->z_acl_lock); 12020a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl == NULL); 12030a586ceaSMark Shellenbaum err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db); 1204f18faf3fSek if (err) { 1205f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1206f18faf3fSek return (err); 1207f18faf3fSek } 1208f18faf3fSek 1209f18faf3fSek dmu_object_info_from_db(db, &doi); 12100a586ceaSMark Shellenbaum if (doi.doi_bonus_type != DMU_OT_SA && 12110a586ceaSMark Shellenbaum (doi.doi_bonus_type != DMU_OT_ZNODE || 12120a586ceaSMark Shellenbaum (doi.doi_bonus_type == DMU_OT_ZNODE && 12130a586ceaSMark Shellenbaum doi.doi_bonus_size < sizeof (znode_phys_t)))) { 12140a586ceaSMark Shellenbaum sa_buf_rele(db, NULL); 1215f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1216be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1217f18faf3fSek } 1218f18faf3fSek 12190a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs, zp, db, doi.doi_bonus_type, NULL); 12200a586ceaSMark Shellenbaum 12210a586ceaSMark Shellenbaum /* reload cached values */ 12220a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, 12230a586ceaSMark Shellenbaum &gen, sizeof (gen)); 12240a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, 12250a586ceaSMark Shellenbaum &zp->z_size, sizeof (zp->z_size)); 12260a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL, 12270a586ceaSMark Shellenbaum &zp->z_links, sizeof (zp->z_links)); 12280a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 12290a586ceaSMark Shellenbaum &zp->z_pflags, sizeof (zp->z_pflags)); 12300a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, 12310a586ceaSMark Shellenbaum &zp->z_atime, sizeof (zp->z_atime)); 12320a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, 1233f1696b23SMark Shellenbaum &zp->z_uid, sizeof (zp->z_uid)); 12340a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, 1235f1696b23SMark Shellenbaum &zp->z_gid, sizeof (zp->z_gid)); 12360a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, 12370a586ceaSMark Shellenbaum &mode, sizeof (mode)); 12380a586ceaSMark Shellenbaum 12390a586ceaSMark Shellenbaum if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) { 12400a586ceaSMark Shellenbaum zfs_znode_dmu_fini(zp); 1241f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1242be6fd75aSMatthew Ahrens return (SET_ERROR(EIO)); 1243f18faf3fSek } 1244f18faf3fSek 12451412a1a2SMark Shellenbaum zp->z_mode = mode; 12461412a1a2SMark Shellenbaum 12470a586ceaSMark Shellenbaum if (gen != zp->z_gen) { 12480a586ceaSMark Shellenbaum zfs_znode_dmu_fini(zp); 12490a586ceaSMark Shellenbaum ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1250be6fd75aSMatthew Ahrens return (SET_ERROR(EIO)); 12516638ae1dSMark Shellenbaum } 12526638ae1dSMark Shellenbaum 12530a586ceaSMark Shellenbaum zp->z_unlinked = (zp->z_links == 0); 12546166ad1cSek zp->z_blksz = doi.doi_data_block_size; 1255f18faf3fSek 1256f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1257f18faf3fSek 1258f18faf3fSek return (0); 1259f18faf3fSek } 1260f18faf3fSek 1261fa9e4066Sahrens void 1262fa9e4066Sahrens zfs_znode_delete(znode_t *zp, dmu_tx_t *tx) 1263fa9e4066Sahrens { 1264fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1265cdb0ab79Smaybee objset_t *os = zfsvfs->z_os; 12664ccbb6e7Sahrens uint64_t obj = zp->z_id; 12671412a1a2SMark Shellenbaum uint64_t acl_obj = zfs_external_acl(zp); 1268fa9e4066Sahrens 12694ccbb6e7Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); 12701412a1a2SMark Shellenbaum if (acl_obj) { 12711412a1a2SMark Shellenbaum VERIFY(!zp->z_is_sa); 1272cdb0ab79Smaybee VERIFY(0 == dmu_object_free(os, acl_obj, tx)); 12731412a1a2SMark Shellenbaum } 1274cdb0ab79Smaybee VERIFY(0 == dmu_object_free(os, obj, tx)); 12754ccbb6e7Sahrens zfs_znode_dmu_fini(zp); 12764ccbb6e7Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); 1277874395d5Smaybee zfs_znode_free(zp); 1278fa9e4066Sahrens } 1279fa9e4066Sahrens 1280fa9e4066Sahrens void 1281fa9e4066Sahrens zfs_zinactive(znode_t *zp) 1282fa9e4066Sahrens { 1283fa9e4066Sahrens vnode_t *vp = ZTOV(zp); 1284fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1285fa9e4066Sahrens uint64_t z_id = zp->z_id; 1286fa9e4066Sahrens 12870a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl); 1288fa9e4066Sahrens 1289fa9e4066Sahrens /* 1290fa9e4066Sahrens * Don't allow a zfs_zget() while were trying to release this znode 1291fa9e4066Sahrens */ 1292fa9e4066Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id); 1293fa9e4066Sahrens 1294fa9e4066Sahrens mutex_enter(&zp->z_lock); 1295fa9e4066Sahrens mutex_enter(&vp->v_lock); 1296fa9e4066Sahrens vp->v_count--; 1297fa9e4066Sahrens if (vp->v_count > 0 || vn_has_cached_data(vp)) { 1298fa9e4066Sahrens /* 1299fa9e4066Sahrens * If the hold count is greater than zero, somebody has 1300fa9e4066Sahrens * obtained a new reference on this znode while we were 1301fa9e4066Sahrens * processing it here, so we are done. If we still have 1302fa9e4066Sahrens * mapped pages then we are also done, since we don't 1303fa9e4066Sahrens * want to inactivate the znode until the pages get pushed. 1304fa9e4066Sahrens * 1305fa9e4066Sahrens * XXX - if vn_has_cached_data(vp) is true, but count == 0, 1306fa9e4066Sahrens * this seems like it would leave the znode hanging with 1307fa9e4066Sahrens * no chance to go inactive... 1308fa9e4066Sahrens */ 1309fa9e4066Sahrens mutex_exit(&vp->v_lock); 1310fa9e4066Sahrens mutex_exit(&zp->z_lock); 1311fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1312fa9e4066Sahrens return; 1313fa9e4066Sahrens } 1314fa9e4066Sahrens mutex_exit(&vp->v_lock); 1315fa9e4066Sahrens 1316fa9e4066Sahrens /* 1317fa9e4066Sahrens * If this was the last reference to a file with no links, 1318fa9e4066Sahrens * remove the file from the file system. 1319fa9e4066Sahrens */ 1320893a6d32Sahrens if (zp->z_unlinked) { 1321fa9e4066Sahrens mutex_exit(&zp->z_lock); 1322fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1323893a6d32Sahrens zfs_rmnode(zp); 1324fa9e4066Sahrens return; 1325fa9e4066Sahrens } 13260a586ceaSMark Shellenbaum 1327fa9e4066Sahrens mutex_exit(&zp->z_lock); 13284ccbb6e7Sahrens zfs_znode_dmu_fini(zp); 1329fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1330874395d5Smaybee zfs_znode_free(zp); 1331fa9e4066Sahrens } 1332fa9e4066Sahrens 1333fa9e4066Sahrens void 1334fa9e4066Sahrens zfs_znode_free(znode_t *zp) 1335fa9e4066Sahrens { 1336fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1337fa9e4066Sahrens 1338874395d5Smaybee vn_invalid(ZTOV(zp)); 1339874395d5Smaybee 1340b5fca8f8Stomee ASSERT(ZTOV(zp)->v_count == 0); 1341b5fca8f8Stomee 1342fa9e4066Sahrens mutex_enter(&zfsvfs->z_znodes_lock); 1343b5fca8f8Stomee POINTER_INVALIDATE(&zp->z_zfsvfs); 1344fa9e4066Sahrens list_remove(&zfsvfs->z_all_znodes, zp); 1345fa9e4066Sahrens mutex_exit(&zfsvfs->z_znodes_lock); 1346fa9e4066Sahrens 1347d47621a4STim Haley if (zp->z_acl_cached) { 1348d47621a4STim Haley zfs_acl_free(zp->z_acl_cached); 1349d47621a4STim Haley zp->z_acl_cached = NULL; 1350d47621a4STim Haley } 1351d47621a4STim Haley 1352fa9e4066Sahrens kmem_cache_free(znode_cache, zp); 1353874395d5Smaybee 1354874395d5Smaybee VFS_RELE(zfsvfs->z_vfs); 1355fa9e4066Sahrens } 1356fa9e4066Sahrens 1357fa9e4066Sahrens void 13580a586ceaSMark Shellenbaum zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2], 13590a586ceaSMark Shellenbaum uint64_t ctime[2], boolean_t have_tx) 1360fa9e4066Sahrens { 1361fa9e4066Sahrens timestruc_t now; 1362fa9e4066Sahrens 1363fa9e4066Sahrens gethrestime(&now); 1364fa9e4066Sahrens 13650a586ceaSMark Shellenbaum if (have_tx) { /* will sa_bulk_update happen really soon? */ 1366fa9e4066Sahrens zp->z_atime_dirty = 0; 1367fa9e4066Sahrens zp->z_seq++; 1368fa9e4066Sahrens } else { 1369fa9e4066Sahrens zp->z_atime_dirty = 1; 1370fa9e4066Sahrens } 1371fa9e4066Sahrens 13720a586ceaSMark Shellenbaum if (flag & AT_ATIME) { 13730a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, zp->z_atime); 13740a586ceaSMark Shellenbaum } 1375fa9e4066Sahrens 1376da6c28aaSamw if (flag & AT_MTIME) { 13770a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, mtime); 13780a586ceaSMark Shellenbaum if (zp->z_zfsvfs->z_use_fuids) { 13790a586ceaSMark Shellenbaum zp->z_pflags |= (ZFS_ARCHIVE | 13800a586ceaSMark Shellenbaum ZFS_AV_MODIFIED); 13810a586ceaSMark Shellenbaum } 1382da6c28aaSamw } 1383fa9e4066Sahrens 1384da6c28aaSamw if (flag & AT_CTIME) { 13850a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, ctime); 1386da6c28aaSamw if (zp->z_zfsvfs->z_use_fuids) 13870a586ceaSMark Shellenbaum zp->z_pflags |= ZFS_ARCHIVE; 1388da6c28aaSamw } 1389fa9e4066Sahrens } 1390fa9e4066Sahrens 1391fa9e4066Sahrens /* 1392104e2ed7Sperrin * Grow the block size for a file. 1393fa9e4066Sahrens * 1394fa9e4066Sahrens * IN: zp - znode of file to free data in. 1395fa9e4066Sahrens * size - requested block size 1396fa9e4066Sahrens * tx - open transaction. 1397fa9e4066Sahrens * 1398fa9e4066Sahrens * NOTE: this function assumes that the znode is write locked. 1399fa9e4066Sahrens */ 1400104e2ed7Sperrin void 1401fa9e4066Sahrens zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx) 1402fa9e4066Sahrens { 1403fa9e4066Sahrens int error; 1404fa9e4066Sahrens u_longlong_t dummy; 1405fa9e4066Sahrens 1406fa9e4066Sahrens if (size <= zp->z_blksz) 1407104e2ed7Sperrin return; 1408fa9e4066Sahrens /* 1409fa9e4066Sahrens * If the file size is already greater than the current blocksize, 1410fa9e4066Sahrens * we will not grow. If there is more than one block in a file, 1411fa9e4066Sahrens * the blocksize cannot change. 1412fa9e4066Sahrens */ 14130a586ceaSMark Shellenbaum if (zp->z_blksz && zp->z_size > zp->z_blksz) 1414104e2ed7Sperrin return; 1415fa9e4066Sahrens 1416fa9e4066Sahrens error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id, 1417fa9e4066Sahrens size, 0, tx); 14180a586ceaSMark Shellenbaum 1419fa9e4066Sahrens if (error == ENOTSUP) 1420104e2ed7Sperrin return; 1421fb09f5aaSMadhav Suresh ASSERT0(error); 1422fa9e4066Sahrens 1423fa9e4066Sahrens /* What blocksize did we actually get? */ 14240a586ceaSMark Shellenbaum dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy); 1425fa9e4066Sahrens } 1426fa9e4066Sahrens 1427fa9e4066Sahrens /* 1428fa9e4066Sahrens * This is a dummy interface used when pvn_vplist_dirty() should *not* 1429fa9e4066Sahrens * be calling back into the fs for a putpage(). E.g.: when truncating 1430fa9e4066Sahrens * a file, the pages being "thrown away* don't need to be written out. 1431fa9e4066Sahrens */ 1432fa9e4066Sahrens /* ARGSUSED */ 1433fa9e4066Sahrens static int 1434fa9e4066Sahrens zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, 1435fa9e4066Sahrens int flags, cred_t *cr) 1436fa9e4066Sahrens { 1437fa9e4066Sahrens ASSERT(0); 1438fa9e4066Sahrens return (0); 1439fa9e4066Sahrens } 1440fa9e4066Sahrens 1441fa9e4066Sahrens /* 1442cdb0ab79Smaybee * Increase the file length 1443fa9e4066Sahrens * 1444fa9e4066Sahrens * IN: zp - znode of file to free data in. 1445cdb0ab79Smaybee * end - new end-of-file 1446fa9e4066Sahrens * 14474bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1448fa9e4066Sahrens */ 1449cdb0ab79Smaybee static int 1450cdb0ab79Smaybee zfs_extend(znode_t *zp, uint64_t end) 1451fa9e4066Sahrens { 14525730cc9aSmaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1453cdb0ab79Smaybee dmu_tx_t *tx; 14545730cc9aSmaybee rl_t *rl; 1455cdb0ab79Smaybee uint64_t newblksz; 1456104e2ed7Sperrin int error; 1457fa9e4066Sahrens 14585730cc9aSmaybee /* 1459cdb0ab79Smaybee * We will change zp_size, lock the whole file. 14605730cc9aSmaybee */ 1461cdb0ab79Smaybee rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); 14625730cc9aSmaybee 1463fa9e4066Sahrens /* 1464fa9e4066Sahrens * Nothing to do if file already at desired length. 1465fa9e4066Sahrens */ 14660a586ceaSMark Shellenbaum if (end <= zp->z_size) { 1467c5c6ffa0Smaybee zfs_range_unlock(rl); 1468fa9e4066Sahrens return (0); 1469fa9e4066Sahrens } 14705730cc9aSmaybee tx = dmu_tx_create(zfsvfs->z_os); 14710a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 14720a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 1473cdb0ab79Smaybee if (end > zp->z_blksz && 14745730cc9aSmaybee (!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) { 1475fa9e4066Sahrens /* 1476fa9e4066Sahrens * We are growing the file past the current block size. 1477fa9e4066Sahrens */ 1478fa9e4066Sahrens if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) { 1479b5152584SMatthew Ahrens /* 1480b5152584SMatthew Ahrens * File's blocksize is already larger than the 1481b5152584SMatthew Ahrens * "recordsize" property. Only let it grow to 1482b5152584SMatthew Ahrens * the next power of 2. 1483b5152584SMatthew Ahrens */ 1484fa9e4066Sahrens ASSERT(!ISP2(zp->z_blksz)); 1485b5152584SMatthew Ahrens newblksz = MIN(end, 1 << highbit64(zp->z_blksz)); 1486fa9e4066Sahrens } else { 1487cdb0ab79Smaybee newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz); 1488fa9e4066Sahrens } 1489cdb0ab79Smaybee dmu_tx_hold_write(tx, zp->z_id, 0, newblksz); 1490cdb0ab79Smaybee } else { 1491cdb0ab79Smaybee newblksz = 0; 14925730cc9aSmaybee } 14935730cc9aSmaybee 1494e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 14955730cc9aSmaybee if (error) { 14965730cc9aSmaybee dmu_tx_abort(tx); 1497c5c6ffa0Smaybee zfs_range_unlock(rl); 14985730cc9aSmaybee return (error); 1499fa9e4066Sahrens } 15005730cc9aSmaybee 1501cdb0ab79Smaybee if (newblksz) 1502cdb0ab79Smaybee zfs_grow_blocksize(zp, newblksz, tx); 15035730cc9aSmaybee 15040a586ceaSMark Shellenbaum zp->z_size = end; 15050a586ceaSMark Shellenbaum 15060a586ceaSMark Shellenbaum VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs), 15070a586ceaSMark Shellenbaum &zp->z_size, sizeof (zp->z_size), tx)); 15085730cc9aSmaybee 1509cdb0ab79Smaybee zfs_range_unlock(rl); 15105730cc9aSmaybee 1511cdb0ab79Smaybee dmu_tx_commit(tx); 15125730cc9aSmaybee 1513cdb0ab79Smaybee return (0); 1514cdb0ab79Smaybee } 1515cdb0ab79Smaybee 1516cdb0ab79Smaybee /* 1517cdb0ab79Smaybee * Free space in a file. 1518cdb0ab79Smaybee * 1519cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1520cdb0ab79Smaybee * off - start of section to free. 1521cdb0ab79Smaybee * len - length of section to free. 1522cdb0ab79Smaybee * 15234bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1524cdb0ab79Smaybee */ 1525cdb0ab79Smaybee static int 1526cdb0ab79Smaybee zfs_free_range(znode_t *zp, uint64_t off, uint64_t len) 1527cdb0ab79Smaybee { 1528cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1529cdb0ab79Smaybee rl_t *rl; 1530cdb0ab79Smaybee int error; 1531cdb0ab79Smaybee 1532cdb0ab79Smaybee /* 1533cdb0ab79Smaybee * Lock the range being freed. 1534cdb0ab79Smaybee */ 1535cdb0ab79Smaybee rl = zfs_range_lock(zp, off, len, RL_WRITER); 1536cdb0ab79Smaybee 1537cdb0ab79Smaybee /* 1538cdb0ab79Smaybee * Nothing to do if file already at desired length. 1539cdb0ab79Smaybee */ 15400a586ceaSMark Shellenbaum if (off >= zp->z_size) { 1541cdb0ab79Smaybee zfs_range_unlock(rl); 1542cdb0ab79Smaybee return (0); 15435730cc9aSmaybee } 15445730cc9aSmaybee 15450a586ceaSMark Shellenbaum if (off + len > zp->z_size) 15460a586ceaSMark Shellenbaum len = zp->z_size - off; 1547cdb0ab79Smaybee 1548cdb0ab79Smaybee error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len); 1549cdb0ab79Smaybee 1550c5c6ffa0Smaybee zfs_range_unlock(rl); 15515730cc9aSmaybee 1552cdb0ab79Smaybee return (error); 1553cdb0ab79Smaybee } 1554cdb0ab79Smaybee 1555cdb0ab79Smaybee /* 1556cdb0ab79Smaybee * Truncate a file 1557cdb0ab79Smaybee * 1558cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1559cdb0ab79Smaybee * end - new end-of-file. 1560cdb0ab79Smaybee * 15614bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1562cdb0ab79Smaybee */ 1563cdb0ab79Smaybee static int 1564cdb0ab79Smaybee zfs_trunc(znode_t *zp, uint64_t end) 1565cdb0ab79Smaybee { 1566cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1567cdb0ab79Smaybee vnode_t *vp = ZTOV(zp); 1568cdb0ab79Smaybee dmu_tx_t *tx; 1569cdb0ab79Smaybee rl_t *rl; 1570cdb0ab79Smaybee int error; 1571fd9ee8b5Sjoyce mcintosh sa_bulk_attr_t bulk[2]; 1572fd9ee8b5Sjoyce mcintosh int count = 0; 1573cdb0ab79Smaybee 1574cdb0ab79Smaybee /* 1575cdb0ab79Smaybee * We will change zp_size, lock the whole file. 1576cdb0ab79Smaybee */ 1577cdb0ab79Smaybee rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); 1578cdb0ab79Smaybee 1579cdb0ab79Smaybee /* 1580cdb0ab79Smaybee * Nothing to do if file already at desired length. 1581cdb0ab79Smaybee */ 15820a586ceaSMark Shellenbaum if (end >= zp->z_size) { 1583cdb0ab79Smaybee zfs_range_unlock(rl); 1584cdb0ab79Smaybee return (0); 1585cdb0ab79Smaybee } 1586cdb0ab79Smaybee 1587cdb0ab79Smaybee error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end, -1); 1588cdb0ab79Smaybee if (error) { 1589cdb0ab79Smaybee zfs_range_unlock(rl); 1590cdb0ab79Smaybee return (error); 1591cdb0ab79Smaybee } 1592cdb0ab79Smaybee tx = dmu_tx_create(zfsvfs->z_os); 15930a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 15940a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 15954bb73804SMatthew Ahrens dmu_tx_mark_netfree(tx); 1596e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 1597cdb0ab79Smaybee if (error) { 1598cdb0ab79Smaybee dmu_tx_abort(tx); 1599cdb0ab79Smaybee zfs_range_unlock(rl); 1600cdb0ab79Smaybee return (error); 1601cdb0ab79Smaybee } 1602cdb0ab79Smaybee 16030a586ceaSMark Shellenbaum zp->z_size = end; 1604fd9ee8b5Sjoyce mcintosh SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), 1605fd9ee8b5Sjoyce mcintosh NULL, &zp->z_size, sizeof (zp->z_size)); 16060a586ceaSMark Shellenbaum 1607fd9ee8b5Sjoyce mcintosh if (end == 0) { 1608fd9ee8b5Sjoyce mcintosh zp->z_pflags &= ~ZFS_SPARSE; 1609fd9ee8b5Sjoyce mcintosh SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), 1610fd9ee8b5Sjoyce mcintosh NULL, &zp->z_pflags, 8); 1611fd9ee8b5Sjoyce mcintosh } 1612fd9ee8b5Sjoyce mcintosh VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0); 1613cdb0ab79Smaybee 16145730cc9aSmaybee dmu_tx_commit(tx); 16155730cc9aSmaybee 1616fa9e4066Sahrens /* 16175730cc9aSmaybee * Clear any mapped pages in the truncated region. This has to 16185730cc9aSmaybee * happen outside of the transaction to avoid the possibility of 16195730cc9aSmaybee * a deadlock with someone trying to push a page that we are 16205730cc9aSmaybee * about to invalidate. 1621fa9e4066Sahrens */ 1622cdb0ab79Smaybee if (vn_has_cached_data(vp)) { 1623fa9e4066Sahrens page_t *pp; 1624cdb0ab79Smaybee uint64_t start = end & PAGEMASK; 1625cdb0ab79Smaybee int poff = end & PAGEOFFSET; 1626fa9e4066Sahrens 16275730cc9aSmaybee if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) { 1628fa9e4066Sahrens /* 1629fa9e4066Sahrens * We need to zero a partial page. 1630fa9e4066Sahrens */ 16315730cc9aSmaybee pagezero(pp, poff, PAGESIZE - poff); 1632fa9e4066Sahrens start += PAGESIZE; 1633fa9e4066Sahrens page_unlock(pp); 1634fa9e4066Sahrens } 1635fa9e4066Sahrens error = pvn_vplist_dirty(vp, start, zfs_no_putpage, 16365730cc9aSmaybee B_INVAL | B_TRUNC, NULL); 1637fa9e4066Sahrens ASSERT(error == 0); 1638fa9e4066Sahrens } 1639ac05c741SMark Maybee 1640ac05c741SMark Maybee zfs_range_unlock(rl); 1641fa9e4066Sahrens 1642fa9e4066Sahrens return (0); 1643fa9e4066Sahrens } 1644fa9e4066Sahrens 1645cdb0ab79Smaybee /* 1646cdb0ab79Smaybee * Free space in a file 1647cdb0ab79Smaybee * 1648cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1649cdb0ab79Smaybee * off - start of range 1650cdb0ab79Smaybee * len - end of range (0 => EOF) 1651cdb0ab79Smaybee * flag - current file open mode flags. 1652cdb0ab79Smaybee * log - TRUE if this action should be logged 1653cdb0ab79Smaybee * 16544bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1655cdb0ab79Smaybee */ 1656cdb0ab79Smaybee int 1657cdb0ab79Smaybee zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log) 1658cdb0ab79Smaybee { 1659cdb0ab79Smaybee vnode_t *vp = ZTOV(zp); 1660cdb0ab79Smaybee dmu_tx_t *tx; 1661cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1662cdb0ab79Smaybee zilog_t *zilog = zfsvfs->z_log; 16630a586ceaSMark Shellenbaum uint64_t mode; 16640a586ceaSMark Shellenbaum uint64_t mtime[2], ctime[2]; 1665db9986c7SMark Shellenbaum sa_bulk_attr_t bulk[3]; 16660a586ceaSMark Shellenbaum int count = 0; 1667cdb0ab79Smaybee int error; 1668cdb0ab79Smaybee 16690a586ceaSMark Shellenbaum if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &mode, 16700a586ceaSMark Shellenbaum sizeof (mode))) != 0) 16710a586ceaSMark Shellenbaum return (error); 16720a586ceaSMark Shellenbaum 16730a586ceaSMark Shellenbaum if (off > zp->z_size) { 1674cdb0ab79Smaybee error = zfs_extend(zp, off+len); 1675cdb0ab79Smaybee if (error == 0 && log) 1676cdb0ab79Smaybee goto log; 1677cdb0ab79Smaybee else 1678cdb0ab79Smaybee return (error); 1679cdb0ab79Smaybee } 1680cdb0ab79Smaybee 1681cdb0ab79Smaybee /* 1682cdb0ab79Smaybee * Check for any locks in the region to be freed. 1683cdb0ab79Smaybee */ 16840a586ceaSMark Shellenbaum 16850a586ceaSMark Shellenbaum if (MANDLOCK(vp, (mode_t)mode)) { 16860a586ceaSMark Shellenbaum uint64_t length = (len ? len : zp->z_size - off); 1687cdb0ab79Smaybee if (error = chklock(vp, FWRITE, off, length, flag, NULL)) 1688cdb0ab79Smaybee return (error); 1689cdb0ab79Smaybee } 1690cdb0ab79Smaybee 1691cdb0ab79Smaybee if (len == 0) { 1692cdb0ab79Smaybee error = zfs_trunc(zp, off); 1693cdb0ab79Smaybee } else { 1694cdb0ab79Smaybee if ((error = zfs_free_range(zp, off, len)) == 0 && 16950a586ceaSMark Shellenbaum off + len > zp->z_size) 1696cdb0ab79Smaybee error = zfs_extend(zp, off+len); 1697cdb0ab79Smaybee } 1698cdb0ab79Smaybee if (error || !log) 1699cdb0ab79Smaybee return (error); 1700cdb0ab79Smaybee log: 1701cdb0ab79Smaybee tx = dmu_tx_create(zfsvfs->z_os); 17020a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 17030a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 1704e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 1705cdb0ab79Smaybee if (error) { 1706cdb0ab79Smaybee dmu_tx_abort(tx); 1707cdb0ab79Smaybee return (error); 1708cdb0ab79Smaybee } 1709cdb0ab79Smaybee 17100a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16); 17110a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16); 1712db9986c7SMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), 1713db9986c7SMark Shellenbaum NULL, &zp->z_pflags, 8); 17140a586ceaSMark Shellenbaum zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE); 17150a586ceaSMark Shellenbaum error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); 17160a586ceaSMark Shellenbaum ASSERT(error == 0); 17170a586ceaSMark Shellenbaum 1718cdb0ab79Smaybee zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len); 1719cdb0ab79Smaybee 1720cdb0ab79Smaybee dmu_tx_commit(tx); 1721cdb0ab79Smaybee return (0); 1722cdb0ab79Smaybee } 1723cdb0ab79Smaybee 1724fa9e4066Sahrens void 1725de8267e0Stimh zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) 1726fa9e4066Sahrens { 17270a586ceaSMark Shellenbaum uint64_t moid, obj, sa_obj, version; 1728de8267e0Stimh uint64_t sense = ZFS_CASE_SENSITIVE; 1729de8267e0Stimh uint64_t norm = 0; 1730de8267e0Stimh nvpair_t *elem; 1731fa9e4066Sahrens int error; 173259e7834dSMark Shellenbaum int i; 1733fa9e4066Sahrens znode_t *rootzp = NULL; 1734c701fde6SGleb Smirnoff zfsvfs_t *zfsvfs; 1735fa9e4066Sahrens vnode_t *vp; 1736fa9e4066Sahrens vattr_t vattr; 17374ccbb6e7Sahrens znode_t *zp; 173889459e17SMark Shellenbaum zfs_acl_ids_t acl_ids; 1739fa9e4066Sahrens 1740fa9e4066Sahrens /* 1741fa9e4066Sahrens * First attempt to create master node. 1742fa9e4066Sahrens */ 1743ea8dc4b6Seschrock /* 1744ea8dc4b6Seschrock * In an empty objset, there are no blocks to read and thus 1745ea8dc4b6Seschrock * there can be no i/o errors (which we assert below). 1746ea8dc4b6Seschrock */ 1747fa9e4066Sahrens moid = MASTER_NODE_OBJ; 1748fa9e4066Sahrens error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE, 1749fa9e4066Sahrens DMU_OT_NONE, 0, tx); 1750fa9e4066Sahrens ASSERT(error == 0); 1751fa9e4066Sahrens 1752fa9e4066Sahrens /* 1753fa9e4066Sahrens * Set starting attributes. 1754fa9e4066Sahrens */ 17550a586ceaSMark Shellenbaum version = zfs_zpl_version_map(spa_version(dmu_objset_spa(os))); 1756de8267e0Stimh elem = NULL; 1757de8267e0Stimh while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) { 1758de8267e0Stimh /* For the moment we expect all zpl props to be uint64_ts */ 1759de8267e0Stimh uint64_t val; 1760de8267e0Stimh char *name; 1761de8267e0Stimh 1762de8267e0Stimh ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64); 1763b3d911cbStimh VERIFY(nvpair_value_uint64(elem, &val) == 0); 1764de8267e0Stimh name = nvpair_name(elem); 1765de8267e0Stimh if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) { 176614843421SMatthew Ahrens if (val < version) 176714843421SMatthew Ahrens version = val; 1768de8267e0Stimh } else { 1769de8267e0Stimh error = zap_update(os, moid, name, 8, 1, &val, tx); 1770de8267e0Stimh } 1771de8267e0Stimh ASSERT(error == 0); 1772de8267e0Stimh if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0) 1773de8267e0Stimh norm = val; 1774de8267e0Stimh else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0) 1775de8267e0Stimh sense = val; 1776de8267e0Stimh } 1777de8267e0Stimh ASSERT(version != 0); 177814843421SMatthew Ahrens error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx); 1779fa9e4066Sahrens 17800a586ceaSMark Shellenbaum /* 17810a586ceaSMark Shellenbaum * Create zap object used for SA attribute registration 17820a586ceaSMark Shellenbaum */ 17830a586ceaSMark Shellenbaum 17840a586ceaSMark Shellenbaum if (version >= ZPL_VERSION_SA) { 17850a586ceaSMark Shellenbaum sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE, 17860a586ceaSMark Shellenbaum DMU_OT_NONE, 0, tx); 17870a586ceaSMark Shellenbaum error = zap_add(os, moid, ZFS_SA_ATTRS, 8, 1, &sa_obj, tx); 17880a586ceaSMark Shellenbaum ASSERT(error == 0); 17890a586ceaSMark Shellenbaum } else { 17900a586ceaSMark Shellenbaum sa_obj = 0; 17910a586ceaSMark Shellenbaum } 1792fa9e4066Sahrens /* 1793fa9e4066Sahrens * Create a delete queue. 1794fa9e4066Sahrens */ 179514843421SMatthew Ahrens obj = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx); 1796fa9e4066Sahrens 179714843421SMatthew Ahrens error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx); 1798fa9e4066Sahrens ASSERT(error == 0); 1799fa9e4066Sahrens 1800fa9e4066Sahrens /* 1801fa9e4066Sahrens * Create root znode. Create minimal znode/vnode/zfsvfs 1802fa9e4066Sahrens * to allow zfs_mknode to work. 1803fa9e4066Sahrens */ 1804fa9e4066Sahrens vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; 1805fa9e4066Sahrens vattr.va_type = VDIR; 1806fa9e4066Sahrens vattr.va_mode = S_IFDIR|0755; 1807ecd6cf80Smarks vattr.va_uid = crgetuid(cr); 1808ecd6cf80Smarks vattr.va_gid = crgetgid(cr); 1809fa9e4066Sahrens 1810fa9e4066Sahrens rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP); 1811744947dcSTom Erickson ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); 1812744947dcSTom Erickson rootzp->z_moved = 0; 1813893a6d32Sahrens rootzp->z_unlinked = 0; 1814fa9e4066Sahrens rootzp->z_atime_dirty = 0; 18150a586ceaSMark Shellenbaum rootzp->z_is_sa = USE_SA(version, os); 1816fa9e4066Sahrens 1817fa9e4066Sahrens vp = ZTOV(rootzp); 1818fa9e4066Sahrens vn_reinit(vp); 1819fa9e4066Sahrens vp->v_type = VDIR; 1820fa9e4066Sahrens 1821c701fde6SGleb Smirnoff zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 1822c701fde6SGleb Smirnoff zfsvfs->z_os = os; 1823c701fde6SGleb Smirnoff zfsvfs->z_parent = zfsvfs; 1824c701fde6SGleb Smirnoff zfsvfs->z_version = version; 1825c701fde6SGleb Smirnoff zfsvfs->z_use_fuids = USE_FUIDS(version, os); 1826c701fde6SGleb Smirnoff zfsvfs->z_use_sa = USE_SA(version, os); 1827c701fde6SGleb Smirnoff zfsvfs->z_norm = norm; 18280a586ceaSMark Shellenbaum 18291d8ccc7bSMark Shellenbaum error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, 1830c701fde6SGleb Smirnoff &zfsvfs->z_attr_table); 18311d8ccc7bSMark Shellenbaum 18321d8ccc7bSMark Shellenbaum ASSERT(error == 0); 18330a586ceaSMark Shellenbaum 1834de8267e0Stimh /* 1835de8267e0Stimh * Fold case on file systems that are always or sometimes case 1836de8267e0Stimh * insensitive. 1837de8267e0Stimh */ 1838de8267e0Stimh if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED) 1839c701fde6SGleb Smirnoff zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER; 1840fa9e4066Sahrens 1841c701fde6SGleb Smirnoff mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 1842c701fde6SGleb Smirnoff list_create(&zfsvfs->z_all_znodes, sizeof (znode_t), 1843fa9e4066Sahrens offsetof(znode_t, z_link_node)); 1844fa9e4066Sahrens 184559e7834dSMark Shellenbaum for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 1846c701fde6SGleb Smirnoff mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 184759e7834dSMark Shellenbaum 1848c701fde6SGleb Smirnoff rootzp->z_zfsvfs = zfsvfs; 184989459e17SMark Shellenbaum VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, 185089459e17SMark Shellenbaum cr, NULL, &acl_ids)); 18510a586ceaSMark Shellenbaum zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); 1852874395d5Smaybee ASSERT3P(zp, ==, rootzp); 1853b5fca8f8Stomee ASSERT(!vn_in_dnlc(ZTOV(rootzp))); /* not valid to move */ 18544ccbb6e7Sahrens error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); 1855fa9e4066Sahrens ASSERT(error == 0); 185689459e17SMark Shellenbaum zfs_acl_ids_free(&acl_ids); 1857b5fca8f8Stomee POINTER_INVALIDATE(&rootzp->z_zfsvfs); 1858fa9e4066Sahrens 1859fa9e4066Sahrens ZTOV(rootzp)->v_count = 0; 18600a586ceaSMark Shellenbaum sa_handle_destroy(rootzp->z_sa_hdl); 1861fa9e4066Sahrens kmem_cache_free(znode_cache, rootzp); 1862743a77edSAlan Wright 1863743a77edSAlan Wright /* 1864743a77edSAlan Wright * Create shares directory 1865743a77edSAlan Wright */ 1866743a77edSAlan Wright 1867c701fde6SGleb Smirnoff error = zfs_create_share_dir(zfsvfs, tx); 186889459e17SMark Shellenbaum 1869743a77edSAlan Wright ASSERT(error == 0); 187059e7834dSMark Shellenbaum 187159e7834dSMark Shellenbaum for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) 1872c701fde6SGleb Smirnoff mutex_destroy(&zfsvfs->z_hold_mtx[i]); 1873c701fde6SGleb Smirnoff kmem_free(zfsvfs, sizeof (zfsvfs_t)); 1874fa9e4066Sahrens } 187555434c77Sek 1876da6c28aaSamw #endif /* _KERNEL */ 18770a586ceaSMark Shellenbaum 187855434c77Sek static int 187999d5e173STim Haley zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table) 188099d5e173STim Haley { 188199d5e173STim Haley uint64_t sa_obj = 0; 188299d5e173STim Haley int error; 188399d5e173STim Haley 188499d5e173STim Haley error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj); 188599d5e173STim Haley if (error != 0 && error != ENOENT) 188699d5e173STim Haley return (error); 188799d5e173STim Haley 188899d5e173STim Haley error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table); 188999d5e173STim Haley return (error); 189099d5e173STim Haley } 189199d5e173STim Haley 189299d5e173STim Haley static int 189399d5e173STim Haley zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp, 1894163eb7ffSTim Haley dmu_buf_t **db, void *tag) 189555434c77Sek { 189655434c77Sek dmu_object_info_t doi; 189755434c77Sek int error; 18980a586ceaSMark Shellenbaum 1899163eb7ffSTim Haley if ((error = sa_buf_hold(osp, obj, tag, db)) != 0) 190055434c77Sek return (error); 190155434c77Sek 190299d5e173STim Haley dmu_object_info_from_db(*db, &doi); 19030a586ceaSMark Shellenbaum if ((doi.doi_bonus_type != DMU_OT_SA && 19040a586ceaSMark Shellenbaum doi.doi_bonus_type != DMU_OT_ZNODE) || 19050a586ceaSMark Shellenbaum doi.doi_bonus_type == DMU_OT_ZNODE && 190655434c77Sek doi.doi_bonus_size < sizeof (znode_phys_t)) { 1907163eb7ffSTim Haley sa_buf_rele(*db, tag); 1908be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 190955434c77Sek } 191055434c77Sek 191199d5e173STim Haley error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp); 191299d5e173STim Haley if (error != 0) { 1913163eb7ffSTim Haley sa_buf_rele(*db, tag); 19140a586ceaSMark Shellenbaum return (error); 19150a586ceaSMark Shellenbaum } 19160a586ceaSMark Shellenbaum 191799d5e173STim Haley return (0); 191899d5e173STim Haley } 191999d5e173STim Haley 192099d5e173STim Haley void 1921163eb7ffSTim Haley zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, void *tag) 192299d5e173STim Haley { 192399d5e173STim Haley sa_handle_destroy(hdl); 1924163eb7ffSTim Haley sa_buf_rele(db, tag); 192599d5e173STim Haley } 192699d5e173STim Haley 192799d5e173STim Haley /* 192899d5e173STim Haley * Given an object number, return its parent object number and whether 192999d5e173STim Haley * or not the object is an extended attribute directory. 193099d5e173STim Haley */ 193199d5e173STim Haley static int 19321ce39b5fSJeremy Jones zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table, 19331ce39b5fSJeremy Jones uint64_t *pobjp, int *is_xattrdir) 193499d5e173STim Haley { 193599d5e173STim Haley uint64_t parent; 193699d5e173STim Haley uint64_t pflags; 193799d5e173STim Haley uint64_t mode; 19381ce39b5fSJeremy Jones uint64_t parent_mode; 193999d5e173STim Haley sa_bulk_attr_t bulk[3]; 19401ce39b5fSJeremy Jones sa_handle_t *sa_hdl; 19411ce39b5fSJeremy Jones dmu_buf_t *sa_db; 194299d5e173STim Haley int count = 0; 194399d5e173STim Haley int error; 194499d5e173STim Haley 194599d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL, 194699d5e173STim Haley &parent, sizeof (parent)); 19470a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL, 194899d5e173STim Haley &pflags, sizeof (pflags)); 19490a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL, 195099d5e173STim Haley &mode, sizeof (mode)); 19510a586ceaSMark Shellenbaum 195299d5e173STim Haley if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0) 19530a586ceaSMark Shellenbaum return (error); 195499d5e173STim Haley 19551ce39b5fSJeremy Jones /* 19561ce39b5fSJeremy Jones * When a link is removed its parent pointer is not changed and will 19571ce39b5fSJeremy Jones * be invalid. There are two cases where a link is removed but the 19581ce39b5fSJeremy Jones * file stays around, when it goes to the delete queue and when there 19591ce39b5fSJeremy Jones * are additional links. 19601ce39b5fSJeremy Jones */ 19611ce39b5fSJeremy Jones error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG); 19621ce39b5fSJeremy Jones if (error != 0) 19631ce39b5fSJeremy Jones return (error); 19641ce39b5fSJeremy Jones 19651ce39b5fSJeremy Jones error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode)); 19661ce39b5fSJeremy Jones zfs_release_sa_handle(sa_hdl, sa_db, FTAG); 19671ce39b5fSJeremy Jones if (error != 0) 19681ce39b5fSJeremy Jones return (error); 19691ce39b5fSJeremy Jones 19700a586ceaSMark Shellenbaum *is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode); 197155434c77Sek 19721ce39b5fSJeremy Jones /* 19731ce39b5fSJeremy Jones * Extended attributes can be applied to files, directories, etc. 19741ce39b5fSJeremy Jones * Otherwise the parent must be a directory. 19751ce39b5fSJeremy Jones */ 19761ce39b5fSJeremy Jones if (!*is_xattrdir && !S_ISDIR(parent_mode)) 1977be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 19781ce39b5fSJeremy Jones 19791ce39b5fSJeremy Jones *pobjp = parent; 19801ce39b5fSJeremy Jones 198155434c77Sek return (0); 198255434c77Sek } 198355434c77Sek 198499d5e173STim Haley /* 198599d5e173STim Haley * Given an object number, return some zpl level statistics 198699d5e173STim Haley */ 198799d5e173STim Haley static int 198899d5e173STim Haley zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table, 198999d5e173STim Haley zfs_stat_t *sb) 199055434c77Sek { 199199d5e173STim Haley sa_bulk_attr_t bulk[4]; 199299d5e173STim Haley int count = 0; 199399d5e173STim Haley 199499d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL, 199599d5e173STim Haley &sb->zs_mode, sizeof (sb->zs_mode)); 199699d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL, 199799d5e173STim Haley &sb->zs_gen, sizeof (sb->zs_gen)); 199899d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL, 199999d5e173STim Haley &sb->zs_links, sizeof (sb->zs_links)); 200099d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL, 200199d5e173STim Haley &sb->zs_ctime, sizeof (sb->zs_ctime)); 200299d5e173STim Haley 200399d5e173STim Haley return (sa_bulk_lookup(hdl, bulk, count)); 200499d5e173STim Haley } 200599d5e173STim Haley 200699d5e173STim Haley static int 200799d5e173STim Haley zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl, 200899d5e173STim Haley sa_attr_type_t *sa_table, char *buf, int len) 200999d5e173STim Haley { 201099d5e173STim Haley sa_handle_t *sa_hdl; 201199d5e173STim Haley sa_handle_t *prevhdl = NULL; 201299d5e173STim Haley dmu_buf_t *prevdb = NULL; 201399d5e173STim Haley dmu_buf_t *sa_db = NULL; 201455434c77Sek char *path = buf + len - 1; 201555434c77Sek int error; 201655434c77Sek 201755434c77Sek *path = '\0'; 201899d5e173STim Haley sa_hdl = hdl; 20190a586ceaSMark Shellenbaum 202055434c77Sek for (;;) { 202155434c77Sek uint64_t pobj; 202255434c77Sek char component[MAXNAMELEN + 2]; 202355434c77Sek size_t complen; 202455434c77Sek int is_xattrdir; 202555434c77Sek 202699d5e173STim Haley if (prevdb) 2027163eb7ffSTim Haley zfs_release_sa_handle(prevhdl, prevdb, FTAG); 202899d5e173STim Haley 20291ce39b5fSJeremy Jones if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj, 203099d5e173STim Haley &is_xattrdir)) != 0) 203155434c77Sek break; 203255434c77Sek 203355434c77Sek if (pobj == obj) { 203455434c77Sek if (path[0] != '/') 203555434c77Sek *--path = '/'; 203655434c77Sek break; 203755434c77Sek } 203855434c77Sek 203955434c77Sek component[0] = '/'; 204055434c77Sek if (is_xattrdir) { 204155434c77Sek (void) sprintf(component + 1, "<xattrdir>"); 204255434c77Sek } else { 2043e7437265Sahrens error = zap_value_search(osp, pobj, obj, 2044e7437265Sahrens ZFS_DIRENT_OBJ(-1ULL), component + 1); 204555434c77Sek if (error != 0) 204655434c77Sek break; 204755434c77Sek } 204855434c77Sek 204955434c77Sek complen = strlen(component); 205055434c77Sek path -= complen; 205155434c77Sek ASSERT(path >= buf); 205255434c77Sek bcopy(component, path, complen); 205355434c77Sek obj = pobj; 205499d5e173STim Haley 205599d5e173STim Haley if (sa_hdl != hdl) { 205699d5e173STim Haley prevhdl = sa_hdl; 205799d5e173STim Haley prevdb = sa_db; 205899d5e173STim Haley } 2059163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG); 206099d5e173STim Haley if (error != 0) { 206199d5e173STim Haley sa_hdl = prevhdl; 206299d5e173STim Haley sa_db = prevdb; 206399d5e173STim Haley break; 206499d5e173STim Haley } 206599d5e173STim Haley } 206699d5e173STim Haley 206799d5e173STim Haley if (sa_hdl != NULL && sa_hdl != hdl) { 206899d5e173STim Haley ASSERT(sa_db != NULL); 2069163eb7ffSTim Haley zfs_release_sa_handle(sa_hdl, sa_db, FTAG); 207055434c77Sek } 207155434c77Sek 207255434c77Sek if (error == 0) 207355434c77Sek (void) memmove(buf, path, buf + len - path); 20740a586ceaSMark Shellenbaum 207555434c77Sek return (error); 207655434c77Sek } 207799d5e173STim Haley 207899d5e173STim Haley int 207999d5e173STim Haley zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len) 208099d5e173STim Haley { 208199d5e173STim Haley sa_attr_type_t *sa_table; 208299d5e173STim Haley sa_handle_t *hdl; 208399d5e173STim Haley dmu_buf_t *db; 208499d5e173STim Haley int error; 208599d5e173STim Haley 208699d5e173STim Haley error = zfs_sa_setup(osp, &sa_table); 208799d5e173STim Haley if (error != 0) 208899d5e173STim Haley return (error); 208999d5e173STim Haley 2090163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG); 209199d5e173STim Haley if (error != 0) 209299d5e173STim Haley return (error); 209399d5e173STim Haley 209499d5e173STim Haley error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len); 209599d5e173STim Haley 2096163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 209799d5e173STim Haley return (error); 209899d5e173STim Haley } 209999d5e173STim Haley 210099d5e173STim Haley int 210199d5e173STim Haley zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb, 210299d5e173STim Haley char *buf, int len) 210399d5e173STim Haley { 210499d5e173STim Haley char *path = buf + len - 1; 210599d5e173STim Haley sa_attr_type_t *sa_table; 210699d5e173STim Haley sa_handle_t *hdl; 210799d5e173STim Haley dmu_buf_t *db; 210899d5e173STim Haley int error; 210999d5e173STim Haley 211099d5e173STim Haley *path = '\0'; 211199d5e173STim Haley 211299d5e173STim Haley error = zfs_sa_setup(osp, &sa_table); 211399d5e173STim Haley if (error != 0) 211499d5e173STim Haley return (error); 211599d5e173STim Haley 2116163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG); 211799d5e173STim Haley if (error != 0) 211899d5e173STim Haley return (error); 211999d5e173STim Haley 212099d5e173STim Haley error = zfs_obj_to_stats_impl(hdl, sa_table, sb); 212199d5e173STim Haley if (error != 0) { 2122163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 212399d5e173STim Haley return (error); 212499d5e173STim Haley } 212599d5e173STim Haley 212699d5e173STim Haley error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len); 212799d5e173STim Haley 2128163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 212999d5e173STim Haley return (error); 213099d5e173STim Haley } 2131