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. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 2675c76197Speteh /* Portions Copyright 2007 Jeremy Teo */ 2775c76197Speteh 2855434c77Sek #ifdef _KERNEL 29fa9e4066Sahrens #include <sys/types.h> 30fa9e4066Sahrens #include <sys/param.h> 31fa9e4066Sahrens #include <sys/time.h> 32fa9e4066Sahrens #include <sys/systm.h> 33fa9e4066Sahrens #include <sys/sysmacros.h> 34fa9e4066Sahrens #include <sys/resource.h> 35fa9e4066Sahrens #include <sys/mntent.h> 3672fc53bcSmarks #include <sys/mkdev.h> 37de8267e0Stimh #include <sys/u8_textprep.h> 38ab04eb8eStimh #include <sys/dsl_dataset.h> 39fa9e4066Sahrens #include <sys/vfs.h> 40aa59c4cbSrsb #include <sys/vfs_opreg.h> 41fa9e4066Sahrens #include <sys/vnode.h> 42fa9e4066Sahrens #include <sys/file.h> 43fa9e4066Sahrens #include <sys/kmem.h> 44fa9e4066Sahrens #include <sys/errno.h> 45fa9e4066Sahrens #include <sys/unistd.h> 46fa9e4066Sahrens #include <sys/mode.h> 47fa9e4066Sahrens #include <sys/atomic.h> 48fa9e4066Sahrens #include <vm/pvn.h> 49fa9e4066Sahrens #include "fs/fs_subr.h" 50fa9e4066Sahrens #include <sys/zfs_dir.h> 51fa9e4066Sahrens #include <sys/zfs_acl.h> 52fa9e4066Sahrens #include <sys/zfs_ioctl.h> 53104e2ed7Sperrin #include <sys/zfs_rlock.h> 54da6c28aaSamw #include <sys/zfs_fuid.h> 550a586ceaSMark Shellenbaum #include <sys/dnode.h> 56fa9e4066Sahrens #include <sys/fs/zfs.h> 57da6c28aaSamw #include <sys/kidmap.h> 5855434c77Sek #endif /* _KERNEL */ 5955434c77Sek 6055434c77Sek #include <sys/dmu.h> 61*b5152584SMatthew Ahrens #include <sys/dmu_objset.h> 6255434c77Sek #include <sys/refcount.h> 6355434c77Sek #include <sys/stat.h> 6455434c77Sek #include <sys/zap.h> 6555434c77Sek #include <sys/zfs_znode.h> 660a586ceaSMark Shellenbaum #include <sys/sa.h> 670a586ceaSMark Shellenbaum #include <sys/zfs_sa.h> 6899d5e173STim Haley #include <sys/zfs_stat.h> 69fa9e4066Sahrens 70de8267e0Stimh #include "zfs_prop.h" 710a586ceaSMark Shellenbaum #include "zfs_comutil.h" 72de8267e0Stimh 73b5fca8f8Stomee /* 74b5fca8f8Stomee * Define ZNODE_STATS to turn on statistic gathering. By default, it is only 75b5fca8f8Stomee * turned on when DEBUG is also defined. 76b5fca8f8Stomee */ 77b5fca8f8Stomee #ifdef DEBUG 78b5fca8f8Stomee #define ZNODE_STATS 79b5fca8f8Stomee #endif /* DEBUG */ 80b5fca8f8Stomee 81b5fca8f8Stomee #ifdef ZNODE_STATS 82b5fca8f8Stomee #define ZNODE_STAT_ADD(stat) ((stat)++) 83b5fca8f8Stomee #else 84b5fca8f8Stomee #define ZNODE_STAT_ADD(stat) /* nothing */ 85b5fca8f8Stomee #endif /* ZNODE_STATS */ 86b5fca8f8Stomee 8755434c77Sek /* 8855434c77Sek * Functions needed for userland (ie: libzpool) are not put under 8955434c77Sek * #ifdef_KERNEL; the rest of the functions have dependencies 9055434c77Sek * (such as VFS logic) that will not compile easily in userland. 9155434c77Sek */ 9255434c77Sek #ifdef _KERNEL 934e9583b2STom Erickson /* 944e9583b2STom Erickson * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to 954e9583b2STom Erickson * be freed before it can be safely accessed. 964e9583b2STom Erickson */ 974e9583b2STom Erickson krwlock_t zfsvfs_lock; 984e9583b2STom Erickson 99b5fca8f8Stomee static kmem_cache_t *znode_cache = NULL; 100fa9e4066Sahrens 101fa9e4066Sahrens /*ARGSUSED*/ 102fa9e4066Sahrens static void 103874395d5Smaybee znode_evict_error(dmu_buf_t *dbuf, void *user_ptr) 104fa9e4066Sahrens { 105874395d5Smaybee /* 106874395d5Smaybee * We should never drop all dbuf refs without first clearing 107874395d5Smaybee * the eviction callback. 108874395d5Smaybee */ 109874395d5Smaybee panic("evicting znode %p\n", user_ptr); 110fa9e4066Sahrens } 111fa9e4066Sahrens 112fa9e4066Sahrens /*ARGSUSED*/ 113fa9e4066Sahrens static int 114b5fca8f8Stomee zfs_znode_cache_constructor(void *buf, void *arg, int kmflags) 115fa9e4066Sahrens { 116fa9e4066Sahrens znode_t *zp = buf; 117fa9e4066Sahrens 118b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 119b5fca8f8Stomee 120b5fca8f8Stomee zp->z_vnode = vn_alloc(kmflags); 121b5fca8f8Stomee if (zp->z_vnode == NULL) { 122b5fca8f8Stomee return (-1); 123b5fca8f8Stomee } 124b5fca8f8Stomee ZTOV(zp)->v_data = zp; 125b5fca8f8Stomee 126b5fca8f8Stomee list_link_init(&zp->z_link_node); 127b5fca8f8Stomee 128fa9e4066Sahrens mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL); 129104e2ed7Sperrin rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL); 130af2c4821Smaybee rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL); 131fa9e4066Sahrens mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL); 132104e2ed7Sperrin 133104e2ed7Sperrin mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL); 134104e2ed7Sperrin avl_create(&zp->z_range_avl, zfs_range_compare, 135104e2ed7Sperrin sizeof (rl_t), offsetof(rl_t, r_node)); 136104e2ed7Sperrin 137b5fca8f8Stomee zp->z_dirlocks = NULL; 138d47621a4STim Haley zp->z_acl_cached = NULL; 139744947dcSTom Erickson zp->z_moved = 0; 140fa9e4066Sahrens return (0); 141fa9e4066Sahrens } 142fa9e4066Sahrens 143fa9e4066Sahrens /*ARGSUSED*/ 144fa9e4066Sahrens static void 145b5fca8f8Stomee zfs_znode_cache_destructor(void *buf, void *arg) 146fa9e4066Sahrens { 147fa9e4066Sahrens znode_t *zp = buf; 148fa9e4066Sahrens 149b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 150b5fca8f8Stomee ASSERT(ZTOV(zp)->v_data == zp); 151b5fca8f8Stomee vn_free(ZTOV(zp)); 152b5fca8f8Stomee ASSERT(!list_link_active(&zp->z_link_node)); 153fa9e4066Sahrens mutex_destroy(&zp->z_lock); 154104e2ed7Sperrin rw_destroy(&zp->z_parent_lock); 155af2c4821Smaybee rw_destroy(&zp->z_name_lock); 156fa9e4066Sahrens mutex_destroy(&zp->z_acl_lock); 157104e2ed7Sperrin avl_destroy(&zp->z_range_avl); 158c25056deSgw mutex_destroy(&zp->z_range_lock); 159fa9e4066Sahrens 160b5fca8f8Stomee ASSERT(zp->z_dirlocks == NULL); 1614929fd5eSTim Haley ASSERT(zp->z_acl_cached == NULL); 162b5fca8f8Stomee } 163b5fca8f8Stomee 164b5fca8f8Stomee #ifdef ZNODE_STATS 165b5fca8f8Stomee static struct { 166b5fca8f8Stomee uint64_t zms_zfsvfs_invalid; 1674e9583b2STom Erickson uint64_t zms_zfsvfs_recheck1; 168b5fca8f8Stomee uint64_t zms_zfsvfs_unmounted; 1694e9583b2STom Erickson uint64_t zms_zfsvfs_recheck2; 170a66b2b35STom Erickson uint64_t zms_obj_held; 171b5fca8f8Stomee uint64_t zms_vnode_locked; 172a66b2b35STom Erickson uint64_t zms_not_only_dnlc; 173b5fca8f8Stomee } znode_move_stats; 174b5fca8f8Stomee #endif /* ZNODE_STATS */ 175b5fca8f8Stomee 176b5fca8f8Stomee static void 177b5fca8f8Stomee zfs_znode_move_impl(znode_t *ozp, znode_t *nzp) 178b5fca8f8Stomee { 179b5fca8f8Stomee vnode_t *vp; 180b5fca8f8Stomee 181b5fca8f8Stomee /* Copy fields. */ 182b5fca8f8Stomee nzp->z_zfsvfs = ozp->z_zfsvfs; 183b5fca8f8Stomee 184b5fca8f8Stomee /* Swap vnodes. */ 185b5fca8f8Stomee vp = nzp->z_vnode; 186b5fca8f8Stomee nzp->z_vnode = ozp->z_vnode; 187b5fca8f8Stomee ozp->z_vnode = vp; /* let destructor free the overwritten vnode */ 188b5fca8f8Stomee ZTOV(ozp)->v_data = ozp; 189b5fca8f8Stomee ZTOV(nzp)->v_data = nzp; 190b5fca8f8Stomee 191b5fca8f8Stomee nzp->z_id = ozp->z_id; 192b5fca8f8Stomee ASSERT(ozp->z_dirlocks == NULL); /* znode not in use */ 193b5fca8f8Stomee ASSERT(avl_numnodes(&ozp->z_range_avl) == 0); 194b5fca8f8Stomee nzp->z_unlinked = ozp->z_unlinked; 195b5fca8f8Stomee nzp->z_atime_dirty = ozp->z_atime_dirty; 196b5fca8f8Stomee nzp->z_zn_prefetch = ozp->z_zn_prefetch; 197b5fca8f8Stomee nzp->z_blksz = ozp->z_blksz; 198b5fca8f8Stomee nzp->z_seq = ozp->z_seq; 199b5fca8f8Stomee nzp->z_mapcnt = ozp->z_mapcnt; 200b5fca8f8Stomee nzp->z_gen = ozp->z_gen; 201b5fca8f8Stomee nzp->z_sync_cnt = ozp->z_sync_cnt; 2020a586ceaSMark Shellenbaum nzp->z_is_sa = ozp->z_is_sa; 2030a586ceaSMark Shellenbaum nzp->z_sa_hdl = ozp->z_sa_hdl; 2040a586ceaSMark Shellenbaum bcopy(ozp->z_atime, nzp->z_atime, sizeof (uint64_t) * 2); 2050a586ceaSMark Shellenbaum nzp->z_links = ozp->z_links; 2060a586ceaSMark Shellenbaum nzp->z_size = ozp->z_size; 2070a586ceaSMark Shellenbaum nzp->z_pflags = ozp->z_pflags; 2080a586ceaSMark Shellenbaum nzp->z_uid = ozp->z_uid; 2090a586ceaSMark Shellenbaum nzp->z_gid = ozp->z_gid; 2100a586ceaSMark Shellenbaum nzp->z_mode = ozp->z_mode; 211d98a6232SMark Shellenbaum 212d98a6232SMark Shellenbaum /* 2136638ae1dSMark Shellenbaum * Since this is just an idle znode and kmem is already dealing with 2146638ae1dSMark Shellenbaum * memory pressure, release any cached ACL. 215d98a6232SMark Shellenbaum */ 216d98a6232SMark Shellenbaum if (ozp->z_acl_cached) { 217d98a6232SMark Shellenbaum zfs_acl_free(ozp->z_acl_cached); 218d98a6232SMark Shellenbaum ozp->z_acl_cached = NULL; 219d98a6232SMark Shellenbaum } 220b5fca8f8Stomee 2210a586ceaSMark Shellenbaum sa_set_userp(nzp->z_sa_hdl, nzp); 222b5fca8f8Stomee 223b5fca8f8Stomee /* 224b5fca8f8Stomee * Invalidate the original znode by clearing fields that provide a 225b5fca8f8Stomee * pointer back to the znode. Set the low bit of the vfs pointer to 226b5fca8f8Stomee * ensure that zfs_znode_move() recognizes the znode as invalid in any 227b5fca8f8Stomee * subsequent callback. 228b5fca8f8Stomee */ 2290a586ceaSMark Shellenbaum ozp->z_sa_hdl = NULL; 230b5fca8f8Stomee POINTER_INVALIDATE(&ozp->z_zfsvfs); 231744947dcSTom Erickson 232744947dcSTom Erickson /* 233744947dcSTom Erickson * Mark the znode. 234744947dcSTom Erickson */ 235744947dcSTom Erickson nzp->z_moved = 1; 236744947dcSTom Erickson ozp->z_moved = (uint8_t)-1; 237b5fca8f8Stomee } 238b5fca8f8Stomee 239b5fca8f8Stomee /*ARGSUSED*/ 240b5fca8f8Stomee static kmem_cbrc_t 241b5fca8f8Stomee zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg) 242b5fca8f8Stomee { 243b5fca8f8Stomee znode_t *ozp = buf, *nzp = newbuf; 244b5fca8f8Stomee zfsvfs_t *zfsvfs; 245b5fca8f8Stomee vnode_t *vp; 246b5fca8f8Stomee 247b5fca8f8Stomee /* 248b5fca8f8Stomee * The znode is on the file system's list of known znodes if the vfs 249b5fca8f8Stomee * pointer is valid. We set the low bit of the vfs pointer when freeing 250b5fca8f8Stomee * the znode to invalidate it, and the memory patterns written by kmem 251b5fca8f8Stomee * (baddcafe and deadbeef) set at least one of the two low bits. A newly 252b5fca8f8Stomee * created znode sets the vfs pointer last of all to indicate that the 253b5fca8f8Stomee * znode is known and in a valid state to be moved by this function. 254b5fca8f8Stomee */ 255b5fca8f8Stomee zfsvfs = ozp->z_zfsvfs; 256b5fca8f8Stomee if (!POINTER_IS_VALID(zfsvfs)) { 257b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_invalid); 258b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 259b5fca8f8Stomee } 260b5fca8f8Stomee 261b5fca8f8Stomee /* 2624e9583b2STom Erickson * Close a small window in which it's possible that the filesystem could 2634e9583b2STom Erickson * be unmounted and freed, and zfsvfs, though valid in the previous 2644e9583b2STom Erickson * statement, could point to unrelated memory by the time we try to 2654e9583b2STom Erickson * prevent the filesystem from being unmounted. 2664e9583b2STom Erickson */ 2674e9583b2STom Erickson rw_enter(&zfsvfs_lock, RW_WRITER); 2684e9583b2STom Erickson if (zfsvfs != ozp->z_zfsvfs) { 2694e9583b2STom Erickson rw_exit(&zfsvfs_lock); 2704e9583b2STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1); 2714e9583b2STom Erickson return (KMEM_CBRC_DONT_KNOW); 2724e9583b2STom Erickson } 2734e9583b2STom Erickson 2744e9583b2STom Erickson /* 2754e9583b2STom Erickson * If the znode is still valid, then so is the file system. We know that 2764e9583b2STom Erickson * no valid file system can be freed while we hold zfsvfs_lock, so we 2774e9583b2STom Erickson * can safely ensure that the filesystem is not and will not be 2784e9583b2STom Erickson * unmounted. The next statement is equivalent to ZFS_ENTER(). 279b5fca8f8Stomee */ 280c9030f6cSAlexander Motin rrm_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG); 28114843421SMatthew Ahrens if (zfsvfs->z_unmounted) { 28214843421SMatthew Ahrens ZFS_EXIT(zfsvfs); 2834e9583b2STom Erickson rw_exit(&zfsvfs_lock); 284b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted); 285b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 286b5fca8f8Stomee } 2874e9583b2STom Erickson rw_exit(&zfsvfs_lock); 288b5fca8f8Stomee 289b5fca8f8Stomee mutex_enter(&zfsvfs->z_znodes_lock); 290b5fca8f8Stomee /* 291b5fca8f8Stomee * Recheck the vfs pointer in case the znode was removed just before 292b5fca8f8Stomee * acquiring the lock. 293b5fca8f8Stomee */ 294b5fca8f8Stomee if (zfsvfs != ozp->z_zfsvfs) { 295b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 296b5fca8f8Stomee ZFS_EXIT(zfsvfs); 2974e9583b2STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2); 298b5fca8f8Stomee return (KMEM_CBRC_DONT_KNOW); 299b5fca8f8Stomee } 300b5fca8f8Stomee 301b5fca8f8Stomee /* 302b5fca8f8Stomee * At this point we know that as long as we hold z_znodes_lock, the 303b5fca8f8Stomee * znode cannot be freed and fields within the znode can be safely 304a66b2b35STom Erickson * accessed. Now, prevent a race with zfs_zget(). 305b5fca8f8Stomee */ 306a66b2b35STom Erickson if (ZFS_OBJ_HOLD_TRYENTER(zfsvfs, ozp->z_id) == 0) { 307a66b2b35STom Erickson mutex_exit(&zfsvfs->z_znodes_lock); 308a66b2b35STom Erickson ZFS_EXIT(zfsvfs); 309a66b2b35STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_obj_held); 310a66b2b35STom Erickson return (KMEM_CBRC_LATER); 311a66b2b35STom Erickson } 312a66b2b35STom Erickson 313b5fca8f8Stomee vp = ZTOV(ozp); 314b5fca8f8Stomee if (mutex_tryenter(&vp->v_lock) == 0) { 315a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 316b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 317b5fca8f8Stomee ZFS_EXIT(zfsvfs); 318b5fca8f8Stomee ZNODE_STAT_ADD(znode_move_stats.zms_vnode_locked); 319b5fca8f8Stomee return (KMEM_CBRC_LATER); 320b5fca8f8Stomee } 321a66b2b35STom Erickson 322b5fca8f8Stomee /* Only move znodes that are referenced _only_ by the DNLC. */ 323b5fca8f8Stomee if (vp->v_count != 1 || !vn_in_dnlc(vp)) { 324b5fca8f8Stomee mutex_exit(&vp->v_lock); 325a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 326b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 327b5fca8f8Stomee ZFS_EXIT(zfsvfs); 328a66b2b35STom Erickson ZNODE_STAT_ADD(znode_move_stats.zms_not_only_dnlc); 329b5fca8f8Stomee return (KMEM_CBRC_LATER); 330b5fca8f8Stomee } 331b5fca8f8Stomee 332b5fca8f8Stomee /* 333b5fca8f8Stomee * The znode is known and in a valid state to move. We're holding the 334b5fca8f8Stomee * locks needed to execute the critical section. 335b5fca8f8Stomee */ 336b5fca8f8Stomee zfs_znode_move_impl(ozp, nzp); 337b5fca8f8Stomee mutex_exit(&vp->v_lock); 338a66b2b35STom Erickson ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id); 339b5fca8f8Stomee 340b5fca8f8Stomee list_link_replace(&ozp->z_link_node, &nzp->z_link_node); 341b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 342b5fca8f8Stomee ZFS_EXIT(zfsvfs); 343b5fca8f8Stomee 344b5fca8f8Stomee return (KMEM_CBRC_YES); 345fa9e4066Sahrens } 346fa9e4066Sahrens 347fa9e4066Sahrens void 348fa9e4066Sahrens zfs_znode_init(void) 349fa9e4066Sahrens { 350fa9e4066Sahrens /* 351fa9e4066Sahrens * Initialize zcache 352fa9e4066Sahrens */ 3534e9583b2STom Erickson rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL); 354fa9e4066Sahrens ASSERT(znode_cache == NULL); 355fa9e4066Sahrens znode_cache = kmem_cache_create("zfs_znode_cache", 356fa9e4066Sahrens sizeof (znode_t), 0, zfs_znode_cache_constructor, 357fa9e4066Sahrens zfs_znode_cache_destructor, NULL, NULL, NULL, 0); 358b5fca8f8Stomee kmem_cache_set_move(znode_cache, zfs_znode_move); 359fa9e4066Sahrens } 360fa9e4066Sahrens 361fa9e4066Sahrens void 362fa9e4066Sahrens zfs_znode_fini(void) 363fa9e4066Sahrens { 364fa9e4066Sahrens /* 365fa9e4066Sahrens * Cleanup vfs & vnode ops 366fa9e4066Sahrens */ 367fa9e4066Sahrens zfs_remove_op_tables(); 368fa9e4066Sahrens 369fa9e4066Sahrens /* 370fa9e4066Sahrens * Cleanup zcache 371fa9e4066Sahrens */ 372fa9e4066Sahrens if (znode_cache) 373fa9e4066Sahrens kmem_cache_destroy(znode_cache); 374fa9e4066Sahrens znode_cache = NULL; 3754e9583b2STom Erickson rw_destroy(&zfsvfs_lock); 376fa9e4066Sahrens } 377fa9e4066Sahrens 378fa9e4066Sahrens struct vnodeops *zfs_dvnodeops; 379fa9e4066Sahrens struct vnodeops *zfs_fvnodeops; 380fa9e4066Sahrens struct vnodeops *zfs_symvnodeops; 381fa9e4066Sahrens struct vnodeops *zfs_xdvnodeops; 382fa9e4066Sahrens struct vnodeops *zfs_evnodeops; 383743a77edSAlan Wright struct vnodeops *zfs_sharevnodeops; 384fa9e4066Sahrens 385fa9e4066Sahrens void 386fa9e4066Sahrens zfs_remove_op_tables() 387fa9e4066Sahrens { 388fa9e4066Sahrens /* 389fa9e4066Sahrens * Remove vfs ops 390fa9e4066Sahrens */ 391fa9e4066Sahrens ASSERT(zfsfstype); 392fa9e4066Sahrens (void) vfs_freevfsops_by_type(zfsfstype); 393fa9e4066Sahrens zfsfstype = 0; 394fa9e4066Sahrens 395fa9e4066Sahrens /* 396fa9e4066Sahrens * Remove vnode ops 397fa9e4066Sahrens */ 398fa9e4066Sahrens if (zfs_dvnodeops) 399fa9e4066Sahrens vn_freevnodeops(zfs_dvnodeops); 400fa9e4066Sahrens if (zfs_fvnodeops) 401fa9e4066Sahrens vn_freevnodeops(zfs_fvnodeops); 402fa9e4066Sahrens if (zfs_symvnodeops) 403fa9e4066Sahrens vn_freevnodeops(zfs_symvnodeops); 404fa9e4066Sahrens if (zfs_xdvnodeops) 405fa9e4066Sahrens vn_freevnodeops(zfs_xdvnodeops); 406fa9e4066Sahrens if (zfs_evnodeops) 407fa9e4066Sahrens vn_freevnodeops(zfs_evnodeops); 408743a77edSAlan Wright if (zfs_sharevnodeops) 409743a77edSAlan Wright vn_freevnodeops(zfs_sharevnodeops); 410fa9e4066Sahrens 411fa9e4066Sahrens zfs_dvnodeops = NULL; 412fa9e4066Sahrens zfs_fvnodeops = NULL; 413fa9e4066Sahrens zfs_symvnodeops = NULL; 414fa9e4066Sahrens zfs_xdvnodeops = NULL; 415fa9e4066Sahrens zfs_evnodeops = NULL; 416743a77edSAlan Wright zfs_sharevnodeops = NULL; 417fa9e4066Sahrens } 418fa9e4066Sahrens 419fa9e4066Sahrens extern const fs_operation_def_t zfs_dvnodeops_template[]; 420fa9e4066Sahrens extern const fs_operation_def_t zfs_fvnodeops_template[]; 421fa9e4066Sahrens extern const fs_operation_def_t zfs_xdvnodeops_template[]; 422fa9e4066Sahrens extern const fs_operation_def_t zfs_symvnodeops_template[]; 423fa9e4066Sahrens extern const fs_operation_def_t zfs_evnodeops_template[]; 424743a77edSAlan Wright extern const fs_operation_def_t zfs_sharevnodeops_template[]; 425fa9e4066Sahrens 426fa9e4066Sahrens int 427fa9e4066Sahrens zfs_create_op_tables() 428fa9e4066Sahrens { 429fa9e4066Sahrens int error; 430fa9e4066Sahrens 431fa9e4066Sahrens /* 432fa9e4066Sahrens * zfs_dvnodeops can be set if mod_remove() calls mod_installfs() 433fa9e4066Sahrens * due to a failure to remove the the 2nd modlinkage (zfs_modldrv). 434fa9e4066Sahrens * In this case we just return as the ops vectors are already set up. 435fa9e4066Sahrens */ 436fa9e4066Sahrens if (zfs_dvnodeops) 437fa9e4066Sahrens return (0); 438fa9e4066Sahrens 439fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template, 440fa9e4066Sahrens &zfs_dvnodeops); 441fa9e4066Sahrens if (error) 442fa9e4066Sahrens return (error); 443fa9e4066Sahrens 444fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template, 445fa9e4066Sahrens &zfs_fvnodeops); 446fa9e4066Sahrens if (error) 447fa9e4066Sahrens return (error); 448fa9e4066Sahrens 449fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template, 450fa9e4066Sahrens &zfs_symvnodeops); 451fa9e4066Sahrens if (error) 452fa9e4066Sahrens return (error); 453fa9e4066Sahrens 454fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template, 455fa9e4066Sahrens &zfs_xdvnodeops); 456fa9e4066Sahrens if (error) 457fa9e4066Sahrens return (error); 458fa9e4066Sahrens 459fa9e4066Sahrens error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template, 460fa9e4066Sahrens &zfs_evnodeops); 461743a77edSAlan Wright if (error) 462743a77edSAlan Wright return (error); 463743a77edSAlan Wright 464743a77edSAlan Wright error = vn_make_ops(MNTTYPE_ZFS, zfs_sharevnodeops_template, 465743a77edSAlan Wright &zfs_sharevnodeops); 466743a77edSAlan Wright 467743a77edSAlan Wright return (error); 468743a77edSAlan Wright } 469743a77edSAlan Wright 4709e1320c0SMark Shellenbaum int 471743a77edSAlan Wright zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) 472743a77edSAlan Wright { 47389459e17SMark Shellenbaum zfs_acl_ids_t acl_ids; 474743a77edSAlan Wright vattr_t vattr; 475743a77edSAlan Wright znode_t *sharezp; 476743a77edSAlan Wright vnode_t *vp; 477743a77edSAlan Wright znode_t *zp; 478743a77edSAlan Wright int error; 479743a77edSAlan Wright 480743a77edSAlan Wright vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; 481743a77edSAlan Wright vattr.va_type = VDIR; 482743a77edSAlan Wright vattr.va_mode = S_IFDIR|0555; 483743a77edSAlan Wright vattr.va_uid = crgetuid(kcred); 484743a77edSAlan Wright vattr.va_gid = crgetgid(kcred); 485743a77edSAlan Wright 486743a77edSAlan Wright sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP); 487744947dcSTom Erickson ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs)); 488744947dcSTom Erickson sharezp->z_moved = 0; 489743a77edSAlan Wright sharezp->z_unlinked = 0; 490743a77edSAlan Wright sharezp->z_atime_dirty = 0; 491743a77edSAlan Wright sharezp->z_zfsvfs = zfsvfs; 4920a586ceaSMark Shellenbaum sharezp->z_is_sa = zfsvfs->z_use_sa; 493743a77edSAlan Wright 494743a77edSAlan Wright vp = ZTOV(sharezp); 495743a77edSAlan Wright vn_reinit(vp); 496743a77edSAlan Wright vp->v_type = VDIR; 497743a77edSAlan Wright 49889459e17SMark Shellenbaum VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, 49989459e17SMark Shellenbaum kcred, NULL, &acl_ids)); 5000a586ceaSMark Shellenbaum zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); 501743a77edSAlan Wright ASSERT3P(zp, ==, sharezp); 502743a77edSAlan Wright ASSERT(!vn_in_dnlc(ZTOV(sharezp))); /* not valid to move */ 503743a77edSAlan Wright POINTER_INVALIDATE(&sharezp->z_zfsvfs); 504743a77edSAlan Wright error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 505743a77edSAlan Wright ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx); 506743a77edSAlan Wright zfsvfs->z_shares_dir = sharezp->z_id; 507743a77edSAlan Wright 50889459e17SMark Shellenbaum zfs_acl_ids_free(&acl_ids); 509743a77edSAlan Wright ZTOV(sharezp)->v_count = 0; 5100a586ceaSMark Shellenbaum sa_handle_destroy(sharezp->z_sa_hdl); 511743a77edSAlan Wright kmem_cache_free(znode_cache, sharezp); 512fa9e4066Sahrens 513fa9e4066Sahrens return (error); 514fa9e4066Sahrens } 515fa9e4066Sahrens 51672fc53bcSmarks /* 51772fc53bcSmarks * define a couple of values we need available 51872fc53bcSmarks * for both 64 and 32 bit environments. 51972fc53bcSmarks */ 52072fc53bcSmarks #ifndef NBITSMINOR64 52172fc53bcSmarks #define NBITSMINOR64 32 52272fc53bcSmarks #endif 52372fc53bcSmarks #ifndef MAXMAJ64 52472fc53bcSmarks #define MAXMAJ64 0xffffffffUL 52572fc53bcSmarks #endif 52672fc53bcSmarks #ifndef MAXMIN64 52772fc53bcSmarks #define MAXMIN64 0xffffffffUL 52872fc53bcSmarks #endif 52972fc53bcSmarks 53072fc53bcSmarks /* 53172fc53bcSmarks * Create special expldev for ZFS private use. 53272fc53bcSmarks * Can't use standard expldev since it doesn't do 53372fc53bcSmarks * what we want. The standard expldev() takes a 53472fc53bcSmarks * dev32_t in LP64 and expands it to a long dev_t. 53572fc53bcSmarks * We need an interface that takes a dev32_t in ILP32 53672fc53bcSmarks * and expands it to a long dev_t. 53772fc53bcSmarks */ 53872fc53bcSmarks static uint64_t 53972fc53bcSmarks zfs_expldev(dev_t dev) 54072fc53bcSmarks { 54172fc53bcSmarks #ifndef _LP64 54272fc53bcSmarks major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32; 54372fc53bcSmarks return (((uint64_t)major << NBITSMINOR64) | 54472fc53bcSmarks ((minor_t)dev & MAXMIN32)); 54572fc53bcSmarks #else 54672fc53bcSmarks return (dev); 54772fc53bcSmarks #endif 54872fc53bcSmarks } 54972fc53bcSmarks 55072fc53bcSmarks /* 55172fc53bcSmarks * Special cmpldev for ZFS private use. 55272fc53bcSmarks * Can't use standard cmpldev since it takes 55372fc53bcSmarks * a long dev_t and compresses it to dev32_t in 55472fc53bcSmarks * LP64. We need to do a compaction of a long dev_t 55572fc53bcSmarks * to a dev32_t in ILP32. 55672fc53bcSmarks */ 55772fc53bcSmarks dev_t 55872fc53bcSmarks zfs_cmpldev(uint64_t dev) 55972fc53bcSmarks { 56072fc53bcSmarks #ifndef _LP64 56172fc53bcSmarks minor_t minor = (minor_t)dev & MAXMIN64; 56272fc53bcSmarks major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64; 56372fc53bcSmarks 56472fc53bcSmarks if (major > MAXMAJ32 || minor > MAXMIN32) 56572fc53bcSmarks return (NODEV32); 56672fc53bcSmarks 56772fc53bcSmarks return (((dev32_t)major << NBITSMINOR32) | minor); 56872fc53bcSmarks #else 56972fc53bcSmarks return (dev); 57072fc53bcSmarks #endif 57172fc53bcSmarks } 57272fc53bcSmarks 5734ccbb6e7Sahrens static void 5740a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp, 5750a586ceaSMark Shellenbaum dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl) 5764ccbb6e7Sahrens { 577b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs)); 578b5fca8f8Stomee ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id))); 5794ccbb6e7Sahrens 5804ccbb6e7Sahrens mutex_enter(&zp->z_lock); 5814ccbb6e7Sahrens 5820a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl == NULL); 5836638ae1dSMark Shellenbaum ASSERT(zp->z_acl_cached == NULL); 5840a586ceaSMark Shellenbaum if (sa_hdl == NULL) { 5850a586ceaSMark Shellenbaum VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, zp, 5860a586ceaSMark Shellenbaum SA_HDL_SHARED, &zp->z_sa_hdl)); 5870a586ceaSMark Shellenbaum } else { 5880a586ceaSMark Shellenbaum zp->z_sa_hdl = sa_hdl; 5890a586ceaSMark Shellenbaum sa_set_userp(sa_hdl, zp); 5900a586ceaSMark Shellenbaum } 5914ccbb6e7Sahrens 5920a586ceaSMark Shellenbaum zp->z_is_sa = (obj_type == DMU_OT_SA) ? B_TRUE : B_FALSE; 5934ccbb6e7Sahrens 5944ccbb6e7Sahrens /* 5954ccbb6e7Sahrens * Slap on VROOT if we are the root znode 5964ccbb6e7Sahrens */ 5974ccbb6e7Sahrens if (zp->z_id == zfsvfs->z_root) 5984ccbb6e7Sahrens ZTOV(zp)->v_flag |= VROOT; 5994ccbb6e7Sahrens 6004ccbb6e7Sahrens mutex_exit(&zp->z_lock); 6014ccbb6e7Sahrens vn_exists(ZTOV(zp)); 6024ccbb6e7Sahrens } 6034ccbb6e7Sahrens 604874395d5Smaybee void 6054ccbb6e7Sahrens zfs_znode_dmu_fini(znode_t *zp) 6064ccbb6e7Sahrens { 607b5fca8f8Stomee ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) || 608b5fca8f8Stomee zp->z_unlinked || 609874395d5Smaybee RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock)); 6100a586ceaSMark Shellenbaum 6110a586ceaSMark Shellenbaum sa_handle_destroy(zp->z_sa_hdl); 6120a586ceaSMark Shellenbaum zp->z_sa_hdl = NULL; 6134ccbb6e7Sahrens } 6144ccbb6e7Sahrens 615fa9e4066Sahrens /* 616fa9e4066Sahrens * Construct a new znode/vnode and intialize. 617fa9e4066Sahrens * 618fa9e4066Sahrens * This does not do a call to dmu_set_user() that is 619fa9e4066Sahrens * up to the caller to do, in case you don't want to 620fa9e4066Sahrens * return the znode 621fa9e4066Sahrens */ 622ea8dc4b6Seschrock static znode_t * 6230a586ceaSMark Shellenbaum zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, 6240a586ceaSMark Shellenbaum dmu_object_type_t obj_type, sa_handle_t *hdl) 625fa9e4066Sahrens { 626fa9e4066Sahrens znode_t *zp; 627fa9e4066Sahrens vnode_t *vp; 6280a586ceaSMark Shellenbaum uint64_t mode; 6290a586ceaSMark Shellenbaum uint64_t parent; 6300a586ceaSMark Shellenbaum sa_bulk_attr_t bulk[9]; 6310a586ceaSMark Shellenbaum int count = 0; 632fa9e4066Sahrens 633fa9e4066Sahrens zp = kmem_cache_alloc(znode_cache, KM_SLEEP); 634fa9e4066Sahrens 635fa9e4066Sahrens ASSERT(zp->z_dirlocks == NULL); 636b5fca8f8Stomee ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); 637744947dcSTom Erickson zp->z_moved = 0; 638fa9e4066Sahrens 639b5fca8f8Stomee /* 640b5fca8f8Stomee * Defer setting z_zfsvfs until the znode is ready to be a candidate for 641b5fca8f8Stomee * the zfs_znode_move() callback. 642b5fca8f8Stomee */ 6430a586ceaSMark Shellenbaum zp->z_sa_hdl = NULL; 644893a6d32Sahrens zp->z_unlinked = 0; 645fa9e4066Sahrens zp->z_atime_dirty = 0; 646fa9e4066Sahrens zp->z_mapcnt = 0; 6474ccbb6e7Sahrens zp->z_id = db->db_object; 648fa9e4066Sahrens zp->z_blksz = blksz; 649fa9e4066Sahrens zp->z_seq = 0x7A4653; 65067bd71c6Sperrin zp->z_sync_cnt = 0; 6514ccbb6e7Sahrens 6524ccbb6e7Sahrens vp = ZTOV(zp); 6534ccbb6e7Sahrens vn_reinit(vp); 6544ccbb6e7Sahrens 6550a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl); 6560a586ceaSMark Shellenbaum 6570a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8); 6580a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8); 6590a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, 6600a586ceaSMark Shellenbaum &zp->z_size, 8); 6610a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL, 6620a586ceaSMark Shellenbaum &zp->z_links, 8); 6630a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 6640a586ceaSMark Shellenbaum &zp->z_pflags, 8); 6650a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8); 6660a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, 6670a586ceaSMark Shellenbaum &zp->z_atime, 16); 6680a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, 669f1696b23SMark Shellenbaum &zp->z_uid, 8); 6700a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, 671f1696b23SMark Shellenbaum &zp->z_gid, 8); 6720a586ceaSMark Shellenbaum 6730a586ceaSMark Shellenbaum if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { 6740a586ceaSMark Shellenbaum if (hdl == NULL) 6750a586ceaSMark Shellenbaum sa_handle_destroy(zp->z_sa_hdl); 6760a586ceaSMark Shellenbaum kmem_cache_free(znode_cache, zp); 6770a586ceaSMark Shellenbaum return (NULL); 6780a586ceaSMark Shellenbaum } 679fa9e4066Sahrens 6800a586ceaSMark Shellenbaum zp->z_mode = mode; 681fa9e4066Sahrens vp->v_vfsp = zfsvfs->z_parent->z_vfs; 6820a586ceaSMark Shellenbaum 6830a586ceaSMark Shellenbaum vp->v_type = IFTOVT((mode_t)mode); 684fa9e4066Sahrens 685fa9e4066Sahrens switch (vp->v_type) { 686fa9e4066Sahrens case VDIR: 6870a586ceaSMark Shellenbaum if (zp->z_pflags & ZFS_XATTR) { 688fa9e4066Sahrens vn_setops(vp, zfs_xdvnodeops); 689fa9e4066Sahrens vp->v_flag |= V_XATTRDIR; 6904ccbb6e7Sahrens } else { 691fa9e4066Sahrens vn_setops(vp, zfs_dvnodeops); 6924ccbb6e7Sahrens } 6937f6e3e7dSperrin zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */ 694fa9e4066Sahrens break; 695fa9e4066Sahrens case VBLK: 696fa9e4066Sahrens case VCHR: 6970a586ceaSMark Shellenbaum { 6980a586ceaSMark Shellenbaum uint64_t rdev; 6990a586ceaSMark Shellenbaum VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs), 7000a586ceaSMark Shellenbaum &rdev, sizeof (rdev)) == 0); 7010a586ceaSMark Shellenbaum 7020a586ceaSMark Shellenbaum vp->v_rdev = zfs_cmpldev(rdev); 7030a586ceaSMark Shellenbaum } 704fa9e4066Sahrens /*FALLTHROUGH*/ 705fa9e4066Sahrens case VFIFO: 706fa9e4066Sahrens case VSOCK: 707fa9e4066Sahrens case VDOOR: 708fa9e4066Sahrens vn_setops(vp, zfs_fvnodeops); 709fa9e4066Sahrens break; 710fa9e4066Sahrens case VREG: 711fa9e4066Sahrens vp->v_flag |= VMODSORT; 7120a586ceaSMark Shellenbaum if (parent == zfsvfs->z_shares_dir) { 713f1696b23SMark Shellenbaum ASSERT(zp->z_uid == 0 && zp->z_gid == 0); 714743a77edSAlan Wright vn_setops(vp, zfs_sharevnodeops); 7150a586ceaSMark Shellenbaum } else { 716743a77edSAlan Wright vn_setops(vp, zfs_fvnodeops); 7170a586ceaSMark Shellenbaum } 718fa9e4066Sahrens break; 719fa9e4066Sahrens case VLNK: 720fa9e4066Sahrens vn_setops(vp, zfs_symvnodeops); 721fa9e4066Sahrens break; 722fa9e4066Sahrens default: 723fa9e4066Sahrens vn_setops(vp, zfs_evnodeops); 724fa9e4066Sahrens break; 725fa9e4066Sahrens } 726fa9e4066Sahrens 727b5fca8f8Stomee mutex_enter(&zfsvfs->z_znodes_lock); 728b5fca8f8Stomee list_insert_tail(&zfsvfs->z_all_znodes, zp); 729b5fca8f8Stomee membar_producer(); 730b5fca8f8Stomee /* 731b5fca8f8Stomee * Everything else must be valid before assigning z_zfsvfs makes the 732b5fca8f8Stomee * znode eligible for zfs_znode_move(). 733b5fca8f8Stomee */ 734b5fca8f8Stomee zp->z_zfsvfs = zfsvfs; 735b5fca8f8Stomee mutex_exit(&zfsvfs->z_znodes_lock); 736b5fca8f8Stomee 737874395d5Smaybee VFS_HOLD(zfsvfs->z_vfs); 738fa9e4066Sahrens return (zp); 739fa9e4066Sahrens } 740fa9e4066Sahrens 7410a586ceaSMark Shellenbaum static uint64_t empty_xattr; 7420a586ceaSMark Shellenbaum static uint64_t pad[4]; 7430a586ceaSMark Shellenbaum static zfs_acl_phys_t acl_phys; 744fa9e4066Sahrens /* 745fa9e4066Sahrens * Create a new DMU object to hold a zfs znode. 746fa9e4066Sahrens * 747fa9e4066Sahrens * IN: dzp - parent directory for new znode 748fa9e4066Sahrens * vap - file attributes for new znode 749fa9e4066Sahrens * tx - dmu transaction id for zap operations 750fa9e4066Sahrens * cr - credentials of caller 751fa9e4066Sahrens * flag - flags: 752fa9e4066Sahrens * IS_ROOT_NODE - new object will be root 753fa9e4066Sahrens * IS_XATTR - new object is an attribute 754da6c28aaSamw * bonuslen - length of bonus buffer 755da6c28aaSamw * setaclp - File/Dir initial ACL 756da6c28aaSamw * fuidp - Tracks fuid allocation. 757fa9e4066Sahrens * 7584ccbb6e7Sahrens * OUT: zpp - allocated znode 759fa9e4066Sahrens * 760fa9e4066Sahrens */ 761fa9e4066Sahrens void 7624ccbb6e7Sahrens zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, 7630a586ceaSMark Shellenbaum uint_t flag, znode_t **zpp, zfs_acl_ids_t *acl_ids) 764fa9e4066Sahrens { 7650a586ceaSMark Shellenbaum uint64_t crtime[2], atime[2], mtime[2], ctime[2]; 7660a586ceaSMark Shellenbaum uint64_t mode, size, links, parent, pflags; 767744947dcSTom Erickson uint64_t dzp_pflags = 0; 7680a586ceaSMark Shellenbaum uint64_t rdev = 0; 769fa9e4066Sahrens zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 7700a586ceaSMark Shellenbaum dmu_buf_t *db; 771fa9e4066Sahrens timestruc_t now; 7724ccbb6e7Sahrens uint64_t gen, obj; 7730a586ceaSMark Shellenbaum int bonuslen; 7740a586ceaSMark Shellenbaum sa_handle_t *sa_hdl; 7750a586ceaSMark Shellenbaum dmu_object_type_t obj_type; 7760a586ceaSMark Shellenbaum sa_bulk_attr_t sa_attrs[ZPL_END]; 7770a586ceaSMark Shellenbaum int cnt = 0; 7780a586ceaSMark Shellenbaum zfs_acl_locator_cb_t locate = { 0 }; 779fa9e4066Sahrens 780fa9e4066Sahrens ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); 781fa9e4066Sahrens 7821209a471SNeil Perrin if (zfsvfs->z_replay) { 7834ccbb6e7Sahrens obj = vap->va_nodeid; 784fa9e4066Sahrens now = vap->va_ctime; /* see zfs_replay_create() */ 785fa9e4066Sahrens gen = vap->va_nblocks; /* ditto */ 786fa9e4066Sahrens } else { 7874ccbb6e7Sahrens obj = 0; 788fa9e4066Sahrens gethrestime(&now); 789fa9e4066Sahrens gen = dmu_tx_get_txg(tx); 790fa9e4066Sahrens } 791fa9e4066Sahrens 7920a586ceaSMark Shellenbaum obj_type = zfsvfs->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE; 7930a586ceaSMark Shellenbaum bonuslen = (obj_type == DMU_OT_SA) ? 7940a586ceaSMark Shellenbaum DN_MAX_BONUSLEN : ZFS_OLD_ZNODE_PHYS_SIZE; 7950a586ceaSMark Shellenbaum 796fa9e4066Sahrens /* 797fa9e4066Sahrens * Create a new DMU object. 798fa9e4066Sahrens */ 799ea8dc4b6Seschrock /* 800ea8dc4b6Seschrock * There's currently no mechanism for pre-reading the blocks that will 801744947dcSTom Erickson * be needed to allocate a new object, so we accept the small chance 802ea8dc4b6Seschrock * that there will be an i/o error and we will fail one of the 803ea8dc4b6Seschrock * assertions below. 804ea8dc4b6Seschrock */ 805fa9e4066Sahrens if (vap->va_type == VDIR) { 8064a1f0cc9SMark Shellenbaum if (zfsvfs->z_replay) { 80743466aaeSMax Grossman VERIFY0(zap_create_claim_norm(zfsvfs->z_os, obj, 808da6c28aaSamw zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS, 80943466aaeSMax Grossman obj_type, bonuslen, tx)); 810fa9e4066Sahrens } else { 8114ccbb6e7Sahrens obj = zap_create_norm(zfsvfs->z_os, 812da6c28aaSamw zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS, 8130a586ceaSMark Shellenbaum obj_type, bonuslen, tx); 814fa9e4066Sahrens } 815fa9e4066Sahrens } else { 8164a1f0cc9SMark Shellenbaum if (zfsvfs->z_replay) { 81743466aaeSMax Grossman VERIFY0(dmu_object_claim(zfsvfs->z_os, obj, 818fa9e4066Sahrens DMU_OT_PLAIN_FILE_CONTENTS, 0, 81943466aaeSMax Grossman obj_type, bonuslen, tx)); 820fa9e4066Sahrens } else { 8214ccbb6e7Sahrens obj = dmu_object_alloc(zfsvfs->z_os, 822fa9e4066Sahrens DMU_OT_PLAIN_FILE_CONTENTS, 0, 8230a586ceaSMark Shellenbaum obj_type, bonuslen, tx); 824fa9e4066Sahrens } 825fa9e4066Sahrens } 82659e7834dSMark Shellenbaum 82759e7834dSMark Shellenbaum ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); 8280a586ceaSMark Shellenbaum VERIFY(0 == sa_buf_hold(zfsvfs->z_os, obj, NULL, &db)); 829fa9e4066Sahrens 830fa9e4066Sahrens /* 831fa9e4066Sahrens * If this is the root, fix up the half-initialized parent pointer 832fa9e4066Sahrens * to reference the just-allocated physical data area. 833fa9e4066Sahrens */ 834fa9e4066Sahrens if (flag & IS_ROOT_NODE) { 8354ccbb6e7Sahrens dzp->z_id = obj; 8360a586ceaSMark Shellenbaum } else { 8370a586ceaSMark Shellenbaum dzp_pflags = dzp->z_pflags; 838fa9e4066Sahrens } 839fa9e4066Sahrens 840fa9e4066Sahrens /* 841fa9e4066Sahrens * If parent is an xattr, so am I. 842fa9e4066Sahrens */ 8430a586ceaSMark Shellenbaum if (dzp_pflags & ZFS_XATTR) { 844fa9e4066Sahrens flag |= IS_XATTR; 845fa9e4066Sahrens } 846fa9e4066Sahrens 847da6c28aaSamw if (zfsvfs->z_use_fuids) 8480a586ceaSMark Shellenbaum pflags = ZFS_ARCHIVE | ZFS_AV_MODIFIED; 8490a586ceaSMark Shellenbaum else 8500a586ceaSMark Shellenbaum pflags = 0; 851da6c28aaSamw 852fa9e4066Sahrens if (vap->va_type == VDIR) { 8530a586ceaSMark Shellenbaum size = 2; /* contents ("." and "..") */ 8540a586ceaSMark Shellenbaum links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1; 8550a586ceaSMark Shellenbaum } else { 8560a586ceaSMark Shellenbaum size = links = 0; 8570a586ceaSMark Shellenbaum } 8580a586ceaSMark Shellenbaum 8590a586ceaSMark Shellenbaum if (vap->va_type == VBLK || vap->va_type == VCHR) { 8600a586ceaSMark Shellenbaum rdev = zfs_expldev(vap->va_rdev); 861fa9e4066Sahrens } 862fa9e4066Sahrens 8630a586ceaSMark Shellenbaum parent = dzp->z_id; 8640a586ceaSMark Shellenbaum mode = acl_ids->z_mode; 865fa9e4066Sahrens if (flag & IS_XATTR) 8660a586ceaSMark Shellenbaum pflags |= ZFS_XATTR; 867fa9e4066Sahrens 8680a586ceaSMark Shellenbaum /* 8690a586ceaSMark Shellenbaum * No execs denied will be deterimed when zfs_mode_compute() is called. 8700a586ceaSMark Shellenbaum */ 8710a586ceaSMark Shellenbaum pflags |= acl_ids->z_aclp->z_hints & 8720a586ceaSMark Shellenbaum (ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|ZFS_ACL_AUTO_INHERIT| 8730a586ceaSMark Shellenbaum ZFS_ACL_DEFAULTED|ZFS_ACL_PROTECTED); 874fa9e4066Sahrens 8750a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, crtime); 8760a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, ctime); 877fa9e4066Sahrens 878fa9e4066Sahrens if (vap->va_mask & AT_ATIME) { 8790a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&vap->va_atime, atime); 880fa9e4066Sahrens } else { 8810a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, atime); 882fa9e4066Sahrens } 883fa9e4066Sahrens 884fa9e4066Sahrens if (vap->va_mask & AT_MTIME) { 8850a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&vap->va_mtime, mtime); 8860a586ceaSMark Shellenbaum } else { 8870a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, mtime); 8880a586ceaSMark Shellenbaum } 8890a586ceaSMark Shellenbaum 8900a586ceaSMark Shellenbaum /* Now add in all of the "SA" attributes */ 8910a586ceaSMark Shellenbaum VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, NULL, SA_HDL_SHARED, 8920a586ceaSMark Shellenbaum &sa_hdl)); 8930a586ceaSMark Shellenbaum 8940a586ceaSMark Shellenbaum /* 8950a586ceaSMark Shellenbaum * Setup the array of attributes to be replaced/set on the new file 8960a586ceaSMark Shellenbaum * 8970a586ceaSMark Shellenbaum * order for DMU_OT_ZNODE is critical since it needs to be constructed 8980a586ceaSMark Shellenbaum * in the old znode_phys_t format. Don't change this ordering 8990a586ceaSMark Shellenbaum */ 9000a586ceaSMark Shellenbaum 9010a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9020a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs), 9030a586ceaSMark Shellenbaum NULL, &atime, 16); 9040a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs), 9050a586ceaSMark Shellenbaum NULL, &mtime, 16); 9060a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs), 9070a586ceaSMark Shellenbaum NULL, &ctime, 16); 9080a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs), 9090a586ceaSMark Shellenbaum NULL, &crtime, 16); 9100a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs), 9110a586ceaSMark Shellenbaum NULL, &gen, 8); 9120a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs), 9130a586ceaSMark Shellenbaum NULL, &mode, 8); 9140a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs), 9150a586ceaSMark Shellenbaum NULL, &size, 8); 9160a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs), 9170a586ceaSMark Shellenbaum NULL, &parent, 8); 918fa9e4066Sahrens } else { 9190a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs), 9200a586ceaSMark Shellenbaum NULL, &mode, 8); 9210a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs), 9220a586ceaSMark Shellenbaum NULL, &size, 8); 9230a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs), 9240a586ceaSMark Shellenbaum NULL, &gen, 8); 9250a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL, 9260a586ceaSMark Shellenbaum &acl_ids->z_fuid, 8); 9270a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL, 9280a586ceaSMark Shellenbaum &acl_ids->z_fgid, 8); 9290a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs), 9300a586ceaSMark Shellenbaum NULL, &parent, 8); 9310a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs), 9320a586ceaSMark Shellenbaum NULL, &pflags, 8); 9330a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs), 9340a586ceaSMark Shellenbaum NULL, &atime, 16); 9350a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs), 9360a586ceaSMark Shellenbaum NULL, &mtime, 16); 9370a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs), 9380a586ceaSMark Shellenbaum NULL, &ctime, 16); 9390a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs), 9400a586ceaSMark Shellenbaum NULL, &crtime, 16); 9410a586ceaSMark Shellenbaum } 9420a586ceaSMark Shellenbaum 9430a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zfsvfs), NULL, &links, 8); 9440a586ceaSMark Shellenbaum 9450a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9460a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zfsvfs), NULL, 9470a586ceaSMark Shellenbaum &empty_xattr, 8); 9480a586ceaSMark Shellenbaum } 9490a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE || 9500a586ceaSMark Shellenbaum (vap->va_type == VBLK || vap->va_type == VCHR)) { 9510a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zfsvfs), 9520a586ceaSMark Shellenbaum NULL, &rdev, 8); 9530a586ceaSMark Shellenbaum 954fa9e4066Sahrens } 9550a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE) { 9560a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs), 9570a586ceaSMark Shellenbaum NULL, &pflags, 8); 9580a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL, 9590a586ceaSMark Shellenbaum &acl_ids->z_fuid, 8); 9600a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL, 9610a586ceaSMark Shellenbaum &acl_ids->z_fgid, 8); 9620a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zfsvfs), NULL, pad, 9630a586ceaSMark Shellenbaum sizeof (uint64_t) * 4); 9640a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zfsvfs), NULL, 9650a586ceaSMark Shellenbaum &acl_phys, sizeof (zfs_acl_phys_t)); 9660a586ceaSMark Shellenbaum } else if (acl_ids->z_aclp->z_version >= ZFS_ACL_VERSION_FUID) { 9670a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zfsvfs), NULL, 9680a586ceaSMark Shellenbaum &acl_ids->z_aclp->z_acl_count, 8); 9690a586ceaSMark Shellenbaum locate.cb_aclp = acl_ids->z_aclp; 9700a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs), 9710a586ceaSMark Shellenbaum zfs_acl_data_locator, &locate, 9720a586ceaSMark Shellenbaum acl_ids->z_aclp->z_acl_bytes); 97327dd1e87SMark Shellenbaum mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags, 97427dd1e87SMark Shellenbaum acl_ids->z_fuid, acl_ids->z_fgid); 9750a586ceaSMark Shellenbaum } 9760a586ceaSMark Shellenbaum 9770a586ceaSMark Shellenbaum VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0); 9780a586ceaSMark Shellenbaum 979874395d5Smaybee if (!(flag & IS_ROOT_NODE)) { 9800a586ceaSMark Shellenbaum *zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, sa_hdl); 9810a586ceaSMark Shellenbaum ASSERT(*zpp != NULL); 982874395d5Smaybee } else { 983874395d5Smaybee /* 984874395d5Smaybee * If we are creating the root node, the "parent" we 985874395d5Smaybee * passed in is the znode for the root. 986874395d5Smaybee */ 987874395d5Smaybee *zpp = dzp; 9880a586ceaSMark Shellenbaum 9890a586ceaSMark Shellenbaum (*zpp)->z_sa_hdl = sa_hdl; 990874395d5Smaybee } 9910a586ceaSMark Shellenbaum 9920a586ceaSMark Shellenbaum (*zpp)->z_pflags = pflags; 9930a586ceaSMark Shellenbaum (*zpp)->z_mode = mode; 99459e7834dSMark Shellenbaum 9958f2529deSMark Shellenbaum if (vap->va_mask & AT_XVATTR) 9968f2529deSMark Shellenbaum zfs_xvattr_set(*zpp, (xvattr_t *)vap, tx); 9978f2529deSMark Shellenbaum 9980a586ceaSMark Shellenbaum if (obj_type == DMU_OT_ZNODE || 9990a586ceaSMark Shellenbaum acl_ids->z_aclp->z_version < ZFS_ACL_VERSION_FUID) { 100043466aaeSMax Grossman VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx)); 10010a586ceaSMark Shellenbaum } 100259e7834dSMark Shellenbaum ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); 1003fa9e4066Sahrens } 1004fa9e4066Sahrens 10050a586ceaSMark Shellenbaum /* 1006f7170741SWill Andrews * Update in-core attributes. It is assumed the caller will be doing an 1007f7170741SWill Andrews * sa_bulk_update to push the changes out. 10080a586ceaSMark Shellenbaum */ 1009da6c28aaSamw void 10100a586ceaSMark Shellenbaum zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) 1011da6c28aaSamw { 1012da6c28aaSamw xoptattr_t *xoap; 1013da6c28aaSamw 1014da6c28aaSamw xoap = xva_getxoptattr(xvap); 1015da6c28aaSamw ASSERT(xoap); 1016da6c28aaSamw 1017da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { 10180a586ceaSMark Shellenbaum uint64_t times[2]; 10190a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&xoap->xoa_createtime, times); 10200a586ceaSMark Shellenbaum (void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), 10210a586ceaSMark Shellenbaum ×, sizeof (times), tx); 1022da6c28aaSamw XVA_SET_RTN(xvap, XAT_CREATETIME); 1023da6c28aaSamw } 1024da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 10250a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly, 10260a586ceaSMark Shellenbaum zp->z_pflags, tx); 1027da6c28aaSamw XVA_SET_RTN(xvap, XAT_READONLY); 1028da6c28aaSamw } 1029da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 10300a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden, 10310a586ceaSMark Shellenbaum zp->z_pflags, tx); 1032da6c28aaSamw XVA_SET_RTN(xvap, XAT_HIDDEN); 1033da6c28aaSamw } 1034da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 10350a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system, 10360a586ceaSMark Shellenbaum zp->z_pflags, tx); 1037da6c28aaSamw XVA_SET_RTN(xvap, XAT_SYSTEM); 1038da6c28aaSamw } 1039da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 10400a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive, 10410a586ceaSMark Shellenbaum zp->z_pflags, tx); 1042da6c28aaSamw XVA_SET_RTN(xvap, XAT_ARCHIVE); 1043da6c28aaSamw } 1044da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { 10450a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable, 10460a586ceaSMark Shellenbaum zp->z_pflags, tx); 1047da6c28aaSamw XVA_SET_RTN(xvap, XAT_IMMUTABLE); 1048da6c28aaSamw } 1049da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { 10500a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink, 10510a586ceaSMark Shellenbaum zp->z_pflags, tx); 1052da6c28aaSamw XVA_SET_RTN(xvap, XAT_NOUNLINK); 1053da6c28aaSamw } 1054da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { 10550a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly, 10560a586ceaSMark Shellenbaum zp->z_pflags, tx); 1057da6c28aaSamw XVA_SET_RTN(xvap, XAT_APPENDONLY); 1058da6c28aaSamw } 1059da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { 10600a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump, 10610a586ceaSMark Shellenbaum zp->z_pflags, tx); 1062da6c28aaSamw XVA_SET_RTN(xvap, XAT_NODUMP); 1063da6c28aaSamw } 1064da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { 10650a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque, 10660a586ceaSMark Shellenbaum zp->z_pflags, tx); 1067da6c28aaSamw XVA_SET_RTN(xvap, XAT_OPAQUE); 1068da6c28aaSamw } 1069da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { 1070da6c28aaSamw ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED, 10710a586ceaSMark Shellenbaum xoap->xoa_av_quarantined, zp->z_pflags, tx); 1072da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); 1073da6c28aaSamw } 1074da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { 10750a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified, 10760a586ceaSMark Shellenbaum zp->z_pflags, tx); 1077da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_MODIFIED); 1078da6c28aaSamw } 1079da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { 10800a586ceaSMark Shellenbaum zfs_sa_set_scanstamp(zp, xvap, tx); 1081da6c28aaSamw XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP); 1082da6c28aaSamw } 10837a286c47SDai Ngo if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { 10840a586ceaSMark Shellenbaum ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse, 10850a586ceaSMark Shellenbaum zp->z_pflags, tx); 10867a286c47SDai Ngo XVA_SET_RTN(xvap, XAT_REPARSE); 10877a286c47SDai Ngo } 1088fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { 1089fd9ee8b5Sjoyce mcintosh ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline, 1090fd9ee8b5Sjoyce mcintosh zp->z_pflags, tx); 1091fd9ee8b5Sjoyce mcintosh XVA_SET_RTN(xvap, XAT_OFFLINE); 1092fd9ee8b5Sjoyce mcintosh } 1093fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { 1094fd9ee8b5Sjoyce mcintosh ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse, 1095fd9ee8b5Sjoyce mcintosh zp->z_pflags, tx); 1096fd9ee8b5Sjoyce mcintosh XVA_SET_RTN(xvap, XAT_SPARSE); 1097fd9ee8b5Sjoyce mcintosh } 1098da6c28aaSamw } 1099da6c28aaSamw 1100fa9e4066Sahrens int 1101fa9e4066Sahrens zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp) 1102fa9e4066Sahrens { 1103fa9e4066Sahrens dmu_object_info_t doi; 1104fa9e4066Sahrens dmu_buf_t *db; 1105fa9e4066Sahrens znode_t *zp; 1106ea8dc4b6Seschrock int err; 11070a586ceaSMark Shellenbaum sa_handle_t *hdl; 1108fa9e4066Sahrens 1109fa9e4066Sahrens *zpp = NULL; 1110fa9e4066Sahrens 1111fa9e4066Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); 1112fa9e4066Sahrens 11130a586ceaSMark Shellenbaum err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db); 1114ea8dc4b6Seschrock if (err) { 1115fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1116ea8dc4b6Seschrock return (err); 1117fa9e4066Sahrens } 1118fa9e4066Sahrens 1119fa9e4066Sahrens dmu_object_info_from_db(db, &doi); 11200a586ceaSMark Shellenbaum if (doi.doi_bonus_type != DMU_OT_SA && 11210a586ceaSMark Shellenbaum (doi.doi_bonus_type != DMU_OT_ZNODE || 11220a586ceaSMark Shellenbaum (doi.doi_bonus_type == DMU_OT_ZNODE && 11230a586ceaSMark Shellenbaum doi.doi_bonus_size < sizeof (znode_phys_t)))) { 11240a586ceaSMark Shellenbaum sa_buf_rele(db, NULL); 1125fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1126be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1127fa9e4066Sahrens } 1128fa9e4066Sahrens 11290a586ceaSMark Shellenbaum hdl = dmu_buf_get_user(db); 11300a586ceaSMark Shellenbaum if (hdl != NULL) { 11310a586ceaSMark Shellenbaum zp = sa_get_userdata(hdl); 11320a586ceaSMark Shellenbaum 1133fa9e4066Sahrens 11344ccbb6e7Sahrens /* 11350a586ceaSMark Shellenbaum * Since "SA" does immediate eviction we 11360a586ceaSMark Shellenbaum * should never find a sa handle that doesn't 11370a586ceaSMark Shellenbaum * know about the znode. 11384ccbb6e7Sahrens */ 11390a586ceaSMark Shellenbaum 11400a586ceaSMark Shellenbaum ASSERT3P(zp, !=, NULL); 11410a586ceaSMark Shellenbaum 11420a586ceaSMark Shellenbaum mutex_enter(&zp->z_lock); 1143fa9e4066Sahrens ASSERT3U(zp->z_id, ==, obj_num); 1144893a6d32Sahrens if (zp->z_unlinked) { 1145be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 1146fa9e4066Sahrens } else { 11474ccbb6e7Sahrens VN_HOLD(ZTOV(zp)); 11484ccbb6e7Sahrens *zpp = zp; 11494ccbb6e7Sahrens err = 0; 1150fa9e4066Sahrens } 11510a586ceaSMark Shellenbaum sa_buf_rele(db, NULL); 1152fa9e4066Sahrens mutex_exit(&zp->z_lock); 1153ea8dc4b6Seschrock ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 11544ccbb6e7Sahrens return (err); 1155fa9e4066Sahrens } 1156fa9e4066Sahrens 1157fa9e4066Sahrens /* 1158fa9e4066Sahrens * Not found create new znode/vnode 115959e7834dSMark Shellenbaum * but only if file exists. 116059e7834dSMark Shellenbaum * 116159e7834dSMark Shellenbaum * There is a small window where zfs_vget() could 116259e7834dSMark Shellenbaum * find this object while a file create is still in 11630a586ceaSMark Shellenbaum * progress. This is checked for in zfs_znode_alloc() 11640a586ceaSMark Shellenbaum * 11650a586ceaSMark Shellenbaum * if zfs_znode_alloc() fails it will drop the hold on the 11660a586ceaSMark Shellenbaum * bonus buffer. 1167fa9e4066Sahrens */ 11680a586ceaSMark Shellenbaum zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size, 11690a586ceaSMark Shellenbaum doi.doi_bonus_type, NULL); 11700a586ceaSMark Shellenbaum if (zp == NULL) { 1171be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 11720a586ceaSMark Shellenbaum } else { 11730a586ceaSMark Shellenbaum *zpp = zp; 117459e7834dSMark Shellenbaum } 1175ea8dc4b6Seschrock ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 117659e7834dSMark Shellenbaum return (err); 1177fa9e4066Sahrens } 1178fa9e4066Sahrens 1179f18faf3fSek int 1180f18faf3fSek zfs_rezget(znode_t *zp) 1181f18faf3fSek { 1182f18faf3fSek zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1183f18faf3fSek dmu_object_info_t doi; 1184f18faf3fSek dmu_buf_t *db; 1185f18faf3fSek uint64_t obj_num = zp->z_id; 11860a586ceaSMark Shellenbaum uint64_t mode; 11870a586ceaSMark Shellenbaum sa_bulk_attr_t bulk[8]; 1188f18faf3fSek int err; 11890a586ceaSMark Shellenbaum int count = 0; 11900a586ceaSMark Shellenbaum uint64_t gen; 1191f18faf3fSek 1192f18faf3fSek ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); 1193f18faf3fSek 11940a586ceaSMark Shellenbaum mutex_enter(&zp->z_acl_lock); 11950a586ceaSMark Shellenbaum if (zp->z_acl_cached) { 11960a586ceaSMark Shellenbaum zfs_acl_free(zp->z_acl_cached); 11970a586ceaSMark Shellenbaum zp->z_acl_cached = NULL; 11980a586ceaSMark Shellenbaum } 11990a586ceaSMark Shellenbaum 12000a586ceaSMark Shellenbaum mutex_exit(&zp->z_acl_lock); 12010a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl == NULL); 12020a586ceaSMark Shellenbaum err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db); 1203f18faf3fSek if (err) { 1204f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1205f18faf3fSek return (err); 1206f18faf3fSek } 1207f18faf3fSek 1208f18faf3fSek dmu_object_info_from_db(db, &doi); 12090a586ceaSMark Shellenbaum if (doi.doi_bonus_type != DMU_OT_SA && 12100a586ceaSMark Shellenbaum (doi.doi_bonus_type != DMU_OT_ZNODE || 12110a586ceaSMark Shellenbaum (doi.doi_bonus_type == DMU_OT_ZNODE && 12120a586ceaSMark Shellenbaum doi.doi_bonus_size < sizeof (znode_phys_t)))) { 12130a586ceaSMark Shellenbaum sa_buf_rele(db, NULL); 1214f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1215be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 1216f18faf3fSek } 1217f18faf3fSek 12180a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs, zp, db, doi.doi_bonus_type, NULL); 12190a586ceaSMark Shellenbaum 12200a586ceaSMark Shellenbaum /* reload cached values */ 12210a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, 12220a586ceaSMark Shellenbaum &gen, sizeof (gen)); 12230a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, 12240a586ceaSMark Shellenbaum &zp->z_size, sizeof (zp->z_size)); 12250a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL, 12260a586ceaSMark Shellenbaum &zp->z_links, sizeof (zp->z_links)); 12270a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 12280a586ceaSMark Shellenbaum &zp->z_pflags, sizeof (zp->z_pflags)); 12290a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, 12300a586ceaSMark Shellenbaum &zp->z_atime, sizeof (zp->z_atime)); 12310a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, 1232f1696b23SMark Shellenbaum &zp->z_uid, sizeof (zp->z_uid)); 12330a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, 1234f1696b23SMark Shellenbaum &zp->z_gid, sizeof (zp->z_gid)); 12350a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, 12360a586ceaSMark Shellenbaum &mode, sizeof (mode)); 12370a586ceaSMark Shellenbaum 12380a586ceaSMark Shellenbaum if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) { 12390a586ceaSMark Shellenbaum zfs_znode_dmu_fini(zp); 1240f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1241be6fd75aSMatthew Ahrens return (SET_ERROR(EIO)); 1242f18faf3fSek } 1243f18faf3fSek 12441412a1a2SMark Shellenbaum zp->z_mode = mode; 12451412a1a2SMark Shellenbaum 12460a586ceaSMark Shellenbaum if (gen != zp->z_gen) { 12470a586ceaSMark Shellenbaum zfs_znode_dmu_fini(zp); 12480a586ceaSMark Shellenbaum ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1249be6fd75aSMatthew Ahrens return (SET_ERROR(EIO)); 12506638ae1dSMark Shellenbaum } 12516638ae1dSMark Shellenbaum 12520a586ceaSMark Shellenbaum zp->z_unlinked = (zp->z_links == 0); 12536166ad1cSek zp->z_blksz = doi.doi_data_block_size; 1254f18faf3fSek 1255f18faf3fSek ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); 1256f18faf3fSek 1257f18faf3fSek return (0); 1258f18faf3fSek } 1259f18faf3fSek 1260fa9e4066Sahrens void 1261fa9e4066Sahrens zfs_znode_delete(znode_t *zp, dmu_tx_t *tx) 1262fa9e4066Sahrens { 1263fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1264cdb0ab79Smaybee objset_t *os = zfsvfs->z_os; 12654ccbb6e7Sahrens uint64_t obj = zp->z_id; 12661412a1a2SMark Shellenbaum uint64_t acl_obj = zfs_external_acl(zp); 1267fa9e4066Sahrens 12684ccbb6e7Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); 12691412a1a2SMark Shellenbaum if (acl_obj) { 12701412a1a2SMark Shellenbaum VERIFY(!zp->z_is_sa); 1271cdb0ab79Smaybee VERIFY(0 == dmu_object_free(os, acl_obj, tx)); 12721412a1a2SMark Shellenbaum } 1273cdb0ab79Smaybee VERIFY(0 == dmu_object_free(os, obj, tx)); 12744ccbb6e7Sahrens zfs_znode_dmu_fini(zp); 12754ccbb6e7Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); 1276874395d5Smaybee zfs_znode_free(zp); 1277fa9e4066Sahrens } 1278fa9e4066Sahrens 1279fa9e4066Sahrens void 1280fa9e4066Sahrens zfs_zinactive(znode_t *zp) 1281fa9e4066Sahrens { 1282fa9e4066Sahrens vnode_t *vp = ZTOV(zp); 1283fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1284fa9e4066Sahrens uint64_t z_id = zp->z_id; 1285fa9e4066Sahrens 12860a586ceaSMark Shellenbaum ASSERT(zp->z_sa_hdl); 1287fa9e4066Sahrens 1288fa9e4066Sahrens /* 1289fa9e4066Sahrens * Don't allow a zfs_zget() while were trying to release this znode 1290fa9e4066Sahrens */ 1291fa9e4066Sahrens ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id); 1292fa9e4066Sahrens 1293fa9e4066Sahrens mutex_enter(&zp->z_lock); 1294fa9e4066Sahrens mutex_enter(&vp->v_lock); 1295fa9e4066Sahrens vp->v_count--; 1296fa9e4066Sahrens if (vp->v_count > 0 || vn_has_cached_data(vp)) { 1297fa9e4066Sahrens /* 1298fa9e4066Sahrens * If the hold count is greater than zero, somebody has 1299fa9e4066Sahrens * obtained a new reference on this znode while we were 1300fa9e4066Sahrens * processing it here, so we are done. If we still have 1301fa9e4066Sahrens * mapped pages then we are also done, since we don't 1302fa9e4066Sahrens * want to inactivate the znode until the pages get pushed. 1303fa9e4066Sahrens * 1304fa9e4066Sahrens * XXX - if vn_has_cached_data(vp) is true, but count == 0, 1305fa9e4066Sahrens * this seems like it would leave the znode hanging with 1306fa9e4066Sahrens * no chance to go inactive... 1307fa9e4066Sahrens */ 1308fa9e4066Sahrens mutex_exit(&vp->v_lock); 1309fa9e4066Sahrens mutex_exit(&zp->z_lock); 1310fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1311fa9e4066Sahrens return; 1312fa9e4066Sahrens } 1313fa9e4066Sahrens mutex_exit(&vp->v_lock); 1314fa9e4066Sahrens 1315fa9e4066Sahrens /* 1316fa9e4066Sahrens * If this was the last reference to a file with no links, 1317fa9e4066Sahrens * remove the file from the file system. 1318fa9e4066Sahrens */ 1319893a6d32Sahrens if (zp->z_unlinked) { 1320fa9e4066Sahrens mutex_exit(&zp->z_lock); 1321fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1322893a6d32Sahrens zfs_rmnode(zp); 1323fa9e4066Sahrens return; 1324fa9e4066Sahrens } 13250a586ceaSMark Shellenbaum 1326fa9e4066Sahrens mutex_exit(&zp->z_lock); 13274ccbb6e7Sahrens zfs_znode_dmu_fini(zp); 1328fa9e4066Sahrens ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id); 1329874395d5Smaybee zfs_znode_free(zp); 1330fa9e4066Sahrens } 1331fa9e4066Sahrens 1332fa9e4066Sahrens void 1333fa9e4066Sahrens zfs_znode_free(znode_t *zp) 1334fa9e4066Sahrens { 1335fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1336fa9e4066Sahrens 1337874395d5Smaybee vn_invalid(ZTOV(zp)); 1338874395d5Smaybee 1339b5fca8f8Stomee ASSERT(ZTOV(zp)->v_count == 0); 1340b5fca8f8Stomee 1341fa9e4066Sahrens mutex_enter(&zfsvfs->z_znodes_lock); 1342b5fca8f8Stomee POINTER_INVALIDATE(&zp->z_zfsvfs); 1343fa9e4066Sahrens list_remove(&zfsvfs->z_all_znodes, zp); 1344fa9e4066Sahrens mutex_exit(&zfsvfs->z_znodes_lock); 1345fa9e4066Sahrens 1346d47621a4STim Haley if (zp->z_acl_cached) { 1347d47621a4STim Haley zfs_acl_free(zp->z_acl_cached); 1348d47621a4STim Haley zp->z_acl_cached = NULL; 1349d47621a4STim Haley } 1350d47621a4STim Haley 1351fa9e4066Sahrens kmem_cache_free(znode_cache, zp); 1352874395d5Smaybee 1353874395d5Smaybee VFS_RELE(zfsvfs->z_vfs); 1354fa9e4066Sahrens } 1355fa9e4066Sahrens 1356fa9e4066Sahrens void 13570a586ceaSMark Shellenbaum zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2], 13580a586ceaSMark Shellenbaum uint64_t ctime[2], boolean_t have_tx) 1359fa9e4066Sahrens { 1360fa9e4066Sahrens timestruc_t now; 1361fa9e4066Sahrens 1362fa9e4066Sahrens gethrestime(&now); 1363fa9e4066Sahrens 13640a586ceaSMark Shellenbaum if (have_tx) { /* will sa_bulk_update happen really soon? */ 1365fa9e4066Sahrens zp->z_atime_dirty = 0; 1366fa9e4066Sahrens zp->z_seq++; 1367fa9e4066Sahrens } else { 1368fa9e4066Sahrens zp->z_atime_dirty = 1; 1369fa9e4066Sahrens } 1370fa9e4066Sahrens 13710a586ceaSMark Shellenbaum if (flag & AT_ATIME) { 13720a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, zp->z_atime); 13730a586ceaSMark Shellenbaum } 1374fa9e4066Sahrens 1375da6c28aaSamw if (flag & AT_MTIME) { 13760a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, mtime); 13770a586ceaSMark Shellenbaum if (zp->z_zfsvfs->z_use_fuids) { 13780a586ceaSMark Shellenbaum zp->z_pflags |= (ZFS_ARCHIVE | 13790a586ceaSMark Shellenbaum ZFS_AV_MODIFIED); 13800a586ceaSMark Shellenbaum } 1381da6c28aaSamw } 1382fa9e4066Sahrens 1383da6c28aaSamw if (flag & AT_CTIME) { 13840a586ceaSMark Shellenbaum ZFS_TIME_ENCODE(&now, ctime); 1385da6c28aaSamw if (zp->z_zfsvfs->z_use_fuids) 13860a586ceaSMark Shellenbaum zp->z_pflags |= ZFS_ARCHIVE; 1387da6c28aaSamw } 1388fa9e4066Sahrens } 1389fa9e4066Sahrens 1390fa9e4066Sahrens /* 1391104e2ed7Sperrin * Grow the block size for a file. 1392fa9e4066Sahrens * 1393fa9e4066Sahrens * IN: zp - znode of file to free data in. 1394fa9e4066Sahrens * size - requested block size 1395fa9e4066Sahrens * tx - open transaction. 1396fa9e4066Sahrens * 1397fa9e4066Sahrens * NOTE: this function assumes that the znode is write locked. 1398fa9e4066Sahrens */ 1399104e2ed7Sperrin void 1400fa9e4066Sahrens zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx) 1401fa9e4066Sahrens { 1402fa9e4066Sahrens int error; 1403fa9e4066Sahrens u_longlong_t dummy; 1404fa9e4066Sahrens 1405fa9e4066Sahrens if (size <= zp->z_blksz) 1406104e2ed7Sperrin return; 1407fa9e4066Sahrens /* 1408fa9e4066Sahrens * If the file size is already greater than the current blocksize, 1409fa9e4066Sahrens * we will not grow. If there is more than one block in a file, 1410fa9e4066Sahrens * the blocksize cannot change. 1411fa9e4066Sahrens */ 14120a586ceaSMark Shellenbaum if (zp->z_blksz && zp->z_size > zp->z_blksz) 1413104e2ed7Sperrin return; 1414fa9e4066Sahrens 1415fa9e4066Sahrens error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id, 1416fa9e4066Sahrens size, 0, tx); 14170a586ceaSMark Shellenbaum 1418fa9e4066Sahrens if (error == ENOTSUP) 1419104e2ed7Sperrin return; 1420fb09f5aaSMadhav Suresh ASSERT0(error); 1421fa9e4066Sahrens 1422fa9e4066Sahrens /* What blocksize did we actually get? */ 14230a586ceaSMark Shellenbaum dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy); 1424fa9e4066Sahrens } 1425fa9e4066Sahrens 1426fa9e4066Sahrens /* 1427fa9e4066Sahrens * This is a dummy interface used when pvn_vplist_dirty() should *not* 1428fa9e4066Sahrens * be calling back into the fs for a putpage(). E.g.: when truncating 1429fa9e4066Sahrens * a file, the pages being "thrown away* don't need to be written out. 1430fa9e4066Sahrens */ 1431fa9e4066Sahrens /* ARGSUSED */ 1432fa9e4066Sahrens static int 1433fa9e4066Sahrens zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, 1434fa9e4066Sahrens int flags, cred_t *cr) 1435fa9e4066Sahrens { 1436fa9e4066Sahrens ASSERT(0); 1437fa9e4066Sahrens return (0); 1438fa9e4066Sahrens } 1439fa9e4066Sahrens 1440fa9e4066Sahrens /* 1441cdb0ab79Smaybee * Increase the file length 1442fa9e4066Sahrens * 1443fa9e4066Sahrens * IN: zp - znode of file to free data in. 1444cdb0ab79Smaybee * end - new end-of-file 1445fa9e4066Sahrens * 14464bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1447fa9e4066Sahrens */ 1448cdb0ab79Smaybee static int 1449cdb0ab79Smaybee zfs_extend(znode_t *zp, uint64_t end) 1450fa9e4066Sahrens { 14515730cc9aSmaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1452cdb0ab79Smaybee dmu_tx_t *tx; 14535730cc9aSmaybee rl_t *rl; 1454cdb0ab79Smaybee uint64_t newblksz; 1455104e2ed7Sperrin int error; 1456fa9e4066Sahrens 14575730cc9aSmaybee /* 1458cdb0ab79Smaybee * We will change zp_size, lock the whole file. 14595730cc9aSmaybee */ 1460cdb0ab79Smaybee rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); 14615730cc9aSmaybee 1462fa9e4066Sahrens /* 1463fa9e4066Sahrens * Nothing to do if file already at desired length. 1464fa9e4066Sahrens */ 14650a586ceaSMark Shellenbaum if (end <= zp->z_size) { 1466c5c6ffa0Smaybee zfs_range_unlock(rl); 1467fa9e4066Sahrens return (0); 1468fa9e4066Sahrens } 14695730cc9aSmaybee tx = dmu_tx_create(zfsvfs->z_os); 14700a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 14710a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 1472cdb0ab79Smaybee if (end > zp->z_blksz && 14735730cc9aSmaybee (!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) { 1474fa9e4066Sahrens /* 1475fa9e4066Sahrens * We are growing the file past the current block size. 1476fa9e4066Sahrens */ 1477fa9e4066Sahrens if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) { 1478*b5152584SMatthew Ahrens /* 1479*b5152584SMatthew Ahrens * File's blocksize is already larger than the 1480*b5152584SMatthew Ahrens * "recordsize" property. Only let it grow to 1481*b5152584SMatthew Ahrens * the next power of 2. 1482*b5152584SMatthew Ahrens */ 1483fa9e4066Sahrens ASSERT(!ISP2(zp->z_blksz)); 1484*b5152584SMatthew Ahrens newblksz = MIN(end, 1 << highbit64(zp->z_blksz)); 1485fa9e4066Sahrens } else { 1486cdb0ab79Smaybee newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz); 1487fa9e4066Sahrens } 1488cdb0ab79Smaybee dmu_tx_hold_write(tx, zp->z_id, 0, newblksz); 1489cdb0ab79Smaybee } else { 1490cdb0ab79Smaybee newblksz = 0; 14915730cc9aSmaybee } 14925730cc9aSmaybee 1493e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 14945730cc9aSmaybee if (error) { 14955730cc9aSmaybee dmu_tx_abort(tx); 1496c5c6ffa0Smaybee zfs_range_unlock(rl); 14975730cc9aSmaybee return (error); 1498fa9e4066Sahrens } 14995730cc9aSmaybee 1500cdb0ab79Smaybee if (newblksz) 1501cdb0ab79Smaybee zfs_grow_blocksize(zp, newblksz, tx); 15025730cc9aSmaybee 15030a586ceaSMark Shellenbaum zp->z_size = end; 15040a586ceaSMark Shellenbaum 15050a586ceaSMark Shellenbaum VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs), 15060a586ceaSMark Shellenbaum &zp->z_size, sizeof (zp->z_size), tx)); 15075730cc9aSmaybee 1508cdb0ab79Smaybee zfs_range_unlock(rl); 15095730cc9aSmaybee 1510cdb0ab79Smaybee dmu_tx_commit(tx); 15115730cc9aSmaybee 1512cdb0ab79Smaybee return (0); 1513cdb0ab79Smaybee } 1514cdb0ab79Smaybee 1515cdb0ab79Smaybee /* 1516cdb0ab79Smaybee * Free space in a file. 1517cdb0ab79Smaybee * 1518cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1519cdb0ab79Smaybee * off - start of section to free. 1520cdb0ab79Smaybee * len - length of section to free. 1521cdb0ab79Smaybee * 15224bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1523cdb0ab79Smaybee */ 1524cdb0ab79Smaybee static int 1525cdb0ab79Smaybee zfs_free_range(znode_t *zp, uint64_t off, uint64_t len) 1526cdb0ab79Smaybee { 1527cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1528cdb0ab79Smaybee rl_t *rl; 1529cdb0ab79Smaybee int error; 1530cdb0ab79Smaybee 1531cdb0ab79Smaybee /* 1532cdb0ab79Smaybee * Lock the range being freed. 1533cdb0ab79Smaybee */ 1534cdb0ab79Smaybee rl = zfs_range_lock(zp, off, len, RL_WRITER); 1535cdb0ab79Smaybee 1536cdb0ab79Smaybee /* 1537cdb0ab79Smaybee * Nothing to do if file already at desired length. 1538cdb0ab79Smaybee */ 15390a586ceaSMark Shellenbaum if (off >= zp->z_size) { 1540cdb0ab79Smaybee zfs_range_unlock(rl); 1541cdb0ab79Smaybee return (0); 15425730cc9aSmaybee } 15435730cc9aSmaybee 15440a586ceaSMark Shellenbaum if (off + len > zp->z_size) 15450a586ceaSMark Shellenbaum len = zp->z_size - off; 1546cdb0ab79Smaybee 1547cdb0ab79Smaybee error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len); 1548cdb0ab79Smaybee 1549c5c6ffa0Smaybee zfs_range_unlock(rl); 15505730cc9aSmaybee 1551cdb0ab79Smaybee return (error); 1552cdb0ab79Smaybee } 1553cdb0ab79Smaybee 1554cdb0ab79Smaybee /* 1555cdb0ab79Smaybee * Truncate a file 1556cdb0ab79Smaybee * 1557cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1558cdb0ab79Smaybee * end - new end-of-file. 1559cdb0ab79Smaybee * 15604bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1561cdb0ab79Smaybee */ 1562cdb0ab79Smaybee static int 1563cdb0ab79Smaybee zfs_trunc(znode_t *zp, uint64_t end) 1564cdb0ab79Smaybee { 1565cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1566cdb0ab79Smaybee vnode_t *vp = ZTOV(zp); 1567cdb0ab79Smaybee dmu_tx_t *tx; 1568cdb0ab79Smaybee rl_t *rl; 1569cdb0ab79Smaybee int error; 1570fd9ee8b5Sjoyce mcintosh sa_bulk_attr_t bulk[2]; 1571fd9ee8b5Sjoyce mcintosh int count = 0; 1572cdb0ab79Smaybee 1573cdb0ab79Smaybee /* 1574cdb0ab79Smaybee * We will change zp_size, lock the whole file. 1575cdb0ab79Smaybee */ 1576cdb0ab79Smaybee rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER); 1577cdb0ab79Smaybee 1578cdb0ab79Smaybee /* 1579cdb0ab79Smaybee * Nothing to do if file already at desired length. 1580cdb0ab79Smaybee */ 15810a586ceaSMark Shellenbaum if (end >= zp->z_size) { 1582cdb0ab79Smaybee zfs_range_unlock(rl); 1583cdb0ab79Smaybee return (0); 1584cdb0ab79Smaybee } 1585cdb0ab79Smaybee 1586cdb0ab79Smaybee error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end, -1); 1587cdb0ab79Smaybee if (error) { 1588cdb0ab79Smaybee zfs_range_unlock(rl); 1589cdb0ab79Smaybee return (error); 1590cdb0ab79Smaybee } 1591cdb0ab79Smaybee tx = dmu_tx_create(zfsvfs->z_os); 15920a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 15930a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 15944bb73804SMatthew Ahrens dmu_tx_mark_netfree(tx); 1595e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 1596cdb0ab79Smaybee if (error) { 1597cdb0ab79Smaybee dmu_tx_abort(tx); 1598cdb0ab79Smaybee zfs_range_unlock(rl); 1599cdb0ab79Smaybee return (error); 1600cdb0ab79Smaybee } 1601cdb0ab79Smaybee 16020a586ceaSMark Shellenbaum zp->z_size = end; 1603fd9ee8b5Sjoyce mcintosh SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), 1604fd9ee8b5Sjoyce mcintosh NULL, &zp->z_size, sizeof (zp->z_size)); 16050a586ceaSMark Shellenbaum 1606fd9ee8b5Sjoyce mcintosh if (end == 0) { 1607fd9ee8b5Sjoyce mcintosh zp->z_pflags &= ~ZFS_SPARSE; 1608fd9ee8b5Sjoyce mcintosh SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), 1609fd9ee8b5Sjoyce mcintosh NULL, &zp->z_pflags, 8); 1610fd9ee8b5Sjoyce mcintosh } 1611fd9ee8b5Sjoyce mcintosh VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0); 1612cdb0ab79Smaybee 16135730cc9aSmaybee dmu_tx_commit(tx); 16145730cc9aSmaybee 1615fa9e4066Sahrens /* 16165730cc9aSmaybee * Clear any mapped pages in the truncated region. This has to 16175730cc9aSmaybee * happen outside of the transaction to avoid the possibility of 16185730cc9aSmaybee * a deadlock with someone trying to push a page that we are 16195730cc9aSmaybee * about to invalidate. 1620fa9e4066Sahrens */ 1621cdb0ab79Smaybee if (vn_has_cached_data(vp)) { 1622fa9e4066Sahrens page_t *pp; 1623cdb0ab79Smaybee uint64_t start = end & PAGEMASK; 1624cdb0ab79Smaybee int poff = end & PAGEOFFSET; 1625fa9e4066Sahrens 16265730cc9aSmaybee if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) { 1627fa9e4066Sahrens /* 1628fa9e4066Sahrens * We need to zero a partial page. 1629fa9e4066Sahrens */ 16305730cc9aSmaybee pagezero(pp, poff, PAGESIZE - poff); 1631fa9e4066Sahrens start += PAGESIZE; 1632fa9e4066Sahrens page_unlock(pp); 1633fa9e4066Sahrens } 1634fa9e4066Sahrens error = pvn_vplist_dirty(vp, start, zfs_no_putpage, 16355730cc9aSmaybee B_INVAL | B_TRUNC, NULL); 1636fa9e4066Sahrens ASSERT(error == 0); 1637fa9e4066Sahrens } 1638ac05c741SMark Maybee 1639ac05c741SMark Maybee zfs_range_unlock(rl); 1640fa9e4066Sahrens 1641fa9e4066Sahrens return (0); 1642fa9e4066Sahrens } 1643fa9e4066Sahrens 1644cdb0ab79Smaybee /* 1645cdb0ab79Smaybee * Free space in a file 1646cdb0ab79Smaybee * 1647cdb0ab79Smaybee * IN: zp - znode of file to free data in. 1648cdb0ab79Smaybee * off - start of range 1649cdb0ab79Smaybee * len - end of range (0 => EOF) 1650cdb0ab79Smaybee * flag - current file open mode flags. 1651cdb0ab79Smaybee * log - TRUE if this action should be logged 1652cdb0ab79Smaybee * 16534bb73804SMatthew Ahrens * RETURN: 0 on success, error code on failure 1654cdb0ab79Smaybee */ 1655cdb0ab79Smaybee int 1656cdb0ab79Smaybee zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log) 1657cdb0ab79Smaybee { 1658cdb0ab79Smaybee vnode_t *vp = ZTOV(zp); 1659cdb0ab79Smaybee dmu_tx_t *tx; 1660cdb0ab79Smaybee zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1661cdb0ab79Smaybee zilog_t *zilog = zfsvfs->z_log; 16620a586ceaSMark Shellenbaum uint64_t mode; 16630a586ceaSMark Shellenbaum uint64_t mtime[2], ctime[2]; 1664db9986c7SMark Shellenbaum sa_bulk_attr_t bulk[3]; 16650a586ceaSMark Shellenbaum int count = 0; 1666cdb0ab79Smaybee int error; 1667cdb0ab79Smaybee 16680a586ceaSMark Shellenbaum if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &mode, 16690a586ceaSMark Shellenbaum sizeof (mode))) != 0) 16700a586ceaSMark Shellenbaum return (error); 16710a586ceaSMark Shellenbaum 16720a586ceaSMark Shellenbaum if (off > zp->z_size) { 1673cdb0ab79Smaybee error = zfs_extend(zp, off+len); 1674cdb0ab79Smaybee if (error == 0 && log) 1675cdb0ab79Smaybee goto log; 1676cdb0ab79Smaybee else 1677cdb0ab79Smaybee return (error); 1678cdb0ab79Smaybee } 1679cdb0ab79Smaybee 1680cdb0ab79Smaybee /* 1681cdb0ab79Smaybee * Check for any locks in the region to be freed. 1682cdb0ab79Smaybee */ 16830a586ceaSMark Shellenbaum 16840a586ceaSMark Shellenbaum if (MANDLOCK(vp, (mode_t)mode)) { 16850a586ceaSMark Shellenbaum uint64_t length = (len ? len : zp->z_size - off); 1686cdb0ab79Smaybee if (error = chklock(vp, FWRITE, off, length, flag, NULL)) 1687cdb0ab79Smaybee return (error); 1688cdb0ab79Smaybee } 1689cdb0ab79Smaybee 1690cdb0ab79Smaybee if (len == 0) { 1691cdb0ab79Smaybee error = zfs_trunc(zp, off); 1692cdb0ab79Smaybee } else { 1693cdb0ab79Smaybee if ((error = zfs_free_range(zp, off, len)) == 0 && 16940a586ceaSMark Shellenbaum off + len > zp->z_size) 1695cdb0ab79Smaybee error = zfs_extend(zp, off+len); 1696cdb0ab79Smaybee } 1697cdb0ab79Smaybee if (error || !log) 1698cdb0ab79Smaybee return (error); 1699cdb0ab79Smaybee log: 1700cdb0ab79Smaybee tx = dmu_tx_create(zfsvfs->z_os); 17010a586ceaSMark Shellenbaum dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 17020a586ceaSMark Shellenbaum zfs_sa_upgrade_txholds(tx, zp); 1703e722410cSMatthew Ahrens error = dmu_tx_assign(tx, TXG_WAIT); 1704cdb0ab79Smaybee if (error) { 1705cdb0ab79Smaybee dmu_tx_abort(tx); 1706cdb0ab79Smaybee return (error); 1707cdb0ab79Smaybee } 1708cdb0ab79Smaybee 17090a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16); 17100a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16); 1711db9986c7SMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), 1712db9986c7SMark Shellenbaum NULL, &zp->z_pflags, 8); 17130a586ceaSMark Shellenbaum zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE); 17140a586ceaSMark Shellenbaum error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); 17150a586ceaSMark Shellenbaum ASSERT(error == 0); 17160a586ceaSMark Shellenbaum 1717cdb0ab79Smaybee zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len); 1718cdb0ab79Smaybee 1719cdb0ab79Smaybee dmu_tx_commit(tx); 1720cdb0ab79Smaybee return (0); 1721cdb0ab79Smaybee } 1722cdb0ab79Smaybee 1723fa9e4066Sahrens void 1724de8267e0Stimh zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) 1725fa9e4066Sahrens { 1726fa9e4066Sahrens zfsvfs_t zfsvfs; 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; 1734fa9e4066Sahrens vnode_t *vp; 1735fa9e4066Sahrens vattr_t vattr; 17364ccbb6e7Sahrens znode_t *zp; 173789459e17SMark Shellenbaum zfs_acl_ids_t acl_ids; 1738fa9e4066Sahrens 1739fa9e4066Sahrens /* 1740fa9e4066Sahrens * First attempt to create master node. 1741fa9e4066Sahrens */ 1742ea8dc4b6Seschrock /* 1743ea8dc4b6Seschrock * In an empty objset, there are no blocks to read and thus 1744ea8dc4b6Seschrock * there can be no i/o errors (which we assert below). 1745ea8dc4b6Seschrock */ 1746fa9e4066Sahrens moid = MASTER_NODE_OBJ; 1747fa9e4066Sahrens error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE, 1748fa9e4066Sahrens DMU_OT_NONE, 0, tx); 1749fa9e4066Sahrens ASSERT(error == 0); 1750fa9e4066Sahrens 1751fa9e4066Sahrens /* 1752fa9e4066Sahrens * Set starting attributes. 1753fa9e4066Sahrens */ 17540a586ceaSMark Shellenbaum version = zfs_zpl_version_map(spa_version(dmu_objset_spa(os))); 1755de8267e0Stimh elem = NULL; 1756de8267e0Stimh while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) { 1757de8267e0Stimh /* For the moment we expect all zpl props to be uint64_ts */ 1758de8267e0Stimh uint64_t val; 1759de8267e0Stimh char *name; 1760de8267e0Stimh 1761de8267e0Stimh ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64); 1762b3d911cbStimh VERIFY(nvpair_value_uint64(elem, &val) == 0); 1763de8267e0Stimh name = nvpair_name(elem); 1764de8267e0Stimh if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) { 176514843421SMatthew Ahrens if (val < version) 176614843421SMatthew Ahrens version = val; 1767de8267e0Stimh } else { 1768de8267e0Stimh error = zap_update(os, moid, name, 8, 1, &val, tx); 1769de8267e0Stimh } 1770de8267e0Stimh ASSERT(error == 0); 1771de8267e0Stimh if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0) 1772de8267e0Stimh norm = val; 1773de8267e0Stimh else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0) 1774de8267e0Stimh sense = val; 1775de8267e0Stimh } 1776de8267e0Stimh ASSERT(version != 0); 177714843421SMatthew Ahrens error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx); 1778fa9e4066Sahrens 17790a586ceaSMark Shellenbaum /* 17800a586ceaSMark Shellenbaum * Create zap object used for SA attribute registration 17810a586ceaSMark Shellenbaum */ 17820a586ceaSMark Shellenbaum 17830a586ceaSMark Shellenbaum if (version >= ZPL_VERSION_SA) { 17840a586ceaSMark Shellenbaum sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE, 17850a586ceaSMark Shellenbaum DMU_OT_NONE, 0, tx); 17860a586ceaSMark Shellenbaum error = zap_add(os, moid, ZFS_SA_ATTRS, 8, 1, &sa_obj, tx); 17870a586ceaSMark Shellenbaum ASSERT(error == 0); 17880a586ceaSMark Shellenbaum } else { 17890a586ceaSMark Shellenbaum sa_obj = 0; 17900a586ceaSMark Shellenbaum } 1791fa9e4066Sahrens /* 1792fa9e4066Sahrens * Create a delete queue. 1793fa9e4066Sahrens */ 179414843421SMatthew Ahrens obj = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx); 1795fa9e4066Sahrens 179614843421SMatthew Ahrens error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx); 1797fa9e4066Sahrens ASSERT(error == 0); 1798fa9e4066Sahrens 1799fa9e4066Sahrens /* 1800fa9e4066Sahrens * Create root znode. Create minimal znode/vnode/zfsvfs 1801fa9e4066Sahrens * to allow zfs_mknode to work. 1802fa9e4066Sahrens */ 1803fa9e4066Sahrens vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE; 1804fa9e4066Sahrens vattr.va_type = VDIR; 1805fa9e4066Sahrens vattr.va_mode = S_IFDIR|0755; 1806ecd6cf80Smarks vattr.va_uid = crgetuid(cr); 1807ecd6cf80Smarks vattr.va_gid = crgetgid(cr); 1808fa9e4066Sahrens 1809fa9e4066Sahrens rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP); 1810744947dcSTom Erickson ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); 1811744947dcSTom Erickson rootzp->z_moved = 0; 1812893a6d32Sahrens rootzp->z_unlinked = 0; 1813fa9e4066Sahrens rootzp->z_atime_dirty = 0; 18140a586ceaSMark Shellenbaum rootzp->z_is_sa = USE_SA(version, os); 1815fa9e4066Sahrens 1816fa9e4066Sahrens vp = ZTOV(rootzp); 1817fa9e4066Sahrens vn_reinit(vp); 1818fa9e4066Sahrens vp->v_type = VDIR; 1819fa9e4066Sahrens 1820fa9e4066Sahrens bzero(&zfsvfs, sizeof (zfsvfs_t)); 1821fa9e4066Sahrens 1822fa9e4066Sahrens zfsvfs.z_os = os; 1823fa9e4066Sahrens zfsvfs.z_parent = &zfsvfs; 1824da6c28aaSamw zfsvfs.z_version = version; 1825da6c28aaSamw zfsvfs.z_use_fuids = USE_FUIDS(version, os); 18260a586ceaSMark Shellenbaum zfsvfs.z_use_sa = USE_SA(version, os); 1827da6c28aaSamw zfsvfs.z_norm = norm; 18280a586ceaSMark Shellenbaum 18291d8ccc7bSMark Shellenbaum error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END, 18301d8ccc7bSMark Shellenbaum &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) 1839de8267e0Stimh zfsvfs.z_norm |= U8_TEXTPREP_TOUPPER; 1840fa9e4066Sahrens 1841fa9e4066Sahrens mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL); 1842fa9e4066Sahrens 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++) 184659e7834dSMark Shellenbaum mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); 184759e7834dSMark Shellenbaum 1848b5fca8f8Stomee 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 1867743a77edSAlan Wright 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++) 187259e7834dSMark Shellenbaum mutex_destroy(&zfsvfs.z_hold_mtx[i]); 1873fa9e4066Sahrens } 187455434c77Sek 1875da6c28aaSamw #endif /* _KERNEL */ 18760a586ceaSMark Shellenbaum 187755434c77Sek static int 187899d5e173STim Haley zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table) 187999d5e173STim Haley { 188099d5e173STim Haley uint64_t sa_obj = 0; 188199d5e173STim Haley int error; 188299d5e173STim Haley 188399d5e173STim Haley error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj); 188499d5e173STim Haley if (error != 0 && error != ENOENT) 188599d5e173STim Haley return (error); 188699d5e173STim Haley 188799d5e173STim Haley error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table); 188899d5e173STim Haley return (error); 188999d5e173STim Haley } 189099d5e173STim Haley 189199d5e173STim Haley static int 189299d5e173STim Haley zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp, 1893163eb7ffSTim Haley dmu_buf_t **db, void *tag) 189455434c77Sek { 189555434c77Sek dmu_object_info_t doi; 189655434c77Sek int error; 18970a586ceaSMark Shellenbaum 1898163eb7ffSTim Haley if ((error = sa_buf_hold(osp, obj, tag, db)) != 0) 189955434c77Sek return (error); 190055434c77Sek 190199d5e173STim Haley dmu_object_info_from_db(*db, &doi); 19020a586ceaSMark Shellenbaum if ((doi.doi_bonus_type != DMU_OT_SA && 19030a586ceaSMark Shellenbaum doi.doi_bonus_type != DMU_OT_ZNODE) || 19040a586ceaSMark Shellenbaum doi.doi_bonus_type == DMU_OT_ZNODE && 190555434c77Sek doi.doi_bonus_size < sizeof (znode_phys_t)) { 1906163eb7ffSTim Haley sa_buf_rele(*db, tag); 1907be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 190855434c77Sek } 190955434c77Sek 191099d5e173STim Haley error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp); 191199d5e173STim Haley if (error != 0) { 1912163eb7ffSTim Haley sa_buf_rele(*db, tag); 19130a586ceaSMark Shellenbaum return (error); 19140a586ceaSMark Shellenbaum } 19150a586ceaSMark Shellenbaum 191699d5e173STim Haley return (0); 191799d5e173STim Haley } 191899d5e173STim Haley 191999d5e173STim Haley void 1920163eb7ffSTim Haley zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, void *tag) 192199d5e173STim Haley { 192299d5e173STim Haley sa_handle_destroy(hdl); 1923163eb7ffSTim Haley sa_buf_rele(db, tag); 192499d5e173STim Haley } 192599d5e173STim Haley 192699d5e173STim Haley /* 192799d5e173STim Haley * Given an object number, return its parent object number and whether 192899d5e173STim Haley * or not the object is an extended attribute directory. 192999d5e173STim Haley */ 193099d5e173STim Haley static int 19311ce39b5fSJeremy Jones zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table, 19321ce39b5fSJeremy Jones uint64_t *pobjp, int *is_xattrdir) 193399d5e173STim Haley { 193499d5e173STim Haley uint64_t parent; 193599d5e173STim Haley uint64_t pflags; 193699d5e173STim Haley uint64_t mode; 19371ce39b5fSJeremy Jones uint64_t parent_mode; 193899d5e173STim Haley sa_bulk_attr_t bulk[3]; 19391ce39b5fSJeremy Jones sa_handle_t *sa_hdl; 19401ce39b5fSJeremy Jones dmu_buf_t *sa_db; 194199d5e173STim Haley int count = 0; 194299d5e173STim Haley int error; 194399d5e173STim Haley 194499d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL, 194599d5e173STim Haley &parent, sizeof (parent)); 19460a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL, 194799d5e173STim Haley &pflags, sizeof (pflags)); 19480a586ceaSMark Shellenbaum SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL, 194999d5e173STim Haley &mode, sizeof (mode)); 19500a586ceaSMark Shellenbaum 195199d5e173STim Haley if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0) 19520a586ceaSMark Shellenbaum return (error); 195399d5e173STim Haley 19541ce39b5fSJeremy Jones /* 19551ce39b5fSJeremy Jones * When a link is removed its parent pointer is not changed and will 19561ce39b5fSJeremy Jones * be invalid. There are two cases where a link is removed but the 19571ce39b5fSJeremy Jones * file stays around, when it goes to the delete queue and when there 19581ce39b5fSJeremy Jones * are additional links. 19591ce39b5fSJeremy Jones */ 19601ce39b5fSJeremy Jones error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG); 19611ce39b5fSJeremy Jones if (error != 0) 19621ce39b5fSJeremy Jones return (error); 19631ce39b5fSJeremy Jones 19641ce39b5fSJeremy Jones error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode)); 19651ce39b5fSJeremy Jones zfs_release_sa_handle(sa_hdl, sa_db, FTAG); 19661ce39b5fSJeremy Jones if (error != 0) 19671ce39b5fSJeremy Jones return (error); 19681ce39b5fSJeremy Jones 19690a586ceaSMark Shellenbaum *is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode); 197055434c77Sek 19711ce39b5fSJeremy Jones /* 19721ce39b5fSJeremy Jones * Extended attributes can be applied to files, directories, etc. 19731ce39b5fSJeremy Jones * Otherwise the parent must be a directory. 19741ce39b5fSJeremy Jones */ 19751ce39b5fSJeremy Jones if (!*is_xattrdir && !S_ISDIR(parent_mode)) 1976be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL)); 19771ce39b5fSJeremy Jones 19781ce39b5fSJeremy Jones *pobjp = parent; 19791ce39b5fSJeremy Jones 198055434c77Sek return (0); 198155434c77Sek } 198255434c77Sek 198399d5e173STim Haley /* 198499d5e173STim Haley * Given an object number, return some zpl level statistics 198599d5e173STim Haley */ 198699d5e173STim Haley static int 198799d5e173STim Haley zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table, 198899d5e173STim Haley zfs_stat_t *sb) 198955434c77Sek { 199099d5e173STim Haley sa_bulk_attr_t bulk[4]; 199199d5e173STim Haley int count = 0; 199299d5e173STim Haley 199399d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL, 199499d5e173STim Haley &sb->zs_mode, sizeof (sb->zs_mode)); 199599d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL, 199699d5e173STim Haley &sb->zs_gen, sizeof (sb->zs_gen)); 199799d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL, 199899d5e173STim Haley &sb->zs_links, sizeof (sb->zs_links)); 199999d5e173STim Haley SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL, 200099d5e173STim Haley &sb->zs_ctime, sizeof (sb->zs_ctime)); 200199d5e173STim Haley 200299d5e173STim Haley return (sa_bulk_lookup(hdl, bulk, count)); 200399d5e173STim Haley } 200499d5e173STim Haley 200599d5e173STim Haley static int 200699d5e173STim Haley zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl, 200799d5e173STim Haley sa_attr_type_t *sa_table, char *buf, int len) 200899d5e173STim Haley { 200999d5e173STim Haley sa_handle_t *sa_hdl; 201099d5e173STim Haley sa_handle_t *prevhdl = NULL; 201199d5e173STim Haley dmu_buf_t *prevdb = NULL; 201299d5e173STim Haley dmu_buf_t *sa_db = NULL; 201355434c77Sek char *path = buf + len - 1; 201455434c77Sek int error; 201555434c77Sek 201655434c77Sek *path = '\0'; 201799d5e173STim Haley sa_hdl = hdl; 20180a586ceaSMark Shellenbaum 201955434c77Sek for (;;) { 202055434c77Sek uint64_t pobj; 202155434c77Sek char component[MAXNAMELEN + 2]; 202255434c77Sek size_t complen; 202355434c77Sek int is_xattrdir; 202455434c77Sek 202599d5e173STim Haley if (prevdb) 2026163eb7ffSTim Haley zfs_release_sa_handle(prevhdl, prevdb, FTAG); 202799d5e173STim Haley 20281ce39b5fSJeremy Jones if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj, 202999d5e173STim Haley &is_xattrdir)) != 0) 203055434c77Sek break; 203155434c77Sek 203255434c77Sek if (pobj == obj) { 203355434c77Sek if (path[0] != '/') 203455434c77Sek *--path = '/'; 203555434c77Sek break; 203655434c77Sek } 203755434c77Sek 203855434c77Sek component[0] = '/'; 203955434c77Sek if (is_xattrdir) { 204055434c77Sek (void) sprintf(component + 1, "<xattrdir>"); 204155434c77Sek } else { 2042e7437265Sahrens error = zap_value_search(osp, pobj, obj, 2043e7437265Sahrens ZFS_DIRENT_OBJ(-1ULL), component + 1); 204455434c77Sek if (error != 0) 204555434c77Sek break; 204655434c77Sek } 204755434c77Sek 204855434c77Sek complen = strlen(component); 204955434c77Sek path -= complen; 205055434c77Sek ASSERT(path >= buf); 205155434c77Sek bcopy(component, path, complen); 205255434c77Sek obj = pobj; 205399d5e173STim Haley 205499d5e173STim Haley if (sa_hdl != hdl) { 205599d5e173STim Haley prevhdl = sa_hdl; 205699d5e173STim Haley prevdb = sa_db; 205799d5e173STim Haley } 2058163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG); 205999d5e173STim Haley if (error != 0) { 206099d5e173STim Haley sa_hdl = prevhdl; 206199d5e173STim Haley sa_db = prevdb; 206299d5e173STim Haley break; 206399d5e173STim Haley } 206499d5e173STim Haley } 206599d5e173STim Haley 206699d5e173STim Haley if (sa_hdl != NULL && sa_hdl != hdl) { 206799d5e173STim Haley ASSERT(sa_db != NULL); 2068163eb7ffSTim Haley zfs_release_sa_handle(sa_hdl, sa_db, FTAG); 206955434c77Sek } 207055434c77Sek 207155434c77Sek if (error == 0) 207255434c77Sek (void) memmove(buf, path, buf + len - path); 20730a586ceaSMark Shellenbaum 207455434c77Sek return (error); 207555434c77Sek } 207699d5e173STim Haley 207799d5e173STim Haley int 207899d5e173STim Haley zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len) 207999d5e173STim Haley { 208099d5e173STim Haley sa_attr_type_t *sa_table; 208199d5e173STim Haley sa_handle_t *hdl; 208299d5e173STim Haley dmu_buf_t *db; 208399d5e173STim Haley int error; 208499d5e173STim Haley 208599d5e173STim Haley error = zfs_sa_setup(osp, &sa_table); 208699d5e173STim Haley if (error != 0) 208799d5e173STim Haley return (error); 208899d5e173STim Haley 2089163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG); 209099d5e173STim Haley if (error != 0) 209199d5e173STim Haley return (error); 209299d5e173STim Haley 209399d5e173STim Haley error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len); 209499d5e173STim Haley 2095163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 209699d5e173STim Haley return (error); 209799d5e173STim Haley } 209899d5e173STim Haley 209999d5e173STim Haley int 210099d5e173STim Haley zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb, 210199d5e173STim Haley char *buf, int len) 210299d5e173STim Haley { 210399d5e173STim Haley char *path = buf + len - 1; 210499d5e173STim Haley sa_attr_type_t *sa_table; 210599d5e173STim Haley sa_handle_t *hdl; 210699d5e173STim Haley dmu_buf_t *db; 210799d5e173STim Haley int error; 210899d5e173STim Haley 210999d5e173STim Haley *path = '\0'; 211099d5e173STim Haley 211199d5e173STim Haley error = zfs_sa_setup(osp, &sa_table); 211299d5e173STim Haley if (error != 0) 211399d5e173STim Haley return (error); 211499d5e173STim Haley 2115163eb7ffSTim Haley error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG); 211699d5e173STim Haley if (error != 0) 211799d5e173STim Haley return (error); 211899d5e173STim Haley 211999d5e173STim Haley error = zfs_obj_to_stats_impl(hdl, sa_table, sb); 212099d5e173STim Haley if (error != 0) { 2121163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 212299d5e173STim Haley return (error); 212399d5e173STim Haley } 212499d5e173STim Haley 212599d5e173STim Haley error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len); 212699d5e173STim Haley 2127163eb7ffSTim Haley zfs_release_sa_handle(hdl, db, FTAG); 212899d5e173STim Haley return (error); 212999d5e173STim Haley } 2130