zfs_vnops.c revision 195785
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22185029Spjd * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26169195Spjd/* Portions Copyright 2007 Jeremy Teo */ 27169195Spjd 28168404Spjd#include <sys/types.h> 29168404Spjd#include <sys/param.h> 30168404Spjd#include <sys/time.h> 31168404Spjd#include <sys/systm.h> 32168404Spjd#include <sys/sysmacros.h> 33168404Spjd#include <sys/resource.h> 34168404Spjd#include <sys/vfs.h> 35168404Spjd#include <sys/vnode.h> 36168404Spjd#include <sys/file.h> 37168404Spjd#include <sys/stat.h> 38168404Spjd#include <sys/kmem.h> 39168404Spjd#include <sys/taskq.h> 40168404Spjd#include <sys/uio.h> 41168404Spjd#include <sys/atomic.h> 42168404Spjd#include <sys/namei.h> 43168404Spjd#include <sys/mman.h> 44168404Spjd#include <sys/cmn_err.h> 45168404Spjd#include <sys/errno.h> 46168404Spjd#include <sys/unistd.h> 47168404Spjd#include <sys/zfs_dir.h> 48168404Spjd#include <sys/zfs_ioctl.h> 49168404Spjd#include <sys/fs/zfs.h> 50168404Spjd#include <sys/dmu.h> 51168404Spjd#include <sys/spa.h> 52168404Spjd#include <sys/txg.h> 53168404Spjd#include <sys/dbuf.h> 54168404Spjd#include <sys/zap.h> 55168404Spjd#include <sys/dirent.h> 56168962Spjd#include <sys/policy.h> 57168962Spjd#include <sys/sunddi.h> 58168404Spjd#include <sys/filio.h> 59168404Spjd#include <sys/zfs_ctldir.h> 60185029Spjd#include <sys/zfs_fuid.h> 61168404Spjd#include <sys/dnlc.h> 62168404Spjd#include <sys/zfs_rlock.h> 63185029Spjd#include <sys/extdirent.h> 64185029Spjd#include <sys/kidmap.h> 65168404Spjd#include <sys/bio.h> 66168404Spjd#include <sys/buf.h> 67168404Spjd#include <sys/sf_buf.h> 68168404Spjd#include <sys/sched.h> 69192800Strasz#include <sys/acl.h> 70168404Spjd 71168404Spjd/* 72168404Spjd * Programming rules. 73168404Spjd * 74168404Spjd * Each vnode op performs some logical unit of work. To do this, the ZPL must 75168404Spjd * properly lock its in-core state, create a DMU transaction, do the work, 76168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction, 77185029Spjd * and wait for the intent log to commit if it is a synchronous operation. 78185029Spjd * Moreover, the vnode ops must work in both normal and log replay context. 79168404Spjd * The ordering of events is important to avoid deadlocks and references 80168404Spjd * to freed memory. The example below illustrates the following Big Rules: 81168404Spjd * 82168404Spjd * (1) A check must be made in each zfs thread for a mounted file system. 83168404Spjd * This is done avoiding races using ZFS_ENTER(zfsvfs). 84185029Spjd * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes 85185029Spjd * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros 86185029Spjd * can return EIO from the calling function. 87168404Spjd * 88168404Spjd * (2) VN_RELE() should always be the last thing except for zil_commit() 89168404Spjd * (if necessary) and ZFS_EXIT(). This is for 3 reasons: 90168404Spjd * First, if it's the last reference, the vnode/znode 91168404Spjd * can be freed, so the zp may point to freed memory. Second, the last 92168404Spjd * reference will call zfs_zinactive(), which may induce a lot of work -- 93168404Spjd * pushing cached pages (which acquires range locks) and syncing out 94168404Spjd * cached atime changes. Third, zfs_zinactive() may require a new tx, 95168404Spjd * which could deadlock the system if you were already holding one. 96191900Skmacy * If you must call VN_RELE() within a tx then use VN_RELE_ASYNC(). 97168404Spjd * 98168404Spjd * (3) All range locks must be grabbed before calling dmu_tx_assign(), 99168404Spjd * as they can span dmu_tx_assign() calls. 100168404Spjd * 101168404Spjd * (4) Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign(). 102168404Spjd * In normal operation, this will be TXG_NOWAIT. During ZIL replay, 103168404Spjd * it will be a specific txg. Either way, dmu_tx_assign() never blocks. 104168404Spjd * This is critical because we don't want to block while holding locks. 105168404Spjd * Note, in particular, that if a lock is sometimes acquired before 106168404Spjd * the tx assigns, and sometimes after (e.g. z_lock), then failing to 107168404Spjd * use a non-blocking assign can deadlock the system. The scenario: 108168404Spjd * 109168404Spjd * Thread A has grabbed a lock before calling dmu_tx_assign(). 110168404Spjd * Thread B is in an already-assigned tx, and blocks for this lock. 111168404Spjd * Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open() 112168404Spjd * forever, because the previous txg can't quiesce until B's tx commits. 113168404Spjd * 114168404Spjd * If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT, 115168404Spjd * then drop all locks, call dmu_tx_wait(), and try again. 116168404Spjd * 117168404Spjd * (5) If the operation succeeded, generate the intent log entry for it 118168404Spjd * before dropping locks. This ensures that the ordering of events 119168404Spjd * in the intent log matches the order in which they actually occurred. 120168404Spjd * 121168404Spjd * (6) At the end of each vnode op, the DMU tx must always commit, 122168404Spjd * regardless of whether there were any errors. 123168404Spjd * 124168404Spjd * (7) After dropping all locks, invoke zil_commit(zilog, seq, foid) 125168404Spjd * to ensure that synchronous semantics are provided when necessary. 126168404Spjd * 127168404Spjd * In general, this is how things should be ordered in each vnode op: 128168404Spjd * 129168404Spjd * ZFS_ENTER(zfsvfs); // exit if unmounted 130168404Spjd * top: 131168404Spjd * zfs_dirent_lock(&dl, ...) // lock directory entry (may VN_HOLD()) 132168404Spjd * rw_enter(...); // grab any other locks you need 133168404Spjd * tx = dmu_tx_create(...); // get DMU tx 134168404Spjd * dmu_tx_hold_*(); // hold each object you might modify 135168404Spjd * error = dmu_tx_assign(tx, zfsvfs->z_assign); // try to assign 136168404Spjd * if (error) { 137168404Spjd * rw_exit(...); // drop locks 138168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 139168404Spjd * VN_RELE(...); // release held vnodes 140168404Spjd * if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 141168404Spjd * dmu_tx_wait(tx); 142168404Spjd * dmu_tx_abort(tx); 143168404Spjd * goto top; 144168404Spjd * } 145168404Spjd * dmu_tx_abort(tx); // abort DMU tx 146168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 147168404Spjd * return (error); // really out of space 148168404Spjd * } 149168404Spjd * error = do_real_work(); // do whatever this VOP does 150168404Spjd * if (error == 0) 151168404Spjd * zfs_log_*(...); // on success, make ZIL entry 152168404Spjd * dmu_tx_commit(tx); // commit DMU tx -- error or not 153168404Spjd * rw_exit(...); // drop locks 154168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 155168404Spjd * VN_RELE(...); // release held vnodes 156168404Spjd * zil_commit(zilog, seq, foid); // synchronous when necessary 157168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 158168404Spjd * return (error); // done, report error 159168404Spjd */ 160185029Spjd 161168404Spjd/* ARGSUSED */ 162168404Spjdstatic int 163185029Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 164168404Spjd{ 165168962Spjd znode_t *zp = VTOZ(*vpp); 166168404Spjd 167185029Spjd if ((flag & FWRITE) && (zp->z_phys->zp_flags & ZFS_APPENDONLY) && 168185029Spjd ((flag & FAPPEND) == 0)) { 169185029Spjd return (EPERM); 170185029Spjd } 171185029Spjd 172185029Spjd if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan && 173185029Spjd ZTOV(zp)->v_type == VREG && 174185029Spjd !(zp->z_phys->zp_flags & ZFS_AV_QUARANTINED) && 175185029Spjd zp->z_phys->zp_size > 0) 176185029Spjd if (fs_vscan(*vpp, cr, 0) != 0) 177185029Spjd return (EACCES); 178185029Spjd 179168404Spjd /* Keep a count of the synchronous opens in the znode */ 180168962Spjd if (flag & (FSYNC | FDSYNC)) 181168404Spjd atomic_inc_32(&zp->z_sync_cnt); 182185029Spjd 183168404Spjd return (0); 184168404Spjd} 185168404Spjd 186168404Spjd/* ARGSUSED */ 187168404Spjdstatic int 188185029Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr, 189185029Spjd caller_context_t *ct) 190168404Spjd{ 191168962Spjd znode_t *zp = VTOZ(vp); 192168404Spjd 193168404Spjd /* Decrement the synchronous opens in the znode */ 194185029Spjd if ((flag & (FSYNC | FDSYNC)) && (count == 1)) 195168404Spjd atomic_dec_32(&zp->z_sync_cnt); 196168404Spjd 197168962Spjd /* 198168962Spjd * Clean up any locks held by this process on the vp. 199168962Spjd */ 200168962Spjd cleanlocks(vp, ddi_get_pid(), 0); 201168962Spjd cleanshares(vp, ddi_get_pid()); 202168962Spjd 203185029Spjd if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan && 204185029Spjd ZTOV(zp)->v_type == VREG && 205185029Spjd !(zp->z_phys->zp_flags & ZFS_AV_QUARANTINED) && 206185029Spjd zp->z_phys->zp_size > 0) 207185029Spjd VERIFY(fs_vscan(vp, cr, 1) == 0); 208185029Spjd 209168404Spjd return (0); 210168404Spjd} 211168404Spjd 212168404Spjd/* 213168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and 214168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. 215168404Spjd */ 216168404Spjdstatic int 217168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off) 218168404Spjd{ 219168404Spjd znode_t *zp = VTOZ(vp); 220168404Spjd uint64_t noff = (uint64_t)*off; /* new offset */ 221168404Spjd uint64_t file_sz; 222168404Spjd int error; 223168404Spjd boolean_t hole; 224168404Spjd 225168404Spjd file_sz = zp->z_phys->zp_size; 226168404Spjd if (noff >= file_sz) { 227168404Spjd return (ENXIO); 228168404Spjd } 229168404Spjd 230168962Spjd if (cmd == _FIO_SEEK_HOLE) 231168404Spjd hole = B_TRUE; 232168404Spjd else 233168404Spjd hole = B_FALSE; 234168404Spjd 235168404Spjd error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); 236168404Spjd 237168404Spjd /* end of file? */ 238168404Spjd if ((error == ESRCH) || (noff > file_sz)) { 239168404Spjd /* 240168404Spjd * Handle the virtual hole at the end of file. 241168404Spjd */ 242168404Spjd if (hole) { 243168404Spjd *off = file_sz; 244168404Spjd return (0); 245168404Spjd } 246168404Spjd return (ENXIO); 247168404Spjd } 248168404Spjd 249168404Spjd if (noff < *off) 250168404Spjd return (error); 251168404Spjd *off = noff; 252168404Spjd return (error); 253168404Spjd} 254168404Spjd 255168404Spjd/* ARGSUSED */ 256168404Spjdstatic int 257168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred, 258185029Spjd int *rvalp, caller_context_t *ct) 259168404Spjd{ 260168962Spjd offset_t off; 261168962Spjd int error; 262168962Spjd zfsvfs_t *zfsvfs; 263185029Spjd znode_t *zp; 264168404Spjd 265168404Spjd switch (com) { 266185029Spjd case _FIOFFS: 267168962Spjd return (0); 268168404Spjd 269168962Spjd /* 270168962Spjd * The following two ioctls are used by bfu. Faking out, 271168962Spjd * necessary to avoid bfu errors. 272168962Spjd */ 273185029Spjd case _FIOGDIO: 274185029Spjd case _FIOSDIO: 275168962Spjd return (0); 276168962Spjd 277185029Spjd case _FIO_SEEK_DATA: 278185029Spjd case _FIO_SEEK_HOLE: 279168962Spjd if (ddi_copyin((void *)data, &off, sizeof (off), flag)) 280168962Spjd return (EFAULT); 281168962Spjd 282185029Spjd zp = VTOZ(vp); 283185029Spjd zfsvfs = zp->z_zfsvfs; 284168404Spjd ZFS_ENTER(zfsvfs); 285185029Spjd ZFS_VERIFY_ZP(zp); 286168404Spjd 287168404Spjd /* offset parameter is in/out */ 288168404Spjd error = zfs_holey(vp, com, &off); 289168404Spjd ZFS_EXIT(zfsvfs); 290168404Spjd if (error) 291168404Spjd return (error); 292168962Spjd if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) 293168962Spjd return (EFAULT); 294168404Spjd return (0); 295168404Spjd } 296168404Spjd return (ENOTTY); 297168404Spjd} 298168404Spjd 299168404Spjd/* 300168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 301168404Spjd * between the DMU cache and the memory mapped pages. What this means: 302168404Spjd * 303168404Spjd * On Write: If we find a memory mapped page, we write to *both* 304168404Spjd * the page and the dmu buffer. 305168404Spjd * 306168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 307168404Spjd * the file is memory mapped. 308168404Spjd */ 309168404Spjdstatic int 310168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) 311168404Spjd{ 312168404Spjd znode_t *zp = VTOZ(vp); 313168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 314168404Spjd vm_object_t obj; 315168404Spjd vm_page_t m; 316168404Spjd struct sf_buf *sf; 317168404Spjd int64_t start, off; 318168404Spjd int len = nbytes; 319168404Spjd int error = 0; 320169059Spjd uint64_t dirbytes; 321168404Spjd 322168404Spjd ASSERT(vp->v_mount != NULL); 323168404Spjd obj = vp->v_object; 324168404Spjd ASSERT(obj != NULL); 325168404Spjd 326168404Spjd start = uio->uio_loffset; 327168404Spjd off = start & PAGEOFFSET; 328169059Spjd dirbytes = 0; 329168404Spjd VM_OBJECT_LOCK(obj); 330168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 331168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 332169059Spjd uint64_t fsize; 333168404Spjd 334168404Spjdagain: 335168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 336168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 337169059Spjd uint64_t woff; 338168404Spjd caddr_t va; 339168404Spjd 340168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) 341168404Spjd goto again; 342169059Spjd fsize = obj->un_pager.vnp.vnp_size; 343168404Spjd vm_page_busy(m); 344169057Spjd vm_page_lock_queues(); 345169057Spjd vm_page_undirty(m); 346169057Spjd vm_page_unlock_queues(); 347168404Spjd VM_OBJECT_UNLOCK(obj); 348169059Spjd if (dirbytes > 0) { 349169059Spjd error = dmu_write_uio(os, zp->z_id, uio, 350169059Spjd dirbytes, tx); 351169059Spjd dirbytes = 0; 352169059Spjd } 353169059Spjd if (error == 0) { 354169059Spjd sched_pin(); 355169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 356169059Spjd va = (caddr_t)sf_buf_kva(sf); 357169059Spjd woff = uio->uio_loffset - off; 358169059Spjd error = uiomove(va + off, bytes, UIO_WRITE, uio); 359169167Spjd /* 360169167Spjd * The uiomove() above could have been partially 361169167Spjd * successful, that's why we call dmu_write() 362169167Spjd * below unconditionally. The page was marked 363169167Spjd * non-dirty above and we would lose the changes 364169167Spjd * without doing so. If the uiomove() failed 365169167Spjd * entirely, well, we just write what we got 366169167Spjd * before one more time. 367169167Spjd */ 368169059Spjd dmu_write(os, zp->z_id, woff, 369169059Spjd MIN(PAGESIZE, fsize - woff), va, tx); 370169059Spjd sf_buf_free(sf); 371169059Spjd sched_unpin(); 372169059Spjd } 373168404Spjd VM_OBJECT_LOCK(obj); 374168404Spjd vm_page_wakeup(m); 375168404Spjd } else { 376177230Spjd if (__predict_false(obj->cache != NULL)) { 377177230Spjd vm_page_cache_free(obj, OFF_TO_IDX(start), 378177230Spjd OFF_TO_IDX(start) + 1); 379177230Spjd } 380169059Spjd dirbytes += bytes; 381168404Spjd } 382168404Spjd len -= bytes; 383168404Spjd off = 0; 384168404Spjd if (error) 385168404Spjd break; 386168404Spjd } 387168404Spjd VM_OBJECT_UNLOCK(obj); 388169059Spjd if (error == 0 && dirbytes > 0) 389169059Spjd error = dmu_write_uio(os, zp->z_id, uio, dirbytes, tx); 390168404Spjd return (error); 391168404Spjd} 392168404Spjd 393168404Spjd/* 394168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 395168404Spjd * between the DMU cache and the memory mapped pages. What this means: 396168404Spjd * 397168404Spjd * On Read: We "read" preferentially from memory mapped pages, 398168404Spjd * else we default from the dmu buffer. 399168404Spjd * 400168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 401168404Spjd * the file is memory mapped. 402168404Spjd */ 403168404Spjdstatic int 404168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio) 405168404Spjd{ 406168404Spjd znode_t *zp = VTOZ(vp); 407168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 408168404Spjd vm_object_t obj; 409168404Spjd vm_page_t m; 410168404Spjd struct sf_buf *sf; 411168404Spjd int64_t start, off; 412168926Spjd caddr_t va; 413168404Spjd int len = nbytes; 414168404Spjd int error = 0; 415169059Spjd uint64_t dirbytes; 416168404Spjd 417168404Spjd ASSERT(vp->v_mount != NULL); 418168404Spjd obj = vp->v_object; 419168404Spjd ASSERT(obj != NULL); 420168404Spjd 421168404Spjd start = uio->uio_loffset; 422168404Spjd off = start & PAGEOFFSET; 423169059Spjd dirbytes = 0; 424168404Spjd VM_OBJECT_LOCK(obj); 425168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 426168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 427168404Spjd 428168404Spjdagain: 429168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 430168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 431168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 432168404Spjd goto again; 433168404Spjd vm_page_busy(m); 434168404Spjd VM_OBJECT_UNLOCK(obj); 435169059Spjd if (dirbytes > 0) { 436169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 437169059Spjd dirbytes); 438169059Spjd dirbytes = 0; 439169059Spjd } 440169059Spjd if (error == 0) { 441169059Spjd sched_pin(); 442169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 443169059Spjd va = (caddr_t)sf_buf_kva(sf); 444169059Spjd error = uiomove(va + off, bytes, UIO_READ, uio); 445169059Spjd sf_buf_free(sf); 446169059Spjd sched_unpin(); 447169059Spjd } 448168404Spjd VM_OBJECT_LOCK(obj); 449168404Spjd vm_page_wakeup(m); 450168926Spjd } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { 451168962Spjd /* 452168962Spjd * The code below is here to make sendfile(2) work 453168962Spjd * correctly with ZFS. As pointed out by ups@ 454168962Spjd * sendfile(2) should be changed to use VOP_GETPAGES(), 455168962Spjd * but it pessimize performance of sendfile/UFS, that's 456168962Spjd * why I handle this special case in ZFS code. 457168962Spjd */ 458168926Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 459168926Spjd goto again; 460168926Spjd vm_page_busy(m); 461168926Spjd VM_OBJECT_UNLOCK(obj); 462169059Spjd if (dirbytes > 0) { 463169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 464169059Spjd dirbytes); 465169059Spjd dirbytes = 0; 466169059Spjd } 467169059Spjd if (error == 0) { 468169059Spjd sched_pin(); 469169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 470169059Spjd va = (caddr_t)sf_buf_kva(sf); 471169059Spjd error = dmu_read(os, zp->z_id, start + off, 472169059Spjd bytes, (void *)(va + off)); 473169059Spjd sf_buf_free(sf); 474169059Spjd sched_unpin(); 475169059Spjd } 476168926Spjd VM_OBJECT_LOCK(obj); 477168926Spjd vm_page_wakeup(m); 478169059Spjd if (error == 0) 479169059Spjd uio->uio_resid -= bytes; 480168404Spjd } else { 481169059Spjd dirbytes += bytes; 482168404Spjd } 483168404Spjd len -= bytes; 484168404Spjd off = 0; 485168404Spjd if (error) 486168404Spjd break; 487168404Spjd } 488168404Spjd VM_OBJECT_UNLOCK(obj); 489169059Spjd if (error == 0 && dirbytes > 0) 490169059Spjd error = dmu_read_uio(os, zp->z_id, uio, dirbytes); 491168404Spjd return (error); 492168404Spjd} 493168404Spjd 494168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */ 495168404Spjd 496168404Spjd/* 497168404Spjd * Read bytes from specified file into supplied buffer. 498168404Spjd * 499168404Spjd * IN: vp - vnode of file to be read from. 500168404Spjd * uio - structure supplying read location, range info, 501168404Spjd * and return buffer. 502168404Spjd * ioflag - SYNC flags; used to provide FRSYNC semantics. 503168404Spjd * cr - credentials of caller. 504185029Spjd * ct - caller context 505168404Spjd * 506168404Spjd * OUT: uio - updated offset and range, buffer filled. 507168404Spjd * 508168404Spjd * RETURN: 0 if success 509168404Spjd * error code if failure 510168404Spjd * 511168404Spjd * Side Effects: 512168404Spjd * vp - atime updated if byte count > 0 513168404Spjd */ 514168404Spjd/* ARGSUSED */ 515168404Spjdstatic int 516168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 517168404Spjd{ 518168404Spjd znode_t *zp = VTOZ(vp); 519168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 520185029Spjd objset_t *os; 521168404Spjd ssize_t n, nbytes; 522168404Spjd int error; 523168404Spjd rl_t *rl; 524168404Spjd 525168404Spjd ZFS_ENTER(zfsvfs); 526185029Spjd ZFS_VERIFY_ZP(zp); 527185029Spjd os = zfsvfs->z_os; 528168404Spjd 529185029Spjd if (zp->z_phys->zp_flags & ZFS_AV_QUARANTINED) { 530185029Spjd ZFS_EXIT(zfsvfs); 531185029Spjd return (EACCES); 532185029Spjd } 533185029Spjd 534168404Spjd /* 535168404Spjd * Validate file offset 536168404Spjd */ 537168404Spjd if (uio->uio_loffset < (offset_t)0) { 538168404Spjd ZFS_EXIT(zfsvfs); 539168404Spjd return (EINVAL); 540168404Spjd } 541168404Spjd 542168404Spjd /* 543168404Spjd * Fasttrack empty reads 544168404Spjd */ 545168404Spjd if (uio->uio_resid == 0) { 546168404Spjd ZFS_EXIT(zfsvfs); 547168404Spjd return (0); 548168404Spjd } 549168404Spjd 550168404Spjd /* 551168962Spjd * Check for mandatory locks 552168962Spjd */ 553168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode)) { 554168962Spjd if (error = chklock(vp, FREAD, 555168962Spjd uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { 556168962Spjd ZFS_EXIT(zfsvfs); 557168962Spjd return (error); 558168962Spjd } 559168962Spjd } 560168962Spjd 561168962Spjd /* 562168404Spjd * If we're in FRSYNC mode, sync out this znode before reading it. 563168404Spjd */ 564168962Spjd if (ioflag & FRSYNC) 565168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 566168404Spjd 567168404Spjd /* 568168404Spjd * Lock the range against changes. 569168404Spjd */ 570168404Spjd rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER); 571168404Spjd 572168404Spjd /* 573168404Spjd * If we are reading past end-of-file we can skip 574168404Spjd * to the end; but we might still need to set atime. 575168404Spjd */ 576168404Spjd if (uio->uio_loffset >= zp->z_phys->zp_size) { 577168404Spjd error = 0; 578168404Spjd goto out; 579168404Spjd } 580168404Spjd 581168404Spjd ASSERT(uio->uio_loffset < zp->z_phys->zp_size); 582168404Spjd n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset); 583168404Spjd 584168404Spjd while (n > 0) { 585168404Spjd nbytes = MIN(n, zfs_read_chunk_size - 586168404Spjd P2PHASE(uio->uio_loffset, zfs_read_chunk_size)); 587168404Spjd 588168404Spjd if (vn_has_cached_data(vp)) 589168404Spjd error = mappedread(vp, nbytes, uio); 590168404Spjd else 591168404Spjd error = dmu_read_uio(os, zp->z_id, uio, nbytes); 592185029Spjd if (error) { 593185029Spjd /* convert checksum errors into IO errors */ 594185029Spjd if (error == ECKSUM) 595185029Spjd error = EIO; 596168404Spjd break; 597185029Spjd } 598168962Spjd 599168404Spjd n -= nbytes; 600168404Spjd } 601168404Spjd 602168404Spjdout: 603168404Spjd zfs_range_unlock(rl); 604168404Spjd 605168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 606168404Spjd ZFS_EXIT(zfsvfs); 607168404Spjd return (error); 608168404Spjd} 609168404Spjd 610168404Spjd/* 611168404Spjd * Fault in the pages of the first n bytes specified by the uio structure. 612168404Spjd * 1 byte in each page is touched and the uio struct is unmodified. 613168404Spjd * Any error will exit this routine as this is only a best 614168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch(). 615168404Spjd */ 616168404Spjdstatic void 617168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio) 618168404Spjd{ 619168404Spjd struct iovec *iov; 620168404Spjd ulong_t cnt, incr; 621168404Spjd caddr_t p; 622168404Spjd 623168404Spjd if (uio->uio_segflg != UIO_USERSPACE) 624168404Spjd return; 625168404Spjd 626168404Spjd iov = uio->uio_iov; 627168404Spjd 628168404Spjd while (n) { 629168404Spjd cnt = MIN(iov->iov_len, n); 630168404Spjd if (cnt == 0) { 631168404Spjd /* empty iov entry */ 632168404Spjd iov++; 633168404Spjd continue; 634168404Spjd } 635168404Spjd n -= cnt; 636168404Spjd /* 637168404Spjd * touch each page in this segment. 638168404Spjd */ 639168404Spjd p = iov->iov_base; 640168404Spjd while (cnt) { 641168404Spjd if (fubyte(p) == -1) 642168404Spjd return; 643168404Spjd incr = MIN(cnt, PAGESIZE); 644168404Spjd p += incr; 645168404Spjd cnt -= incr; 646168404Spjd } 647168404Spjd /* 648168404Spjd * touch the last byte in case it straddles a page. 649168404Spjd */ 650168404Spjd p--; 651168404Spjd if (fubyte(p) == -1) 652168404Spjd return; 653168404Spjd iov++; 654168404Spjd } 655168404Spjd} 656168404Spjd 657168404Spjd/* 658168404Spjd * Write the bytes to a file. 659168404Spjd * 660168404Spjd * IN: vp - vnode of file to be written to. 661168404Spjd * uio - structure supplying write location, range info, 662168404Spjd * and data buffer. 663168404Spjd * ioflag - IO_APPEND flag set if in append mode. 664168404Spjd * cr - credentials of caller. 665185029Spjd * ct - caller context (NFS/CIFS fem monitor only) 666168404Spjd * 667168404Spjd * OUT: uio - updated offset and range. 668168404Spjd * 669168404Spjd * RETURN: 0 if success 670168404Spjd * error code if failure 671168404Spjd * 672168404Spjd * Timestamps: 673168404Spjd * vp - ctime|mtime updated if byte count > 0 674168404Spjd */ 675168404Spjd/* ARGSUSED */ 676168404Spjdstatic int 677168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 678168404Spjd{ 679168404Spjd znode_t *zp = VTOZ(vp); 680168962Spjd rlim64_t limit = MAXOFFSET_T; 681168404Spjd ssize_t start_resid = uio->uio_resid; 682168404Spjd ssize_t tx_bytes; 683168404Spjd uint64_t end_size; 684168404Spjd dmu_tx_t *tx; 685168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 686185029Spjd zilog_t *zilog; 687168404Spjd offset_t woff; 688168404Spjd ssize_t n, nbytes; 689168404Spjd rl_t *rl; 690168404Spjd int max_blksz = zfsvfs->z_max_blksz; 691185029Spjd uint64_t pflags; 692168404Spjd int error; 693168404Spjd 694168404Spjd /* 695168404Spjd * Fasttrack empty write 696168404Spjd */ 697168404Spjd n = start_resid; 698168404Spjd if (n == 0) 699168404Spjd return (0); 700168404Spjd 701168962Spjd if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 702168962Spjd limit = MAXOFFSET_T; 703168962Spjd 704168404Spjd ZFS_ENTER(zfsvfs); 705185029Spjd ZFS_VERIFY_ZP(zp); 706168404Spjd 707168404Spjd /* 708185029Spjd * If immutable or not appending then return EPERM 709185029Spjd */ 710185029Spjd pflags = zp->z_phys->zp_flags; 711185029Spjd if ((pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || 712185029Spjd ((pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) && 713185029Spjd (uio->uio_loffset < zp->z_phys->zp_size))) { 714185029Spjd ZFS_EXIT(zfsvfs); 715185029Spjd return (EPERM); 716185029Spjd } 717185029Spjd 718185029Spjd zilog = zfsvfs->z_log; 719185029Spjd 720185029Spjd /* 721168404Spjd * Pre-fault the pages to ensure slow (eg NFS) pages 722168404Spjd * don't hold up txg. 723168404Spjd */ 724168404Spjd zfs_prefault_write(n, uio); 725168404Spjd 726168404Spjd /* 727168404Spjd * If in append mode, set the io offset pointer to eof. 728168404Spjd */ 729168404Spjd if (ioflag & IO_APPEND) { 730168404Spjd /* 731168404Spjd * Range lock for a file append: 732168404Spjd * The value for the start of range will be determined by 733168404Spjd * zfs_range_lock() (to guarantee append semantics). 734168404Spjd * If this write will cause the block size to increase, 735168404Spjd * zfs_range_lock() will lock the entire file, so we must 736168404Spjd * later reduce the range after we grow the block size. 737168404Spjd */ 738168404Spjd rl = zfs_range_lock(zp, 0, n, RL_APPEND); 739168404Spjd if (rl->r_len == UINT64_MAX) { 740168404Spjd /* overlocked, zp_size can't change */ 741168404Spjd woff = uio->uio_loffset = zp->z_phys->zp_size; 742168404Spjd } else { 743168404Spjd woff = uio->uio_loffset = rl->r_off; 744168404Spjd } 745168404Spjd } else { 746168404Spjd woff = uio->uio_loffset; 747168404Spjd /* 748168404Spjd * Validate file offset 749168404Spjd */ 750168404Spjd if (woff < 0) { 751168404Spjd ZFS_EXIT(zfsvfs); 752168404Spjd return (EINVAL); 753168404Spjd } 754168404Spjd 755168404Spjd /* 756168404Spjd * If we need to grow the block size then zfs_range_lock() 757168404Spjd * will lock a wider range than we request here. 758168404Spjd * Later after growing the block size we reduce the range. 759168404Spjd */ 760168404Spjd rl = zfs_range_lock(zp, woff, n, RL_WRITER); 761168404Spjd } 762168404Spjd 763168962Spjd if (woff >= limit) { 764168962Spjd zfs_range_unlock(rl); 765168962Spjd ZFS_EXIT(zfsvfs); 766168962Spjd return (EFBIG); 767168962Spjd } 768168962Spjd 769168962Spjd if ((woff + n) > limit || woff > (limit - n)) 770168962Spjd n = limit - woff; 771168962Spjd 772168962Spjd /* 773168962Spjd * Check for mandatory locks 774168962Spjd */ 775168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode) && 776168962Spjd (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { 777168962Spjd zfs_range_unlock(rl); 778168962Spjd ZFS_EXIT(zfsvfs); 779168962Spjd return (error); 780168962Spjd } 781168404Spjd end_size = MAX(zp->z_phys->zp_size, woff + n); 782168404Spjd 783168404Spjd /* 784168404Spjd * Write the file in reasonable size chunks. Each chunk is written 785168404Spjd * in a separate transaction; this keeps the intent log records small 786168404Spjd * and allows us to do more fine-grained space accounting. 787168404Spjd */ 788168404Spjd while (n > 0) { 789168404Spjd /* 790168404Spjd * Start a transaction. 791168404Spjd */ 792168404Spjd woff = uio->uio_loffset; 793168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 794168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 795168404Spjd dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); 796168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 797168404Spjd if (error) { 798168404Spjd if (error == ERESTART && 799168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 800168404Spjd dmu_tx_wait(tx); 801168404Spjd dmu_tx_abort(tx); 802168404Spjd continue; 803168404Spjd } 804168404Spjd dmu_tx_abort(tx); 805168404Spjd break; 806168404Spjd } 807168404Spjd 808168404Spjd /* 809168404Spjd * If zfs_range_lock() over-locked we grow the blocksize 810168404Spjd * and then reduce the lock range. This will only happen 811168404Spjd * on the first iteration since zfs_range_reduce() will 812168404Spjd * shrink down r_len to the appropriate size. 813168404Spjd */ 814168404Spjd if (rl->r_len == UINT64_MAX) { 815168404Spjd uint64_t new_blksz; 816168404Spjd 817168404Spjd if (zp->z_blksz > max_blksz) { 818168404Spjd ASSERT(!ISP2(zp->z_blksz)); 819168404Spjd new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE); 820168404Spjd } else { 821168404Spjd new_blksz = MIN(end_size, max_blksz); 822168404Spjd } 823168404Spjd zfs_grow_blocksize(zp, new_blksz, tx); 824168404Spjd zfs_range_reduce(rl, woff, n); 825168404Spjd } 826168404Spjd 827168404Spjd /* 828168404Spjd * XXX - should we really limit each write to z_max_blksz? 829168404Spjd * Perhaps we should use SPA_MAXBLOCKSIZE chunks? 830168404Spjd */ 831168404Spjd nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz)); 832168404Spjd 833168404Spjd if (woff + nbytes > zp->z_phys->zp_size) 834168404Spjd vnode_pager_setsize(vp, woff + nbytes); 835168404Spjd 836169302Spjd rw_enter(&zp->z_map_lock, RW_READER); 837169302Spjd 838168962Spjd tx_bytes = uio->uio_resid; 839168404Spjd if (vn_has_cached_data(vp)) { 840168404Spjd rw_exit(&zp->z_map_lock); 841168404Spjd error = mappedwrite(vp, nbytes, uio, tx); 842168404Spjd } else { 843168404Spjd error = dmu_write_uio(zfsvfs->z_os, zp->z_id, 844168404Spjd uio, nbytes, tx); 845168404Spjd rw_exit(&zp->z_map_lock); 846168404Spjd } 847168404Spjd tx_bytes -= uio->uio_resid; 848168404Spjd 849168404Spjd /* 850168404Spjd * If we made no progress, we're done. If we made even 851168404Spjd * partial progress, update the znode and ZIL accordingly. 852168404Spjd */ 853168404Spjd if (tx_bytes == 0) { 854168404Spjd dmu_tx_commit(tx); 855168404Spjd ASSERT(error != 0); 856168404Spjd break; 857168404Spjd } 858168404Spjd 859168404Spjd /* 860168404Spjd * Clear Set-UID/Set-GID bits on successful write if not 861168404Spjd * privileged and at least one of the excute bits is set. 862168404Spjd * 863168404Spjd * It would be nice to to this after all writes have 864168404Spjd * been done, but that would still expose the ISUID/ISGID 865168404Spjd * to another app after the partial write is committed. 866185029Spjd * 867185029Spjd * Note: we don't call zfs_fuid_map_id() here because 868185029Spjd * user 0 is not an ephemeral uid. 869168404Spjd */ 870168404Spjd mutex_enter(&zp->z_acl_lock); 871168404Spjd if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) | 872168404Spjd (S_IXUSR >> 6))) != 0 && 873168404Spjd (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 && 874185029Spjd secpolicy_vnode_setid_retain(vp, cr, 875168404Spjd (zp->z_phys->zp_mode & S_ISUID) != 0 && 876168404Spjd zp->z_phys->zp_uid == 0) != 0) { 877185029Spjd zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID); 878168404Spjd } 879168404Spjd mutex_exit(&zp->z_acl_lock); 880168404Spjd 881168404Spjd /* 882168404Spjd * Update time stamp. NOTE: This marks the bonus buffer as 883168404Spjd * dirty, so we don't have to do it again for zp_size. 884168404Spjd */ 885168404Spjd zfs_time_stamper(zp, CONTENT_MODIFIED, tx); 886168404Spjd 887168404Spjd /* 888168404Spjd * Update the file size (zp_size) if it has changed; 889168404Spjd * account for possible concurrent updates. 890168404Spjd */ 891168404Spjd while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset) 892168404Spjd (void) atomic_cas_64(&zp->z_phys->zp_size, end_size, 893168404Spjd uio->uio_loffset); 894168404Spjd zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); 895168404Spjd dmu_tx_commit(tx); 896168404Spjd 897168404Spjd if (error != 0) 898168404Spjd break; 899168404Spjd ASSERT(tx_bytes == nbytes); 900168404Spjd n -= nbytes; 901168404Spjd } 902168404Spjd 903168404Spjd zfs_range_unlock(rl); 904168404Spjd 905168404Spjd /* 906168404Spjd * If we're in replay mode, or we made no progress, return error. 907168404Spjd * Otherwise, it's at least a partial write, so it's successful. 908168404Spjd */ 909168404Spjd if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) { 910168404Spjd ZFS_EXIT(zfsvfs); 911168404Spjd return (error); 912168404Spjd } 913168404Spjd 914168962Spjd if (ioflag & (FSYNC | FDSYNC)) 915168404Spjd zil_commit(zilog, zp->z_last_itx, zp->z_id); 916168404Spjd 917168404Spjd ZFS_EXIT(zfsvfs); 918168404Spjd return (0); 919168404Spjd} 920168404Spjd 921168404Spjdvoid 922168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd) 923168404Spjd{ 924168404Spjd zgd_t *zgd = (zgd_t *)vzgd; 925168404Spjd rl_t *rl = zgd->zgd_rl; 926168404Spjd vnode_t *vp = ZTOV(rl->r_zp); 927168404Spjd int vfslocked; 928168404Spjd 929168404Spjd vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); 930168404Spjd dmu_buf_rele(db, vzgd); 931168404Spjd zfs_range_unlock(rl); 932191900Skmacy /* 933191900Skmacy * Release the vnode asynchronously as we currently have the 934191900Skmacy * txg stopped from syncing. 935191900Skmacy */ 936191900Skmacy VN_RELE_ASYNC(vp, NULL); 937185029Spjd zil_add_block(zgd->zgd_zilog, zgd->zgd_bp); 938168404Spjd kmem_free(zgd, sizeof (zgd_t)); 939168404Spjd VFS_UNLOCK_GIANT(vfslocked); 940168404Spjd} 941168404Spjd 942168404Spjd/* 943168404Spjd * Get data to generate a TX_WRITE intent log record. 944168404Spjd */ 945168404Spjdint 946168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) 947168404Spjd{ 948168404Spjd zfsvfs_t *zfsvfs = arg; 949168404Spjd objset_t *os = zfsvfs->z_os; 950168404Spjd znode_t *zp; 951168404Spjd uint64_t off = lr->lr_offset; 952168404Spjd dmu_buf_t *db; 953168404Spjd rl_t *rl; 954168404Spjd zgd_t *zgd; 955168404Spjd int dlen = lr->lr_length; /* length of user data */ 956168404Spjd int error = 0; 957168404Spjd 958168404Spjd ASSERT(zio); 959168404Spjd ASSERT(dlen != 0); 960168404Spjd 961168404Spjd /* 962168404Spjd * Nothing to do if the file has been removed 963168404Spjd */ 964168404Spjd if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0) 965168404Spjd return (ENOENT); 966168404Spjd if (zp->z_unlinked) { 967191900Skmacy /* 968191900Skmacy * Release the vnode asynchronously as we currently have the 969191900Skmacy * txg stopped from syncing. 970191900Skmacy */ 971191900Skmacy VN_RELE_ASYNC(ZTOV(zp), NULL); 972191900Skmacy 973168404Spjd return (ENOENT); 974168404Spjd } 975168404Spjd 976168404Spjd /* 977168404Spjd * Write records come in two flavors: immediate and indirect. 978168404Spjd * For small writes it's cheaper to store the data with the 979168404Spjd * log record (immediate); for large writes it's cheaper to 980168404Spjd * sync the data and get a pointer to it (indirect) so that 981168404Spjd * we don't have to write the data twice. 982168404Spjd */ 983168404Spjd if (buf != NULL) { /* immediate write */ 984168404Spjd rl = zfs_range_lock(zp, off, dlen, RL_READER); 985168404Spjd /* test for truncation needs to be done while range locked */ 986168404Spjd if (off >= zp->z_phys->zp_size) { 987168404Spjd error = ENOENT; 988168404Spjd goto out; 989168404Spjd } 990168404Spjd VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf)); 991168404Spjd } else { /* indirect write */ 992168404Spjd uint64_t boff; /* block starting offset */ 993168404Spjd 994168404Spjd /* 995168404Spjd * Have to lock the whole block to ensure when it's 996168404Spjd * written out and it's checksum is being calculated 997168404Spjd * that no one can change the data. We need to re-check 998168404Spjd * blocksize after we get the lock in case it's changed! 999168404Spjd */ 1000168404Spjd for (;;) { 1001168404Spjd if (ISP2(zp->z_blksz)) { 1002168404Spjd boff = P2ALIGN_TYPED(off, zp->z_blksz, 1003168404Spjd uint64_t); 1004168404Spjd } else { 1005168404Spjd boff = 0; 1006168404Spjd } 1007168404Spjd dlen = zp->z_blksz; 1008168404Spjd rl = zfs_range_lock(zp, boff, dlen, RL_READER); 1009168404Spjd if (zp->z_blksz == dlen) 1010168404Spjd break; 1011168404Spjd zfs_range_unlock(rl); 1012168404Spjd } 1013168404Spjd /* test for truncation needs to be done while range locked */ 1014168404Spjd if (off >= zp->z_phys->zp_size) { 1015168404Spjd error = ENOENT; 1016168404Spjd goto out; 1017168404Spjd } 1018168404Spjd zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP); 1019168404Spjd zgd->zgd_rl = rl; 1020168404Spjd zgd->zgd_zilog = zfsvfs->z_log; 1021168404Spjd zgd->zgd_bp = &lr->lr_blkptr; 1022168404Spjd VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db)); 1023168404Spjd ASSERT(boff == db->db_offset); 1024168404Spjd lr->lr_blkoff = off - boff; 1025168404Spjd error = dmu_sync(zio, db, &lr->lr_blkptr, 1026168404Spjd lr->lr_common.lrc_txg, zfs_get_done, zgd); 1027185029Spjd ASSERT((error && error != EINPROGRESS) || 1028185029Spjd lr->lr_length <= zp->z_blksz); 1029185029Spjd if (error == 0) 1030185029Spjd zil_add_block(zfsvfs->z_log, &lr->lr_blkptr); 1031168404Spjd /* 1032168404Spjd * If we get EINPROGRESS, then we need to wait for a 1033168404Spjd * write IO initiated by dmu_sync() to complete before 1034168404Spjd * we can release this dbuf. We will finish everything 1035168404Spjd * up in the zfs_get_done() callback. 1036168404Spjd */ 1037168404Spjd if (error == EINPROGRESS) 1038168404Spjd return (0); 1039168404Spjd dmu_buf_rele(db, zgd); 1040168404Spjd kmem_free(zgd, sizeof (zgd_t)); 1041168404Spjd } 1042168404Spjdout: 1043168404Spjd zfs_range_unlock(rl); 1044191900Skmacy /* 1045191900Skmacy * Release the vnode asynchronously as we currently have the 1046191900Skmacy * txg stopped from syncing. 1047191900Skmacy */ 1048191900Skmacy VN_RELE_ASYNC(ZTOV(zp), NULL); 1049168404Spjd return (error); 1050168404Spjd} 1051168404Spjd 1052168404Spjd/*ARGSUSED*/ 1053168404Spjdstatic int 1054185029Spjdzfs_access(vnode_t *vp, int mode, int flag, cred_t *cr, 1055185029Spjd caller_context_t *ct) 1056168404Spjd{ 1057168404Spjd znode_t *zp = VTOZ(vp); 1058168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1059168404Spjd int error; 1060168404Spjd 1061168404Spjd ZFS_ENTER(zfsvfs); 1062185029Spjd ZFS_VERIFY_ZP(zp); 1063185029Spjd 1064185029Spjd if (flag & V_ACE_MASK) 1065185029Spjd error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); 1066185029Spjd else 1067185029Spjd error = zfs_zaccess_rwx(zp, mode, flag, cr); 1068185029Spjd 1069168404Spjd ZFS_EXIT(zfsvfs); 1070168404Spjd return (error); 1071168404Spjd} 1072168404Spjd 1073168404Spjd/* 1074168404Spjd * Lookup an entry in a directory, or an extended attribute directory. 1075168404Spjd * If it exists, return a held vnode reference for it. 1076168404Spjd * 1077168404Spjd * IN: dvp - vnode of directory to search. 1078168404Spjd * nm - name of entry to lookup. 1079168404Spjd * pnp - full pathname to lookup [UNUSED]. 1080168404Spjd * flags - LOOKUP_XATTR set if looking for an attribute. 1081168404Spjd * rdir - root directory vnode [UNUSED]. 1082168404Spjd * cr - credentials of caller. 1083185029Spjd * ct - caller context 1084185029Spjd * direntflags - directory lookup flags 1085185029Spjd * realpnp - returned pathname. 1086168404Spjd * 1087168404Spjd * OUT: vpp - vnode of located entry, NULL if not found. 1088168404Spjd * 1089168404Spjd * RETURN: 0 if success 1090168404Spjd * error code if failure 1091168404Spjd * 1092168404Spjd * Timestamps: 1093168404Spjd * NA 1094168404Spjd */ 1095168404Spjd/* ARGSUSED */ 1096168962Spjdstatic int 1097168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, 1098185029Spjd int nameiop, cred_t *cr, kthread_t *td, int flags) 1099168404Spjd{ 1100168962Spjd znode_t *zdp = VTOZ(dvp); 1101168962Spjd zfsvfs_t *zfsvfs = zdp->z_zfsvfs; 1102168962Spjd int error; 1103185029Spjd int *direntflags = NULL; 1104185029Spjd void *realpnp = NULL; 1105168404Spjd 1106168404Spjd ZFS_ENTER(zfsvfs); 1107185029Spjd ZFS_VERIFY_ZP(zdp); 1108168404Spjd 1109168404Spjd *vpp = NULL; 1110168404Spjd 1111185029Spjd if (flags & LOOKUP_XATTR) { 1112168404Spjd#ifdef TODO 1113168404Spjd /* 1114168404Spjd * If the xattr property is off, refuse the lookup request. 1115168404Spjd */ 1116168404Spjd if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) { 1117168404Spjd ZFS_EXIT(zfsvfs); 1118168404Spjd return (EINVAL); 1119168404Spjd } 1120185029Spjd#endif 1121168404Spjd 1122168404Spjd /* 1123168404Spjd * We don't allow recursive attributes.. 1124168404Spjd * Maybe someday we will. 1125168404Spjd */ 1126168404Spjd if (zdp->z_phys->zp_flags & ZFS_XATTR) { 1127168404Spjd ZFS_EXIT(zfsvfs); 1128168404Spjd return (EINVAL); 1129168404Spjd } 1130168404Spjd 1131168404Spjd if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) { 1132168404Spjd ZFS_EXIT(zfsvfs); 1133168404Spjd return (error); 1134168404Spjd } 1135168404Spjd 1136168404Spjd /* 1137168404Spjd * Do we have permission to get into attribute directory? 1138168404Spjd */ 1139168404Spjd 1140185029Spjd if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, 0, 1141185029Spjd B_FALSE, cr)) { 1142168404Spjd VN_RELE(*vpp); 1143185029Spjd *vpp = NULL; 1144168404Spjd } 1145168404Spjd 1146168404Spjd ZFS_EXIT(zfsvfs); 1147168404Spjd return (error); 1148168404Spjd } 1149168404Spjd 1150168404Spjd if (dvp->v_type != VDIR) { 1151168404Spjd ZFS_EXIT(zfsvfs); 1152168404Spjd return (ENOTDIR); 1153168404Spjd } 1154168404Spjd 1155168404Spjd /* 1156168404Spjd * Check accessibility of directory. 1157168404Spjd */ 1158168404Spjd 1159185029Spjd if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) { 1160168404Spjd ZFS_EXIT(zfsvfs); 1161168404Spjd return (error); 1162168404Spjd } 1163168404Spjd 1164185029Spjd if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm), 1165185029Spjd NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 1166185029Spjd ZFS_EXIT(zfsvfs); 1167185029Spjd return (EILSEQ); 1168185029Spjd } 1169168404Spjd 1170185029Spjd error = zfs_dirlook(zdp, nm, vpp, flags, direntflags, realpnp); 1171185029Spjd if (error == 0) { 1172168962Spjd /* 1173168962Spjd * Convert device special files 1174168962Spjd */ 1175168962Spjd if (IS_DEVVP(*vpp)) { 1176168962Spjd vnode_t *svp; 1177168962Spjd 1178168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1179168962Spjd VN_RELE(*vpp); 1180168962Spjd if (svp == NULL) 1181168962Spjd error = ENOSYS; 1182168962Spjd else 1183168962Spjd *vpp = svp; 1184168962Spjd } 1185168962Spjd } 1186168962Spjd 1187168404Spjd ZFS_EXIT(zfsvfs); 1188168404Spjd 1189168404Spjd /* Translate errors and add SAVENAME when needed. */ 1190168404Spjd if (cnp->cn_flags & ISLASTCN) { 1191168404Spjd switch (nameiop) { 1192168404Spjd case CREATE: 1193168404Spjd case RENAME: 1194168404Spjd if (error == ENOENT) { 1195168404Spjd error = EJUSTRETURN; 1196168404Spjd cnp->cn_flags |= SAVENAME; 1197168404Spjd break; 1198168404Spjd } 1199168404Spjd /* FALLTHROUGH */ 1200168404Spjd case DELETE: 1201168404Spjd if (error == 0) 1202168404Spjd cnp->cn_flags |= SAVENAME; 1203168404Spjd break; 1204168404Spjd } 1205168404Spjd } 1206168404Spjd if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) { 1207169198Spjd int ltype = 0; 1208169198Spjd 1209169198Spjd if (cnp->cn_flags & ISDOTDOT) { 1210176559Sattilio ltype = VOP_ISLOCKED(dvp); 1211175294Sattilio VOP_UNLOCK(dvp, 0); 1212169198Spjd } 1213175202Sattilio error = vn_lock(*vpp, cnp->cn_lkflags); 1214168962Spjd if (cnp->cn_flags & ISDOTDOT) 1215175202Sattilio vn_lock(dvp, ltype | LK_RETRY); 1216169172Spjd if (error != 0) { 1217169172Spjd VN_RELE(*vpp); 1218169172Spjd *vpp = NULL; 1219169172Spjd return (error); 1220169172Spjd } 1221168404Spjd } 1222168404Spjd 1223168404Spjd#ifdef FREEBSD_NAMECACHE 1224168404Spjd /* 1225168404Spjd * Insert name into cache (as non-existent) if appropriate. 1226168404Spjd */ 1227168404Spjd if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 1228168404Spjd cache_enter(dvp, *vpp, cnp); 1229169170Spjd /* 1230169170Spjd * Insert name into cache if appropriate. 1231169170Spjd */ 1232168404Spjd if (error == 0 && (cnp->cn_flags & MAKEENTRY)) { 1233168404Spjd if (!(cnp->cn_flags & ISLASTCN) || 1234168404Spjd (nameiop != DELETE && nameiop != RENAME)) { 1235168404Spjd cache_enter(dvp, *vpp, cnp); 1236168404Spjd } 1237168404Spjd } 1238168404Spjd#endif 1239168404Spjd 1240168404Spjd return (error); 1241168404Spjd} 1242168404Spjd 1243168404Spjd/* 1244168404Spjd * Attempt to create a new entry in a directory. If the entry 1245168404Spjd * already exists, truncate the file if permissible, else return 1246168404Spjd * an error. Return the vp of the created or trunc'd file. 1247168404Spjd * 1248168404Spjd * IN: dvp - vnode of directory to put new file entry in. 1249168404Spjd * name - name of new file entry. 1250168404Spjd * vap - attributes of new file. 1251168404Spjd * excl - flag indicating exclusive or non-exclusive mode. 1252168404Spjd * mode - mode to open file with. 1253168404Spjd * cr - credentials of caller. 1254168404Spjd * flag - large file flag [UNUSED]. 1255185029Spjd * ct - caller context 1256185029Spjd * vsecp - ACL to be set 1257168404Spjd * 1258168404Spjd * OUT: vpp - vnode of created or trunc'd entry. 1259168404Spjd * 1260168404Spjd * RETURN: 0 if success 1261168404Spjd * error code if failure 1262168404Spjd * 1263168404Spjd * Timestamps: 1264168404Spjd * dvp - ctime|mtime updated if new entry created 1265168404Spjd * vp - ctime|mtime always, atime if new 1266168404Spjd */ 1267185029Spjd 1268168404Spjd/* ARGSUSED */ 1269168404Spjdstatic int 1270168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode, 1271185029Spjd vnode_t **vpp, cred_t *cr, kthread_t *td) 1272168404Spjd{ 1273168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1274168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1275185029Spjd zilog_t *zilog; 1276185029Spjd objset_t *os; 1277168404Spjd zfs_dirlock_t *dl; 1278168404Spjd dmu_tx_t *tx; 1279168404Spjd int error; 1280185029Spjd zfs_acl_t *aclp = NULL; 1281185029Spjd zfs_fuid_info_t *fuidp = NULL; 1282185029Spjd void *vsecp = NULL; 1283185029Spjd int flag = 0; 1284168404Spjd 1285185029Spjd /* 1286185029Spjd * If we have an ephemeral id, ACL, or XVATTR then 1287185029Spjd * make sure file system is at proper version 1288185029Spjd */ 1289185029Spjd 1290185029Spjd if (zfsvfs->z_use_fuids == B_FALSE && 1291185029Spjd (vsecp || (vap->va_mask & AT_XVATTR) || 1292185029Spjd IS_EPHEMERAL(crgetuid(cr)) || IS_EPHEMERAL(crgetgid(cr)))) 1293185029Spjd return (EINVAL); 1294185029Spjd 1295168404Spjd ZFS_ENTER(zfsvfs); 1296185029Spjd ZFS_VERIFY_ZP(dzp); 1297185029Spjd os = zfsvfs->z_os; 1298185029Spjd zilog = zfsvfs->z_log; 1299168404Spjd 1300185029Spjd if (zfsvfs->z_utf8 && u8_validate(name, strlen(name), 1301185029Spjd NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 1302185029Spjd ZFS_EXIT(zfsvfs); 1303185029Spjd return (EILSEQ); 1304185029Spjd } 1305185029Spjd 1306185029Spjd if (vap->va_mask & AT_XVATTR) { 1307185029Spjd if ((error = secpolicy_xvattr((xvattr_t *)vap, 1308185029Spjd crgetuid(cr), cr, vap->va_type)) != 0) { 1309185029Spjd ZFS_EXIT(zfsvfs); 1310185029Spjd return (error); 1311185029Spjd } 1312185029Spjd } 1313168404Spjdtop: 1314168404Spjd *vpp = NULL; 1315168404Spjd 1316182905Strasz if ((vap->va_mode & S_ISVTX) && secpolicy_vnode_stky_modify(cr)) 1317182905Strasz vap->va_mode &= ~S_ISVTX; 1318168404Spjd 1319168404Spjd if (*name == '\0') { 1320168404Spjd /* 1321168404Spjd * Null component name refers to the directory itself. 1322168404Spjd */ 1323168404Spjd VN_HOLD(dvp); 1324168404Spjd zp = dzp; 1325168404Spjd dl = NULL; 1326168404Spjd error = 0; 1327168404Spjd } else { 1328168404Spjd /* possible VN_HOLD(zp) */ 1329185029Spjd int zflg = 0; 1330185029Spjd 1331185029Spjd if (flag & FIGNORECASE) 1332185029Spjd zflg |= ZCILOOK; 1333185029Spjd 1334185029Spjd error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, 1335185029Spjd NULL, NULL); 1336185029Spjd if (error) { 1337168404Spjd if (strcmp(name, "..") == 0) 1338168404Spjd error = EISDIR; 1339168404Spjd ZFS_EXIT(zfsvfs); 1340185029Spjd if (aclp) 1341185029Spjd zfs_acl_free(aclp); 1342168404Spjd return (error); 1343168404Spjd } 1344168404Spjd } 1345185029Spjd if (vsecp && aclp == NULL) { 1346185029Spjd error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, &aclp); 1347185029Spjd if (error) { 1348185029Spjd ZFS_EXIT(zfsvfs); 1349185029Spjd if (dl) 1350185029Spjd zfs_dirent_unlock(dl); 1351185029Spjd return (error); 1352185029Spjd } 1353185029Spjd } 1354168404Spjd 1355185029Spjd if (zp == NULL) { 1356185029Spjd uint64_t txtype; 1357168404Spjd 1358168404Spjd /* 1359168404Spjd * Create a new file object and update the directory 1360168404Spjd * to reference it. 1361168404Spjd */ 1362185029Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { 1363168404Spjd goto out; 1364168404Spjd } 1365168404Spjd 1366168404Spjd /* 1367168404Spjd * We only support the creation of regular files in 1368168404Spjd * extended attribute directories. 1369168404Spjd */ 1370168404Spjd if ((dzp->z_phys->zp_flags & ZFS_XATTR) && 1371168404Spjd (vap->va_type != VREG)) { 1372168404Spjd error = EINVAL; 1373168404Spjd goto out; 1374168404Spjd } 1375168404Spjd 1376168404Spjd tx = dmu_tx_create(os); 1377168404Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1378185029Spjd if ((aclp && aclp->z_has_fuids) || IS_EPHEMERAL(crgetuid(cr)) || 1379185029Spjd IS_EPHEMERAL(crgetgid(cr))) { 1380185029Spjd if (zfsvfs->z_fuid_obj == 0) { 1381185029Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1382185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 1383185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 1384185029Spjd dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, 1385185029Spjd FALSE, NULL); 1386185029Spjd } else { 1387185029Spjd dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 1388185029Spjd dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 1389185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 1390185029Spjd } 1391185029Spjd } 1392168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 1393168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 1394185029Spjd if ((dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) || aclp) { 1395168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1396168404Spjd 0, SPA_MAXBLOCKSIZE); 1397185029Spjd } 1398168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1399168404Spjd if (error) { 1400168404Spjd zfs_dirent_unlock(dl); 1401168404Spjd if (error == ERESTART && 1402168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1403168404Spjd dmu_tx_wait(tx); 1404168404Spjd dmu_tx_abort(tx); 1405168404Spjd goto top; 1406168404Spjd } 1407168404Spjd dmu_tx_abort(tx); 1408168404Spjd ZFS_EXIT(zfsvfs); 1409185029Spjd if (aclp) 1410185029Spjd zfs_acl_free(aclp); 1411168404Spjd return (error); 1412168404Spjd } 1413185029Spjd zfs_mknode(dzp, vap, tx, cr, 0, &zp, 0, aclp, &fuidp); 1414168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1415185029Spjd txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap); 1416185029Spjd if (flag & FIGNORECASE) 1417185029Spjd txtype |= TX_CI; 1418185029Spjd zfs_log_create(zilog, tx, txtype, dzp, zp, name, 1419185029Spjd vsecp, fuidp, vap); 1420185029Spjd if (fuidp) 1421185029Spjd zfs_fuid_info_free(fuidp); 1422168404Spjd dmu_tx_commit(tx); 1423168404Spjd } else { 1424185029Spjd int aflags = (flag & FAPPEND) ? V_APPEND : 0; 1425185029Spjd 1426168404Spjd /* 1427168404Spjd * A directory entry already exists for this name. 1428168404Spjd */ 1429168404Spjd /* 1430168962Spjd * Can't truncate an existing file if in exclusive mode. 1431168962Spjd */ 1432168962Spjd if (excl == EXCL) { 1433168962Spjd error = EEXIST; 1434168962Spjd goto out; 1435168962Spjd } 1436168962Spjd /* 1437168404Spjd * Can't open a directory for writing. 1438168404Spjd */ 1439168404Spjd if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) { 1440168404Spjd error = EISDIR; 1441168404Spjd goto out; 1442168404Spjd } 1443168404Spjd /* 1444168404Spjd * Verify requested access to file. 1445168404Spjd */ 1446185029Spjd if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr))) { 1447168404Spjd goto out; 1448168404Spjd } 1449168404Spjd 1450168404Spjd mutex_enter(&dzp->z_lock); 1451168404Spjd dzp->z_seq++; 1452168404Spjd mutex_exit(&dzp->z_lock); 1453168404Spjd 1454168404Spjd /* 1455168404Spjd * Truncate regular files if requested. 1456168404Spjd */ 1457168404Spjd if ((ZTOV(zp)->v_type == VREG) && 1458168404Spjd (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) { 1459185029Spjd /* we can't hold any locks when calling zfs_freesp() */ 1460185029Spjd zfs_dirent_unlock(dl); 1461185029Spjd dl = NULL; 1462168404Spjd error = zfs_freesp(zp, 0, 0, mode, TRUE); 1463185029Spjd if (error == 0) { 1464185029Spjd vnevent_create(ZTOV(zp), ct); 1465168404Spjd } 1466168404Spjd } 1467168404Spjd } 1468168404Spjdout: 1469168404Spjd if (dl) 1470168404Spjd zfs_dirent_unlock(dl); 1471168404Spjd 1472168404Spjd if (error) { 1473168404Spjd if (zp) 1474168404Spjd VN_RELE(ZTOV(zp)); 1475168962Spjd } else { 1476168962Spjd *vpp = ZTOV(zp); 1477168962Spjd /* 1478168962Spjd * If vnode is for a device return a specfs vnode instead. 1479168962Spjd */ 1480168962Spjd if (IS_DEVVP(*vpp)) { 1481168962Spjd struct vnode *svp; 1482168962Spjd 1483168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1484168962Spjd VN_RELE(*vpp); 1485168962Spjd if (svp == NULL) { 1486168962Spjd error = ENOSYS; 1487168962Spjd } 1488168962Spjd *vpp = svp; 1489168962Spjd } 1490168404Spjd } 1491185029Spjd if (aclp) 1492185029Spjd zfs_acl_free(aclp); 1493168404Spjd 1494168404Spjd ZFS_EXIT(zfsvfs); 1495168404Spjd return (error); 1496168404Spjd} 1497168404Spjd 1498168404Spjd/* 1499168404Spjd * Remove an entry from a directory. 1500168404Spjd * 1501168404Spjd * IN: dvp - vnode of directory to remove entry from. 1502168404Spjd * name - name of entry to remove. 1503168404Spjd * cr - credentials of caller. 1504185029Spjd * ct - caller context 1505185029Spjd * flags - case flags 1506168404Spjd * 1507168404Spjd * RETURN: 0 if success 1508168404Spjd * error code if failure 1509168404Spjd * 1510168404Spjd * Timestamps: 1511168404Spjd * dvp - ctime|mtime 1512168404Spjd * vp - ctime (if nlink > 0) 1513168404Spjd */ 1514185029Spjd/*ARGSUSED*/ 1515168404Spjdstatic int 1516185029Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr, caller_context_t *ct, 1517185029Spjd int flags) 1518168404Spjd{ 1519168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1520168404Spjd znode_t *xzp = NULL; 1521168404Spjd vnode_t *vp; 1522168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1523185029Spjd zilog_t *zilog; 1524168962Spjd uint64_t acl_obj, xattr_obj; 1525168404Spjd zfs_dirlock_t *dl; 1526168404Spjd dmu_tx_t *tx; 1527168962Spjd boolean_t may_delete_now, delete_now = FALSE; 1528185029Spjd boolean_t unlinked, toobig = FALSE; 1529185029Spjd uint64_t txtype; 1530185029Spjd pathname_t *realnmp = NULL; 1531185029Spjd pathname_t realnm; 1532168404Spjd int error; 1533185029Spjd int zflg = ZEXISTS; 1534168404Spjd 1535168404Spjd ZFS_ENTER(zfsvfs); 1536185029Spjd ZFS_VERIFY_ZP(dzp); 1537185029Spjd zilog = zfsvfs->z_log; 1538168404Spjd 1539185029Spjd if (flags & FIGNORECASE) { 1540185029Spjd zflg |= ZCILOOK; 1541185029Spjd pn_alloc(&realnm); 1542185029Spjd realnmp = &realnm; 1543185029Spjd } 1544185029Spjd 1545168404Spjdtop: 1546168404Spjd /* 1547168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1548168404Spjd */ 1549185029Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, 1550185029Spjd NULL, realnmp)) { 1551185029Spjd if (realnmp) 1552185029Spjd pn_free(realnmp); 1553168404Spjd ZFS_EXIT(zfsvfs); 1554168404Spjd return (error); 1555168404Spjd } 1556168404Spjd 1557168404Spjd vp = ZTOV(zp); 1558168404Spjd 1559168962Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1560168404Spjd goto out; 1561168962Spjd } 1562168404Spjd 1563168962Spjd /* 1564168962Spjd * Need to use rmdir for removing directories. 1565168962Spjd */ 1566168962Spjd if (vp->v_type == VDIR) { 1567168962Spjd error = EPERM; 1568168962Spjd goto out; 1569168962Spjd } 1570168962Spjd 1571185029Spjd vnevent_remove(vp, dvp, name, ct); 1572168962Spjd 1573185029Spjd if (realnmp) 1574185029Spjd dnlc_remove(dvp, realnmp->pn_buf); 1575185029Spjd else 1576185029Spjd dnlc_remove(dvp, name); 1577168404Spjd 1578168962Spjd may_delete_now = FALSE; 1579168962Spjd 1580168404Spjd /* 1581168404Spjd * We may delete the znode now, or we may put it in the unlinked set; 1582168404Spjd * it depends on whether we're the last link, and on whether there are 1583168404Spjd * other holds on the vnode. So we dmu_tx_hold() the right things to 1584168404Spjd * allow for either case. 1585168404Spjd */ 1586168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1587168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1588168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1589185029Spjd if (may_delete_now) { 1590185029Spjd toobig = 1591185029Spjd zp->z_phys->zp_size > zp->z_blksz * DMU_MAX_DELETEBLKCNT; 1592185029Spjd /* if the file is too big, only hold_free a token amount */ 1593185029Spjd dmu_tx_hold_free(tx, zp->z_id, 0, 1594185029Spjd (toobig ? DMU_MAX_ACCESS : DMU_OBJECT_END)); 1595185029Spjd } 1596168404Spjd 1597168404Spjd /* are there any extended attributes? */ 1598168404Spjd if ((xattr_obj = zp->z_phys->zp_xattr) != 0) { 1599168404Spjd /* XXX - do we need this if we are deleting? */ 1600168404Spjd dmu_tx_hold_bonus(tx, xattr_obj); 1601168404Spjd } 1602168404Spjd 1603168962Spjd /* are there any additional acls */ 1604168962Spjd if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 && 1605168962Spjd may_delete_now) 1606168962Spjd dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); 1607168962Spjd 1608168404Spjd /* charge as an update -- would be nice not to charge at all */ 1609168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1610168404Spjd 1611168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1612168404Spjd if (error) { 1613168404Spjd zfs_dirent_unlock(dl); 1614168962Spjd VN_RELE(vp); 1615168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1616168404Spjd dmu_tx_wait(tx); 1617168404Spjd dmu_tx_abort(tx); 1618168404Spjd goto top; 1619168404Spjd } 1620185029Spjd if (realnmp) 1621185029Spjd pn_free(realnmp); 1622168404Spjd dmu_tx_abort(tx); 1623168404Spjd ZFS_EXIT(zfsvfs); 1624168404Spjd return (error); 1625168404Spjd } 1626168404Spjd 1627168404Spjd /* 1628168404Spjd * Remove the directory entry. 1629168404Spjd */ 1630185029Spjd error = zfs_link_destroy(dl, zp, tx, zflg, &unlinked); 1631168404Spjd 1632168404Spjd if (error) { 1633168404Spjd dmu_tx_commit(tx); 1634168404Spjd goto out; 1635168404Spjd } 1636168404Spjd 1637168962Spjd if (0 && unlinked) { 1638168962Spjd VI_LOCK(vp); 1639185029Spjd delete_now = may_delete_now && !toobig && 1640168962Spjd vp->v_count == 1 && !vn_has_cached_data(vp) && 1641168962Spjd zp->z_phys->zp_xattr == xattr_obj && 1642168962Spjd zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj; 1643168962Spjd VI_UNLOCK(vp); 1644168962Spjd } 1645168962Spjd 1646168962Spjd if (delete_now) { 1647168962Spjd if (zp->z_phys->zp_xattr) { 1648168962Spjd error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp); 1649168962Spjd ASSERT3U(error, ==, 0); 1650168962Spjd ASSERT3U(xzp->z_phys->zp_links, ==, 2); 1651168962Spjd dmu_buf_will_dirty(xzp->z_dbuf, tx); 1652168962Spjd mutex_enter(&xzp->z_lock); 1653168962Spjd xzp->z_unlinked = 1; 1654168962Spjd xzp->z_phys->zp_links = 0; 1655168962Spjd mutex_exit(&xzp->z_lock); 1656168962Spjd zfs_unlinked_add(xzp, tx); 1657168962Spjd zp->z_phys->zp_xattr = 0; /* probably unnecessary */ 1658168962Spjd } 1659168962Spjd mutex_enter(&zp->z_lock); 1660168962Spjd VI_LOCK(vp); 1661168962Spjd vp->v_count--; 1662168962Spjd ASSERT3U(vp->v_count, ==, 0); 1663168962Spjd VI_UNLOCK(vp); 1664168962Spjd mutex_exit(&zp->z_lock); 1665168962Spjd zfs_znode_delete(zp, tx); 1666168962Spjd } else if (unlinked) { 1667168404Spjd zfs_unlinked_add(zp, tx); 1668168962Spjd } 1669168404Spjd 1670185029Spjd txtype = TX_REMOVE; 1671185029Spjd if (flags & FIGNORECASE) 1672185029Spjd txtype |= TX_CI; 1673185029Spjd zfs_log_remove(zilog, tx, txtype, dzp, name); 1674168404Spjd 1675168404Spjd dmu_tx_commit(tx); 1676168404Spjdout: 1677185029Spjd if (realnmp) 1678185029Spjd pn_free(realnmp); 1679185029Spjd 1680168404Spjd zfs_dirent_unlock(dl); 1681168404Spjd 1682168962Spjd if (!delete_now) { 1683168962Spjd VN_RELE(vp); 1684168962Spjd } else if (xzp) { 1685185029Spjd /* this rele is delayed to prevent nesting transactions */ 1686168962Spjd VN_RELE(ZTOV(xzp)); 1687168962Spjd } 1688168962Spjd 1689168404Spjd ZFS_EXIT(zfsvfs); 1690168404Spjd return (error); 1691168404Spjd} 1692168404Spjd 1693168404Spjd/* 1694168404Spjd * Create a new directory and insert it into dvp using the name 1695168404Spjd * provided. Return a pointer to the inserted directory. 1696168404Spjd * 1697168404Spjd * IN: dvp - vnode of directory to add subdir to. 1698168404Spjd * dirname - name of new directory. 1699168404Spjd * vap - attributes of new directory. 1700168404Spjd * cr - credentials of caller. 1701185029Spjd * ct - caller context 1702185029Spjd * vsecp - ACL to be set 1703168404Spjd * 1704168404Spjd * OUT: vpp - vnode of created directory. 1705168404Spjd * 1706168404Spjd * RETURN: 0 if success 1707168404Spjd * error code if failure 1708168404Spjd * 1709168404Spjd * Timestamps: 1710168404Spjd * dvp - ctime|mtime updated 1711168404Spjd * vp - ctime|mtime|atime updated 1712168404Spjd */ 1713185029Spjd/*ARGSUSED*/ 1714168404Spjdstatic int 1715185029Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr, 1716185029Spjd caller_context_t *ct, int flags, vsecattr_t *vsecp) 1717168404Spjd{ 1718168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1719168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1720185029Spjd zilog_t *zilog; 1721168404Spjd zfs_dirlock_t *dl; 1722185029Spjd uint64_t txtype; 1723168404Spjd dmu_tx_t *tx; 1724168404Spjd int error; 1725185029Spjd zfs_acl_t *aclp = NULL; 1726185029Spjd zfs_fuid_info_t *fuidp = NULL; 1727185029Spjd int zf = ZNEW; 1728168404Spjd 1729168404Spjd ASSERT(vap->va_type == VDIR); 1730168404Spjd 1731185029Spjd /* 1732185029Spjd * If we have an ephemeral id, ACL, or XVATTR then 1733185029Spjd * make sure file system is at proper version 1734185029Spjd */ 1735185029Spjd 1736185029Spjd if (zfsvfs->z_use_fuids == B_FALSE && 1737185029Spjd (vsecp || (vap->va_mask & AT_XVATTR) || IS_EPHEMERAL(crgetuid(cr))|| 1738185029Spjd IS_EPHEMERAL(crgetgid(cr)))) 1739185029Spjd return (EINVAL); 1740185029Spjd 1741168404Spjd ZFS_ENTER(zfsvfs); 1742185029Spjd ZFS_VERIFY_ZP(dzp); 1743185029Spjd zilog = zfsvfs->z_log; 1744168404Spjd 1745168404Spjd if (dzp->z_phys->zp_flags & ZFS_XATTR) { 1746168404Spjd ZFS_EXIT(zfsvfs); 1747168404Spjd return (EINVAL); 1748168404Spjd } 1749168404Spjd 1750185029Spjd if (zfsvfs->z_utf8 && u8_validate(dirname, 1751185029Spjd strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 1752185029Spjd ZFS_EXIT(zfsvfs); 1753185029Spjd return (EILSEQ); 1754185029Spjd } 1755185029Spjd if (flags & FIGNORECASE) 1756185029Spjd zf |= ZCILOOK; 1757185029Spjd 1758185029Spjd if (vap->va_mask & AT_XVATTR) 1759185029Spjd if ((error = secpolicy_xvattr((xvattr_t *)vap, 1760185029Spjd crgetuid(cr), cr, vap->va_type)) != 0) { 1761185029Spjd ZFS_EXIT(zfsvfs); 1762185029Spjd return (error); 1763185029Spjd } 1764185029Spjd 1765168404Spjd /* 1766168404Spjd * First make sure the new directory doesn't exist. 1767168404Spjd */ 1768185029Spjdtop: 1769185029Spjd *vpp = NULL; 1770185029Spjd 1771185029Spjd if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, zf, 1772185029Spjd NULL, NULL)) { 1773168404Spjd ZFS_EXIT(zfsvfs); 1774168404Spjd return (error); 1775168404Spjd } 1776168404Spjd 1777185029Spjd if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr)) { 1778168404Spjd zfs_dirent_unlock(dl); 1779168404Spjd ZFS_EXIT(zfsvfs); 1780168404Spjd return (error); 1781168404Spjd } 1782168404Spjd 1783185029Spjd if (vsecp && aclp == NULL) { 1784185029Spjd error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, &aclp); 1785185029Spjd if (error) { 1786185029Spjd zfs_dirent_unlock(dl); 1787185029Spjd ZFS_EXIT(zfsvfs); 1788185029Spjd return (error); 1789185029Spjd } 1790185029Spjd } 1791168404Spjd /* 1792168404Spjd * Add a new entry to the directory. 1793168404Spjd */ 1794168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1795168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname); 1796168404Spjd dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 1797185029Spjd if ((aclp && aclp->z_has_fuids) || IS_EPHEMERAL(crgetuid(cr)) || 1798185029Spjd IS_EPHEMERAL(crgetgid(cr))) { 1799185029Spjd if (zfsvfs->z_fuid_obj == 0) { 1800185029Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1801185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 1802185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 1803185029Spjd dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 1804185029Spjd } else { 1805185029Spjd dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 1806185029Spjd dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 1807185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 1808185029Spjd } 1809185029Spjd } 1810185029Spjd if ((dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) || aclp) 1811168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1812168404Spjd 0, SPA_MAXBLOCKSIZE); 1813168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1814168404Spjd if (error) { 1815168404Spjd zfs_dirent_unlock(dl); 1816168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1817168404Spjd dmu_tx_wait(tx); 1818168404Spjd dmu_tx_abort(tx); 1819168404Spjd goto top; 1820168404Spjd } 1821168404Spjd dmu_tx_abort(tx); 1822168404Spjd ZFS_EXIT(zfsvfs); 1823185029Spjd if (aclp) 1824185029Spjd zfs_acl_free(aclp); 1825168404Spjd return (error); 1826168404Spjd } 1827168404Spjd 1828168404Spjd /* 1829168404Spjd * Create new node. 1830168404Spjd */ 1831185029Spjd zfs_mknode(dzp, vap, tx, cr, 0, &zp, 0, aclp, &fuidp); 1832168404Spjd 1833185029Spjd if (aclp) 1834185029Spjd zfs_acl_free(aclp); 1835185029Spjd 1836168404Spjd /* 1837168404Spjd * Now put new name in parent dir. 1838168404Spjd */ 1839168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1840168404Spjd 1841168404Spjd *vpp = ZTOV(zp); 1842168404Spjd 1843185029Spjd txtype = zfs_log_create_txtype(Z_DIR, vsecp, vap); 1844185029Spjd if (flags & FIGNORECASE) 1845185029Spjd txtype |= TX_CI; 1846185029Spjd zfs_log_create(zilog, tx, txtype, dzp, zp, dirname, vsecp, fuidp, vap); 1847185029Spjd 1848185029Spjd if (fuidp) 1849185029Spjd zfs_fuid_info_free(fuidp); 1850168404Spjd dmu_tx_commit(tx); 1851168404Spjd 1852168404Spjd zfs_dirent_unlock(dl); 1853168404Spjd 1854168404Spjd ZFS_EXIT(zfsvfs); 1855168404Spjd return (0); 1856168404Spjd} 1857168404Spjd 1858168404Spjd/* 1859168404Spjd * Remove a directory subdir entry. If the current working 1860168404Spjd * directory is the same as the subdir to be removed, the 1861168404Spjd * remove will fail. 1862168404Spjd * 1863168404Spjd * IN: dvp - vnode of directory to remove from. 1864168404Spjd * name - name of directory to be removed. 1865168404Spjd * cwd - vnode of current working directory. 1866168404Spjd * cr - credentials of caller. 1867185029Spjd * ct - caller context 1868185029Spjd * flags - case flags 1869168404Spjd * 1870168404Spjd * RETURN: 0 if success 1871168404Spjd * error code if failure 1872168404Spjd * 1873168404Spjd * Timestamps: 1874168404Spjd * dvp - ctime|mtime updated 1875168404Spjd */ 1876185029Spjd/*ARGSUSED*/ 1877168404Spjdstatic int 1878185029Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, 1879185029Spjd caller_context_t *ct, int flags) 1880168404Spjd{ 1881168404Spjd znode_t *dzp = VTOZ(dvp); 1882168404Spjd znode_t *zp; 1883168404Spjd vnode_t *vp; 1884168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1885185029Spjd zilog_t *zilog; 1886168404Spjd zfs_dirlock_t *dl; 1887168404Spjd dmu_tx_t *tx; 1888168404Spjd int error; 1889185029Spjd int zflg = ZEXISTS; 1890168404Spjd 1891168962Spjd ZFS_ENTER(zfsvfs); 1892185029Spjd ZFS_VERIFY_ZP(dzp); 1893185029Spjd zilog = zfsvfs->z_log; 1894168404Spjd 1895185029Spjd if (flags & FIGNORECASE) 1896185029Spjd zflg |= ZCILOOK; 1897168404Spjdtop: 1898168404Spjd zp = NULL; 1899168404Spjd 1900168404Spjd /* 1901168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1902168404Spjd */ 1903185029Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, 1904185029Spjd NULL, NULL)) { 1905168404Spjd ZFS_EXIT(zfsvfs); 1906168404Spjd return (error); 1907168404Spjd } 1908168404Spjd 1909168404Spjd vp = ZTOV(zp); 1910168404Spjd 1911168404Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1912168404Spjd goto out; 1913168404Spjd } 1914168404Spjd 1915168962Spjd if (vp->v_type != VDIR) { 1916168962Spjd error = ENOTDIR; 1917168962Spjd goto out; 1918168962Spjd } 1919168962Spjd 1920168962Spjd if (vp == cwd) { 1921168962Spjd error = EINVAL; 1922168962Spjd goto out; 1923168962Spjd } 1924168962Spjd 1925185029Spjd vnevent_rmdir(vp, dvp, name, ct); 1926168962Spjd 1927168404Spjd /* 1928168404Spjd * Grab a lock on the directory to make sure that noone is 1929168404Spjd * trying to add (or lookup) entries while we are removing it. 1930168404Spjd */ 1931168404Spjd rw_enter(&zp->z_name_lock, RW_WRITER); 1932168404Spjd 1933168404Spjd /* 1934168404Spjd * Grab a lock on the parent pointer to make sure we play well 1935168404Spjd * with the treewalk and directory rename code. 1936168404Spjd */ 1937168404Spjd rw_enter(&zp->z_parent_lock, RW_WRITER); 1938168404Spjd 1939168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1940168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1941168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1942168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1943168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1944168404Spjd if (error) { 1945168404Spjd rw_exit(&zp->z_parent_lock); 1946168404Spjd rw_exit(&zp->z_name_lock); 1947168404Spjd zfs_dirent_unlock(dl); 1948168962Spjd VN_RELE(vp); 1949168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1950168404Spjd dmu_tx_wait(tx); 1951168404Spjd dmu_tx_abort(tx); 1952168404Spjd goto top; 1953168404Spjd } 1954168404Spjd dmu_tx_abort(tx); 1955168404Spjd ZFS_EXIT(zfsvfs); 1956168404Spjd return (error); 1957168404Spjd } 1958168404Spjd 1959168404Spjd#ifdef FREEBSD_NAMECACHE 1960168404Spjd cache_purge(dvp); 1961168404Spjd#endif 1962168404Spjd 1963185029Spjd error = zfs_link_destroy(dl, zp, tx, zflg, NULL); 1964168404Spjd 1965185029Spjd if (error == 0) { 1966185029Spjd uint64_t txtype = TX_RMDIR; 1967185029Spjd if (flags & FIGNORECASE) 1968185029Spjd txtype |= TX_CI; 1969185029Spjd zfs_log_remove(zilog, tx, txtype, dzp, name); 1970185029Spjd } 1971168404Spjd 1972168404Spjd dmu_tx_commit(tx); 1973168404Spjd 1974168404Spjd rw_exit(&zp->z_parent_lock); 1975168404Spjd rw_exit(&zp->z_name_lock); 1976168404Spjd#ifdef FREEBSD_NAMECACHE 1977168404Spjd cache_purge(vp); 1978168404Spjd#endif 1979168404Spjdout: 1980168404Spjd zfs_dirent_unlock(dl); 1981168404Spjd 1982168962Spjd VN_RELE(vp); 1983168962Spjd 1984168404Spjd ZFS_EXIT(zfsvfs); 1985168404Spjd return (error); 1986168404Spjd} 1987168404Spjd 1988168404Spjd/* 1989168404Spjd * Read as many directory entries as will fit into the provided 1990168404Spjd * buffer from the given directory cursor position (specified in 1991168404Spjd * the uio structure. 1992168404Spjd * 1993168404Spjd * IN: vp - vnode of directory to read. 1994168404Spjd * uio - structure supplying read location, range info, 1995168404Spjd * and return buffer. 1996168404Spjd * cr - credentials of caller. 1997185029Spjd * ct - caller context 1998185029Spjd * flags - case flags 1999168404Spjd * 2000168404Spjd * OUT: uio - updated offset and range, buffer filled. 2001168404Spjd * eofp - set to true if end-of-file detected. 2002168404Spjd * 2003168404Spjd * RETURN: 0 if success 2004168404Spjd * error code if failure 2005168404Spjd * 2006168404Spjd * Timestamps: 2007168404Spjd * vp - atime updated 2008168404Spjd * 2009168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero. 2010168404Spjd * This allows us to use the low range for "special" directory entries: 2011168404Spjd * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, 2012168404Spjd * we use the offset 2 for the '.zfs' directory. 2013168404Spjd */ 2014168404Spjd/* ARGSUSED */ 2015168404Spjdstatic int 2016168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies) 2017168404Spjd{ 2018168404Spjd znode_t *zp = VTOZ(vp); 2019168404Spjd iovec_t *iovp; 2020185029Spjd edirent_t *eodp; 2021168404Spjd dirent64_t *odp; 2022168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2023168404Spjd objset_t *os; 2024168404Spjd caddr_t outbuf; 2025168404Spjd size_t bufsize; 2026168404Spjd zap_cursor_t zc; 2027168404Spjd zap_attribute_t zap; 2028168404Spjd uint_t bytes_wanted; 2029168404Spjd uint64_t offset; /* must be unsigned; checks for < 1 */ 2030168404Spjd int local_eof; 2031168404Spjd int outcount; 2032168404Spjd int error; 2033168404Spjd uint8_t prefetch; 2034185029Spjd boolean_t check_sysattrs; 2035168404Spjd uint8_t type; 2036168962Spjd int ncooks; 2037168962Spjd u_long *cooks = NULL; 2038185029Spjd int flags = 0; 2039168404Spjd 2040168404Spjd ZFS_ENTER(zfsvfs); 2041185029Spjd ZFS_VERIFY_ZP(zp); 2042168404Spjd 2043168404Spjd /* 2044168404Spjd * If we are not given an eof variable, 2045168404Spjd * use a local one. 2046168404Spjd */ 2047168404Spjd if (eofp == NULL) 2048168404Spjd eofp = &local_eof; 2049168404Spjd 2050168404Spjd /* 2051168404Spjd * Check for valid iov_len. 2052168404Spjd */ 2053168404Spjd if (uio->uio_iov->iov_len <= 0) { 2054168404Spjd ZFS_EXIT(zfsvfs); 2055168404Spjd return (EINVAL); 2056168404Spjd } 2057168404Spjd 2058168404Spjd /* 2059168404Spjd * Quit if directory has been removed (posix) 2060168404Spjd */ 2061168404Spjd if ((*eofp = zp->z_unlinked) != 0) { 2062168404Spjd ZFS_EXIT(zfsvfs); 2063168404Spjd return (0); 2064168404Spjd } 2065168404Spjd 2066168404Spjd error = 0; 2067168404Spjd os = zfsvfs->z_os; 2068168404Spjd offset = uio->uio_loffset; 2069168404Spjd prefetch = zp->z_zn_prefetch; 2070168404Spjd 2071168404Spjd /* 2072168404Spjd * Initialize the iterator cursor. 2073168404Spjd */ 2074168404Spjd if (offset <= 3) { 2075168404Spjd /* 2076168404Spjd * Start iteration from the beginning of the directory. 2077168404Spjd */ 2078168404Spjd zap_cursor_init(&zc, os, zp->z_id); 2079168404Spjd } else { 2080168404Spjd /* 2081168404Spjd * The offset is a serialized cursor. 2082168404Spjd */ 2083168404Spjd zap_cursor_init_serialized(&zc, os, zp->z_id, offset); 2084168404Spjd } 2085168404Spjd 2086168404Spjd /* 2087168404Spjd * Get space to change directory entries into fs independent format. 2088168404Spjd */ 2089168404Spjd iovp = uio->uio_iov; 2090168404Spjd bytes_wanted = iovp->iov_len; 2091168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { 2092168404Spjd bufsize = bytes_wanted; 2093168404Spjd outbuf = kmem_alloc(bufsize, KM_SLEEP); 2094168404Spjd odp = (struct dirent64 *)outbuf; 2095168404Spjd } else { 2096168404Spjd bufsize = bytes_wanted; 2097168404Spjd odp = (struct dirent64 *)iovp->iov_base; 2098168404Spjd } 2099185029Spjd eodp = (struct edirent *)odp; 2100168404Spjd 2101169170Spjd if (ncookies != NULL) { 2102168404Spjd /* 2103168404Spjd * Minimum entry size is dirent size and 1 byte for a file name. 2104168404Spjd */ 2105168962Spjd ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1); 2106168962Spjd cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK); 2107169170Spjd *cookies = cooks; 2108168962Spjd *ncookies = ncooks; 2109168404Spjd } 2110185029Spjd /* 2111185029Spjd * If this VFS supports the system attribute view interface; and 2112185029Spjd * we're looking at an extended attribute directory; and we care 2113185029Spjd * about normalization conflicts on this vfs; then we must check 2114185029Spjd * for normalization conflicts with the sysattr name space. 2115185029Spjd */ 2116185029Spjd#ifdef TODO 2117185029Spjd check_sysattrs = vfs_has_feature(vp->v_vfsp, VFSFT_SYSATTR_VIEWS) && 2118185029Spjd (vp->v_flag & V_XATTRDIR) && zfsvfs->z_norm && 2119185029Spjd (flags & V_RDDIR_ENTFLAGS); 2120185029Spjd#else 2121185029Spjd check_sysattrs = 0; 2122185029Spjd#endif 2123168404Spjd 2124168404Spjd /* 2125168404Spjd * Transform to file-system independent format 2126168404Spjd */ 2127168404Spjd outcount = 0; 2128168404Spjd while (outcount < bytes_wanted) { 2129168404Spjd ino64_t objnum; 2130168404Spjd ushort_t reclen; 2131185029Spjd off64_t *next; 2132168404Spjd 2133168404Spjd /* 2134168404Spjd * Special case `.', `..', and `.zfs'. 2135168404Spjd */ 2136168404Spjd if (offset == 0) { 2137168404Spjd (void) strcpy(zap.za_name, "."); 2138185029Spjd zap.za_normalization_conflict = 0; 2139168404Spjd objnum = zp->z_id; 2140169108Spjd type = DT_DIR; 2141168404Spjd } else if (offset == 1) { 2142168404Spjd (void) strcpy(zap.za_name, ".."); 2143185029Spjd zap.za_normalization_conflict = 0; 2144168404Spjd objnum = zp->z_phys->zp_parent; 2145169108Spjd type = DT_DIR; 2146168404Spjd } else if (offset == 2 && zfs_show_ctldir(zp)) { 2147168404Spjd (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME); 2148185029Spjd zap.za_normalization_conflict = 0; 2149168404Spjd objnum = ZFSCTL_INO_ROOT; 2150169108Spjd type = DT_DIR; 2151168404Spjd } else { 2152168404Spjd /* 2153168404Spjd * Grab next entry. 2154168404Spjd */ 2155168404Spjd if (error = zap_cursor_retrieve(&zc, &zap)) { 2156168404Spjd if ((*eofp = (error == ENOENT)) != 0) 2157168404Spjd break; 2158168404Spjd else 2159168404Spjd goto update; 2160168404Spjd } 2161168404Spjd 2162168404Spjd if (zap.za_integer_length != 8 || 2163168404Spjd zap.za_num_integers != 1) { 2164168404Spjd cmn_err(CE_WARN, "zap_readdir: bad directory " 2165168404Spjd "entry, obj = %lld, offset = %lld\n", 2166168404Spjd (u_longlong_t)zp->z_id, 2167168404Spjd (u_longlong_t)offset); 2168168404Spjd error = ENXIO; 2169168404Spjd goto update; 2170168404Spjd } 2171168404Spjd 2172168404Spjd objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); 2173168404Spjd /* 2174168404Spjd * MacOS X can extract the object type here such as: 2175168404Spjd * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer); 2176168404Spjd */ 2177168404Spjd type = ZFS_DIRENT_TYPE(zap.za_first_integer); 2178185029Spjd 2179185029Spjd if (check_sysattrs && !zap.za_normalization_conflict) { 2180185029Spjd#ifdef TODO 2181185029Spjd zap.za_normalization_conflict = 2182185029Spjd xattr_sysattr_casechk(zap.za_name); 2183185029Spjd#else 2184185029Spjd panic("%s:%u: TODO", __func__, __LINE__); 2185185029Spjd#endif 2186185029Spjd } 2187168404Spjd } 2188168404Spjd 2189185029Spjd if (flags & V_RDDIR_ENTFLAGS) 2190185029Spjd reclen = EDIRENT_RECLEN(strlen(zap.za_name)); 2191185029Spjd else 2192185029Spjd reclen = DIRENT64_RECLEN(strlen(zap.za_name)); 2193185029Spjd 2194168404Spjd /* 2195168404Spjd * Will this entry fit in the buffer? 2196168404Spjd */ 2197168404Spjd if (outcount + reclen > bufsize) { 2198168404Spjd /* 2199168404Spjd * Did we manage to fit anything in the buffer? 2200168404Spjd */ 2201168404Spjd if (!outcount) { 2202168404Spjd error = EINVAL; 2203168404Spjd goto update; 2204168404Spjd } 2205168404Spjd break; 2206168404Spjd } 2207185029Spjd if (flags & V_RDDIR_ENTFLAGS) { 2208185029Spjd /* 2209185029Spjd * Add extended flag entry: 2210185029Spjd */ 2211185029Spjd eodp->ed_ino = objnum; 2212185029Spjd eodp->ed_reclen = reclen; 2213185029Spjd /* NOTE: ed_off is the offset for the *next* entry */ 2214185029Spjd next = &(eodp->ed_off); 2215185029Spjd eodp->ed_eflags = zap.za_normalization_conflict ? 2216185029Spjd ED_CASE_CONFLICT : 0; 2217185029Spjd (void) strncpy(eodp->ed_name, zap.za_name, 2218185029Spjd EDIRENT_NAMELEN(reclen)); 2219185029Spjd eodp = (edirent_t *)((intptr_t)eodp + reclen); 2220185029Spjd } else { 2221185029Spjd /* 2222185029Spjd * Add normal entry: 2223185029Spjd */ 2224185029Spjd odp->d_ino = objnum; 2225185029Spjd odp->d_reclen = reclen; 2226185029Spjd odp->d_namlen = strlen(zap.za_name); 2227185029Spjd (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); 2228185029Spjd odp->d_type = type; 2229185029Spjd odp = (dirent64_t *)((intptr_t)odp + reclen); 2230185029Spjd } 2231168404Spjd outcount += reclen; 2232168404Spjd 2233168404Spjd ASSERT(outcount <= bufsize); 2234168404Spjd 2235168404Spjd /* Prefetch znode */ 2236168404Spjd if (prefetch) 2237168404Spjd dmu_prefetch(os, objnum, 0, 0); 2238168404Spjd 2239168404Spjd /* 2240168404Spjd * Move to the next entry, fill in the previous offset. 2241168404Spjd */ 2242168404Spjd if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) { 2243168404Spjd zap_cursor_advance(&zc); 2244168404Spjd offset = zap_cursor_serialize(&zc); 2245168404Spjd } else { 2246168404Spjd offset += 1; 2247168404Spjd } 2248168404Spjd 2249168962Spjd if (cooks != NULL) { 2250168962Spjd *cooks++ = offset; 2251168962Spjd ncooks--; 2252168962Spjd KASSERT(ncooks >= 0, ("ncookies=%d", ncooks)); 2253168404Spjd } 2254168404Spjd } 2255168404Spjd zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ 2256168404Spjd 2257168404Spjd /* Subtract unused cookies */ 2258168962Spjd if (ncookies != NULL) 2259168962Spjd *ncookies -= ncooks; 2260168404Spjd 2261168404Spjd if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { 2262168404Spjd iovp->iov_base += outcount; 2263168404Spjd iovp->iov_len -= outcount; 2264168404Spjd uio->uio_resid -= outcount; 2265168404Spjd } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) { 2266168404Spjd /* 2267168404Spjd * Reset the pointer. 2268168404Spjd */ 2269168404Spjd offset = uio->uio_loffset; 2270168404Spjd } 2271168404Spjd 2272168404Spjdupdate: 2273168404Spjd zap_cursor_fini(&zc); 2274168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 2275168404Spjd kmem_free(outbuf, bufsize); 2276168404Spjd 2277168404Spjd if (error == ENOENT) 2278168404Spjd error = 0; 2279168404Spjd 2280168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 2281168404Spjd 2282168404Spjd uio->uio_loffset = offset; 2283168404Spjd ZFS_EXIT(zfsvfs); 2284169107Spjd if (error != 0 && cookies != NULL) { 2285168962Spjd free(*cookies, M_TEMP); 2286168962Spjd *cookies = NULL; 2287168962Spjd *ncookies = 0; 2288168404Spjd } 2289168404Spjd return (error); 2290168404Spjd} 2291168404Spjd 2292185029Spjdulong_t zfs_fsync_sync_cnt = 4; 2293185029Spjd 2294168404Spjdstatic int 2295185029Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 2296168404Spjd{ 2297168962Spjd znode_t *zp = VTOZ(vp); 2298168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2299168404Spjd 2300185029Spjd (void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt); 2301185029Spjd 2302168404Spjd ZFS_ENTER(zfsvfs); 2303185029Spjd ZFS_VERIFY_ZP(zp); 2304168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 2305168404Spjd ZFS_EXIT(zfsvfs); 2306168404Spjd return (0); 2307168404Spjd} 2308168404Spjd 2309185029Spjd 2310168404Spjd/* 2311168404Spjd * Get the requested file attributes and place them in the provided 2312168404Spjd * vattr structure. 2313168404Spjd * 2314168404Spjd * IN: vp - vnode of file. 2315168404Spjd * vap - va_mask identifies requested attributes. 2316185029Spjd * If AT_XVATTR set, then optional attrs are requested 2317185029Spjd * flags - ATTR_NOACLCHECK (CIFS server context) 2318168404Spjd * cr - credentials of caller. 2319185029Spjd * ct - caller context 2320168404Spjd * 2321168404Spjd * OUT: vap - attribute values. 2322168404Spjd * 2323168404Spjd * RETURN: 0 (always succeeds) 2324168404Spjd */ 2325168404Spjd/* ARGSUSED */ 2326168404Spjdstatic int 2327185029Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 2328185029Spjd caller_context_t *ct) 2329168404Spjd{ 2330168962Spjd znode_t *zp = VTOZ(vp); 2331168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2332185029Spjd znode_phys_t *pzp; 2333185029Spjd int error = 0; 2334168962Spjd uint32_t blksize; 2335168962Spjd u_longlong_t nblocks; 2336185029Spjd uint64_t links; 2337185029Spjd xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ 2338185029Spjd xoptattr_t *xoap = NULL; 2339185029Spjd boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; 2340168404Spjd 2341168404Spjd ZFS_ENTER(zfsvfs); 2342185029Spjd ZFS_VERIFY_ZP(zp); 2343185029Spjd pzp = zp->z_phys; 2344168404Spjd 2345185029Spjd mutex_enter(&zp->z_lock); 2346185029Spjd 2347168404Spjd /* 2348185029Spjd * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES. 2349185029Spjd * Also, if we are the owner don't bother, since owner should 2350185029Spjd * always be allowed to read basic attributes of file. 2351185029Spjd */ 2352185029Spjd if (!(pzp->zp_flags & ZFS_ACL_TRIVIAL) && 2353185029Spjd (pzp->zp_uid != crgetuid(cr))) { 2354185029Spjd if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0, 2355185029Spjd skipaclchk, cr)) { 2356185029Spjd mutex_exit(&zp->z_lock); 2357185029Spjd ZFS_EXIT(zfsvfs); 2358185029Spjd return (error); 2359185029Spjd } 2360185029Spjd } 2361185029Spjd 2362185029Spjd /* 2363168404Spjd * Return all attributes. It's cheaper to provide the answer 2364168404Spjd * than to determine whether we were asked the question. 2365168404Spjd */ 2366168404Spjd 2367168404Spjd vap->va_type = IFTOVT(pzp->zp_mode); 2368168404Spjd vap->va_mode = pzp->zp_mode & ~S_IFMT; 2369185029Spjd zfs_fuid_map_ids(zp, cr, &vap->va_uid, &vap->va_gid); 2370185029Spjd// vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev; 2371168404Spjd vap->va_nodeid = zp->z_id; 2372185029Spjd if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp)) 2373185029Spjd links = pzp->zp_links + 1; 2374185029Spjd else 2375185029Spjd links = pzp->zp_links; 2376185029Spjd vap->va_nlink = MIN(links, UINT32_MAX); /* nlink_t limit! */ 2377168404Spjd vap->va_size = pzp->zp_size; 2378168404Spjd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 2379168958Spjd vap->va_rdev = zfs_cmpldev(pzp->zp_rdev); 2380168404Spjd vap->va_seq = zp->z_seq; 2381168404Spjd vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */ 2382168404Spjd 2383185029Spjd /* 2384185029Spjd * Add in any requested optional attributes and the create time. 2385185029Spjd * Also set the corresponding bits in the returned attribute bitmap. 2386185029Spjd */ 2387185029Spjd if ((xoap = xva_getxoptattr(xvap)) != NULL && zfsvfs->z_use_fuids) { 2388185029Spjd if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 2389185029Spjd xoap->xoa_archive = 2390185029Spjd ((pzp->zp_flags & ZFS_ARCHIVE) != 0); 2391185029Spjd XVA_SET_RTN(xvap, XAT_ARCHIVE); 2392185029Spjd } 2393185029Spjd 2394185029Spjd if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 2395185029Spjd xoap->xoa_readonly = 2396185029Spjd ((pzp->zp_flags & ZFS_READONLY) != 0); 2397185029Spjd XVA_SET_RTN(xvap, XAT_READONLY); 2398185029Spjd } 2399185029Spjd 2400185029Spjd if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 2401185029Spjd xoap->xoa_system = 2402185029Spjd ((pzp->zp_flags & ZFS_SYSTEM) != 0); 2403185029Spjd XVA_SET_RTN(xvap, XAT_SYSTEM); 2404185029Spjd } 2405185029Spjd 2406185029Spjd if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 2407185029Spjd xoap->xoa_hidden = 2408185029Spjd ((pzp->zp_flags & ZFS_HIDDEN) != 0); 2409185029Spjd XVA_SET_RTN(xvap, XAT_HIDDEN); 2410185029Spjd } 2411185029Spjd 2412185029Spjd if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { 2413185029Spjd xoap->xoa_nounlink = 2414185029Spjd ((pzp->zp_flags & ZFS_NOUNLINK) != 0); 2415185029Spjd XVA_SET_RTN(xvap, XAT_NOUNLINK); 2416185029Spjd } 2417185029Spjd 2418185029Spjd if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { 2419185029Spjd xoap->xoa_immutable = 2420185029Spjd ((pzp->zp_flags & ZFS_IMMUTABLE) != 0); 2421185029Spjd XVA_SET_RTN(xvap, XAT_IMMUTABLE); 2422185029Spjd } 2423185029Spjd 2424185029Spjd if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { 2425185029Spjd xoap->xoa_appendonly = 2426185029Spjd ((pzp->zp_flags & ZFS_APPENDONLY) != 0); 2427185029Spjd XVA_SET_RTN(xvap, XAT_APPENDONLY); 2428185029Spjd } 2429185029Spjd 2430185029Spjd if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { 2431185029Spjd xoap->xoa_nodump = 2432185029Spjd ((pzp->zp_flags & ZFS_NODUMP) != 0); 2433185029Spjd XVA_SET_RTN(xvap, XAT_NODUMP); 2434185029Spjd } 2435185029Spjd 2436185029Spjd if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { 2437185029Spjd xoap->xoa_opaque = 2438185029Spjd ((pzp->zp_flags & ZFS_OPAQUE) != 0); 2439185029Spjd XVA_SET_RTN(xvap, XAT_OPAQUE); 2440185029Spjd } 2441185029Spjd 2442185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { 2443185029Spjd xoap->xoa_av_quarantined = 2444185029Spjd ((pzp->zp_flags & ZFS_AV_QUARANTINED) != 0); 2445185029Spjd XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); 2446185029Spjd } 2447185029Spjd 2448185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { 2449185029Spjd xoap->xoa_av_modified = 2450185029Spjd ((pzp->zp_flags & ZFS_AV_MODIFIED) != 0); 2451185029Spjd XVA_SET_RTN(xvap, XAT_AV_MODIFIED); 2452185029Spjd } 2453185029Spjd 2454185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) && 2455185029Spjd vp->v_type == VREG && 2456185029Spjd (pzp->zp_flags & ZFS_BONUS_SCANSTAMP)) { 2457185029Spjd size_t len; 2458185029Spjd dmu_object_info_t doi; 2459185029Spjd 2460185029Spjd /* 2461185029Spjd * Only VREG files have anti-virus scanstamps, so we 2462185029Spjd * won't conflict with symlinks in the bonus buffer. 2463185029Spjd */ 2464185029Spjd dmu_object_info_from_db(zp->z_dbuf, &doi); 2465185029Spjd len = sizeof (xoap->xoa_av_scanstamp) + 2466185029Spjd sizeof (znode_phys_t); 2467185029Spjd if (len <= doi.doi_bonus_size) { 2468185029Spjd /* 2469185029Spjd * pzp points to the start of the 2470185029Spjd * znode_phys_t. pzp + 1 points to the 2471185029Spjd * first byte after the znode_phys_t. 2472185029Spjd */ 2473185029Spjd (void) memcpy(xoap->xoa_av_scanstamp, 2474185029Spjd pzp + 1, 2475185029Spjd sizeof (xoap->xoa_av_scanstamp)); 2476185029Spjd XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP); 2477185029Spjd } 2478185029Spjd } 2479185029Spjd 2480185029Spjd if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { 2481185029Spjd ZFS_TIME_DECODE(&xoap->xoa_createtime, pzp->zp_crtime); 2482185029Spjd XVA_SET_RTN(xvap, XAT_CREATETIME); 2483185029Spjd } 2484185029Spjd } 2485185029Spjd 2486168404Spjd ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime); 2487168404Spjd ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime); 2488168404Spjd ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime); 2489168404Spjd ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime); 2490168404Spjd 2491168404Spjd mutex_exit(&zp->z_lock); 2492168404Spjd 2493168404Spjd dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks); 2494168404Spjd vap->va_blksize = blksize; 2495168404Spjd vap->va_bytes = nblocks << 9; /* nblocks * 512 */ 2496168404Spjd 2497168404Spjd if (zp->z_blksz == 0) { 2498168404Spjd /* 2499168404Spjd * Block size hasn't been set; suggest maximal I/O transfers. 2500168404Spjd */ 2501168404Spjd vap->va_blksize = zfsvfs->z_max_blksz; 2502168404Spjd } 2503168404Spjd 2504168404Spjd ZFS_EXIT(zfsvfs); 2505168404Spjd return (0); 2506168404Spjd} 2507168404Spjd 2508168404Spjd/* 2509168404Spjd * Set the file attributes to the values contained in the 2510168404Spjd * vattr structure. 2511168404Spjd * 2512168404Spjd * IN: vp - vnode of file to be modified. 2513168404Spjd * vap - new attribute values. 2514185029Spjd * If AT_XVATTR set, then optional attrs are being set 2515168404Spjd * flags - ATTR_UTIME set if non-default time values provided. 2516185029Spjd * - ATTR_NOACLCHECK (CIFS context only). 2517168404Spjd * cr - credentials of caller. 2518185029Spjd * ct - caller context 2519168404Spjd * 2520168404Spjd * RETURN: 0 if success 2521168404Spjd * error code if failure 2522168404Spjd * 2523168404Spjd * Timestamps: 2524168404Spjd * vp - ctime updated, mtime updated if size changed. 2525168404Spjd */ 2526168404Spjd/* ARGSUSED */ 2527168404Spjdstatic int 2528168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 2529168962Spjd caller_context_t *ct) 2530168404Spjd{ 2531185029Spjd znode_t *zp = VTOZ(vp); 2532185029Spjd znode_phys_t *pzp; 2533168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2534185029Spjd zilog_t *zilog; 2535168404Spjd dmu_tx_t *tx; 2536168404Spjd vattr_t oldva; 2537168962Spjd uint_t mask = vap->va_mask; 2538168404Spjd uint_t saved_mask; 2539168404Spjd int trim_mask = 0; 2540168404Spjd uint64_t new_mode; 2541168404Spjd znode_t *attrzp; 2542168404Spjd int need_policy = FALSE; 2543168404Spjd int err; 2544185029Spjd zfs_fuid_info_t *fuidp = NULL; 2545185029Spjd xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ 2546185029Spjd xoptattr_t *xoap; 2547185029Spjd zfs_acl_t *aclp = NULL; 2548185029Spjd boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; 2549168404Spjd 2550168404Spjd if (mask == 0) 2551168404Spjd return (0); 2552168404Spjd 2553168962Spjd if (mask & AT_NOSET) 2554168962Spjd return (EINVAL); 2555168962Spjd 2556185029Spjd ZFS_ENTER(zfsvfs); 2557185029Spjd ZFS_VERIFY_ZP(zp); 2558185029Spjd 2559185029Spjd pzp = zp->z_phys; 2560185029Spjd zilog = zfsvfs->z_log; 2561185029Spjd 2562185029Spjd /* 2563185029Spjd * Make sure that if we have ephemeral uid/gid or xvattr specified 2564185029Spjd * that file system is at proper version level 2565185029Spjd */ 2566185029Spjd 2567185029Spjd if (zfsvfs->z_use_fuids == B_FALSE && 2568185029Spjd (((mask & AT_UID) && IS_EPHEMERAL(vap->va_uid)) || 2569185029Spjd ((mask & AT_GID) && IS_EPHEMERAL(vap->va_gid)) || 2570185029Spjd (mask & AT_XVATTR))) { 2571185029Spjd ZFS_EXIT(zfsvfs); 2572185029Spjd return (EINVAL); 2573185029Spjd } 2574185029Spjd 2575185029Spjd if (mask & AT_SIZE && vp->v_type == VDIR) { 2576185029Spjd ZFS_EXIT(zfsvfs); 2577168404Spjd return (EISDIR); 2578185029Spjd } 2579168404Spjd 2580185029Spjd if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) { 2581185029Spjd ZFS_EXIT(zfsvfs); 2582168404Spjd return (EINVAL); 2583185029Spjd } 2584168404Spjd 2585185029Spjd /* 2586185029Spjd * If this is an xvattr_t, then get a pointer to the structure of 2587185029Spjd * optional attributes. If this is NULL, then we have a vattr_t. 2588185029Spjd */ 2589185029Spjd xoap = xva_getxoptattr(xvap); 2590168404Spjd 2591185029Spjd /* 2592185029Spjd * Immutable files can only alter immutable bit and atime 2593185029Spjd */ 2594185029Spjd if ((pzp->zp_flags & ZFS_IMMUTABLE) && 2595185029Spjd ((mask & (AT_SIZE|AT_UID|AT_GID|AT_MTIME|AT_MODE)) || 2596185029Spjd ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) { 2597185029Spjd ZFS_EXIT(zfsvfs); 2598185029Spjd return (EPERM); 2599185029Spjd } 2600185029Spjd 2601185029Spjd if ((mask & AT_SIZE) && (pzp->zp_flags & ZFS_READONLY)) { 2602185029Spjd ZFS_EXIT(zfsvfs); 2603185029Spjd return (EPERM); 2604185029Spjd } 2605185029Spjd 2606185029Spjd /* 2607185029Spjd * Verify timestamps doesn't overflow 32 bits. 2608185029Spjd * ZFS can handle large timestamps, but 32bit syscalls can't 2609185029Spjd * handle times greater than 2039. This check should be removed 2610185029Spjd * once large timestamps are fully supported. 2611185029Spjd */ 2612185029Spjd if (mask & (AT_ATIME | AT_MTIME)) { 2613185029Spjd if (((mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) || 2614185029Spjd ((mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) { 2615185029Spjd ZFS_EXIT(zfsvfs); 2616185029Spjd return (EOVERFLOW); 2617185029Spjd } 2618185029Spjd } 2619185029Spjd 2620168404Spjdtop: 2621168404Spjd attrzp = NULL; 2622168404Spjd 2623168404Spjd if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { 2624168404Spjd ZFS_EXIT(zfsvfs); 2625168404Spjd return (EROFS); 2626168404Spjd } 2627168404Spjd 2628168404Spjd /* 2629168404Spjd * First validate permissions 2630168404Spjd */ 2631168404Spjd 2632168404Spjd if (mask & AT_SIZE) { 2633185029Spjd err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr); 2634168404Spjd if (err) { 2635168404Spjd ZFS_EXIT(zfsvfs); 2636168404Spjd return (err); 2637168404Spjd } 2638168404Spjd /* 2639168404Spjd * XXX - Note, we are not providing any open 2640168404Spjd * mode flags here (like FNDELAY), so we may 2641168404Spjd * block if there are locks present... this 2642168404Spjd * should be addressed in openat(). 2643168404Spjd */ 2644185029Spjd /* XXX - would it be OK to generate a log record here? */ 2645185029Spjd err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); 2646168404Spjd if (err) { 2647168404Spjd ZFS_EXIT(zfsvfs); 2648168404Spjd return (err); 2649168404Spjd } 2650168404Spjd } 2651168404Spjd 2652185029Spjd if (mask & (AT_ATIME|AT_MTIME) || 2653185029Spjd ((mask & AT_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) || 2654185029Spjd XVA_ISSET_REQ(xvap, XAT_READONLY) || 2655185029Spjd XVA_ISSET_REQ(xvap, XAT_ARCHIVE) || 2656185029Spjd XVA_ISSET_REQ(xvap, XAT_CREATETIME) || 2657185029Spjd XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) 2658185029Spjd need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, 2659185029Spjd skipaclchk, cr); 2660168404Spjd 2661168404Spjd if (mask & (AT_UID|AT_GID)) { 2662168404Spjd int idmask = (mask & (AT_UID|AT_GID)); 2663168404Spjd int take_owner; 2664168404Spjd int take_group; 2665168404Spjd 2666168404Spjd /* 2667168404Spjd * NOTE: even if a new mode is being set, 2668168404Spjd * we may clear S_ISUID/S_ISGID bits. 2669168404Spjd */ 2670168404Spjd 2671168404Spjd if (!(mask & AT_MODE)) 2672168404Spjd vap->va_mode = pzp->zp_mode; 2673168404Spjd 2674168404Spjd /* 2675168404Spjd * Take ownership or chgrp to group we are a member of 2676168404Spjd */ 2677168404Spjd 2678168404Spjd take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr)); 2679185029Spjd take_group = (mask & AT_GID) && 2680185029Spjd zfs_groupmember(zfsvfs, vap->va_gid, cr); 2681168404Spjd 2682168404Spjd /* 2683168404Spjd * If both AT_UID and AT_GID are set then take_owner and 2684168404Spjd * take_group must both be set in order to allow taking 2685168404Spjd * ownership. 2686168404Spjd * 2687168404Spjd * Otherwise, send the check through secpolicy_vnode_setattr() 2688168404Spjd * 2689168404Spjd */ 2690168404Spjd 2691168404Spjd if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) || 2692168404Spjd ((idmask == AT_UID) && take_owner) || 2693168404Spjd ((idmask == AT_GID) && take_group)) { 2694185029Spjd if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, 2695185029Spjd skipaclchk, cr) == 0) { 2696168404Spjd /* 2697168404Spjd * Remove setuid/setgid for non-privileged users 2698168404Spjd */ 2699185029Spjd secpolicy_setid_clear(vap, vp, cr); 2700168404Spjd trim_mask = (mask & (AT_UID|AT_GID)); 2701168404Spjd } else { 2702168404Spjd need_policy = TRUE; 2703168404Spjd } 2704168404Spjd } else { 2705168404Spjd need_policy = TRUE; 2706168404Spjd } 2707168404Spjd } 2708168404Spjd 2709168404Spjd mutex_enter(&zp->z_lock); 2710168404Spjd oldva.va_mode = pzp->zp_mode; 2711185029Spjd zfs_fuid_map_ids(zp, cr, &oldva.va_uid, &oldva.va_gid); 2712185029Spjd if (mask & AT_XVATTR) { 2713185029Spjd if ((need_policy == FALSE) && 2714185029Spjd (XVA_ISSET_REQ(xvap, XAT_APPENDONLY) && 2715185029Spjd xoap->xoa_appendonly != 2716185029Spjd ((pzp->zp_flags & ZFS_APPENDONLY) != 0)) || 2717185029Spjd (XVA_ISSET_REQ(xvap, XAT_NOUNLINK) && 2718185029Spjd xoap->xoa_nounlink != 2719185029Spjd ((pzp->zp_flags & ZFS_NOUNLINK) != 0)) || 2720185029Spjd (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE) && 2721185029Spjd xoap->xoa_immutable != 2722185029Spjd ((pzp->zp_flags & ZFS_IMMUTABLE) != 0)) || 2723185029Spjd (XVA_ISSET_REQ(xvap, XAT_NODUMP) && 2724185029Spjd xoap->xoa_nodump != 2725185029Spjd ((pzp->zp_flags & ZFS_NODUMP) != 0)) || 2726185029Spjd (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED) && 2727185029Spjd xoap->xoa_av_modified != 2728185029Spjd ((pzp->zp_flags & ZFS_AV_MODIFIED) != 0)) || 2729185029Spjd ((XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED) && 2730185029Spjd ((vp->v_type != VREG && xoap->xoa_av_quarantined) || 2731185029Spjd xoap->xoa_av_quarantined != 2732185029Spjd ((pzp->zp_flags & ZFS_AV_QUARANTINED) != 0)))) || 2733185029Spjd (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) || 2734185029Spjd (XVA_ISSET_REQ(xvap, XAT_OPAQUE))) { 2735185029Spjd need_policy = TRUE; 2736185029Spjd } 2737185029Spjd } 2738185029Spjd 2739168404Spjd mutex_exit(&zp->z_lock); 2740168404Spjd 2741168404Spjd if (mask & AT_MODE) { 2742185029Spjd if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { 2743168962Spjd err = secpolicy_setid_setsticky_clear(vp, vap, 2744168962Spjd &oldva, cr); 2745168962Spjd if (err) { 2746168962Spjd ZFS_EXIT(zfsvfs); 2747168962Spjd return (err); 2748168962Spjd } 2749168404Spjd trim_mask |= AT_MODE; 2750168404Spjd } else { 2751168404Spjd need_policy = TRUE; 2752168404Spjd } 2753168404Spjd } 2754168404Spjd 2755168404Spjd if (need_policy) { 2756168404Spjd /* 2757168404Spjd * If trim_mask is set then take ownership 2758168404Spjd * has been granted or write_acl is present and user 2759168404Spjd * has the ability to modify mode. In that case remove 2760168404Spjd * UID|GID and or MODE from mask so that 2761168404Spjd * secpolicy_vnode_setattr() doesn't revoke it. 2762168404Spjd */ 2763168404Spjd 2764168404Spjd if (trim_mask) { 2765168404Spjd saved_mask = vap->va_mask; 2766168404Spjd vap->va_mask &= ~trim_mask; 2767168404Spjd } 2768168404Spjd err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 2769185029Spjd (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp); 2770168404Spjd if (err) { 2771168404Spjd ZFS_EXIT(zfsvfs); 2772168404Spjd return (err); 2773168404Spjd } 2774168404Spjd 2775168404Spjd if (trim_mask) 2776168404Spjd vap->va_mask |= saved_mask; 2777168404Spjd } 2778168404Spjd 2779168404Spjd /* 2780168404Spjd * secpolicy_vnode_setattr, or take ownership may have 2781168404Spjd * changed va_mask 2782168404Spjd */ 2783168404Spjd mask = vap->va_mask; 2784168404Spjd 2785168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2786168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2787185029Spjd if (((mask & AT_UID) && IS_EPHEMERAL(vap->va_uid)) || 2788185029Spjd ((mask & AT_GID) && IS_EPHEMERAL(vap->va_gid))) { 2789185029Spjd if (zfsvfs->z_fuid_obj == 0) { 2790185029Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 2791185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 2792185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 2793185029Spjd dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 2794185029Spjd } else { 2795185029Spjd dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 2796185029Spjd dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 2797185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 2798185029Spjd } 2799185029Spjd } 2800168404Spjd 2801168404Spjd if (mask & AT_MODE) { 2802168404Spjd uint64_t pmode = pzp->zp_mode; 2803168404Spjd 2804168404Spjd new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); 2805168404Spjd 2806185029Spjd if (err = zfs_acl_chmod_setattr(zp, &aclp, new_mode)) { 2807185029Spjd dmu_tx_abort(tx); 2808185029Spjd ZFS_EXIT(zfsvfs); 2809185029Spjd return (err); 2810185029Spjd } 2811185029Spjd if (pzp->zp_acl.z_acl_extern_obj) { 2812185029Spjd /* Are we upgrading ACL from old V0 format to new V1 */ 2813185029Spjd if (zfsvfs->z_version <= ZPL_VERSION_FUID && 2814185029Spjd pzp->zp_acl.z_acl_version == 2815185029Spjd ZFS_ACL_VERSION_INITIAL) { 2816185029Spjd dmu_tx_hold_free(tx, 2817185029Spjd pzp->zp_acl.z_acl_extern_obj, 0, 2818185029Spjd DMU_OBJECT_END); 2819185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2820185029Spjd 0, aclp->z_acl_bytes); 2821185029Spjd } else { 2822185029Spjd dmu_tx_hold_write(tx, 2823185029Spjd pzp->zp_acl.z_acl_extern_obj, 0, 2824185029Spjd aclp->z_acl_bytes); 2825185029Spjd } 2826185029Spjd } else if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 2827168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2828185029Spjd 0, aclp->z_acl_bytes); 2829185029Spjd } 2830168404Spjd } 2831168404Spjd 2832185029Spjd if ((mask & (AT_UID | AT_GID)) && pzp->zp_xattr != 0) { 2833185029Spjd err = zfs_zget(zp->z_zfsvfs, pzp->zp_xattr, &attrzp); 2834168404Spjd if (err) { 2835168404Spjd dmu_tx_abort(tx); 2836168404Spjd ZFS_EXIT(zfsvfs); 2837185029Spjd if (aclp) 2838185029Spjd zfs_acl_free(aclp); 2839168404Spjd return (err); 2840168404Spjd } 2841168404Spjd dmu_tx_hold_bonus(tx, attrzp->z_id); 2842168404Spjd } 2843168404Spjd 2844168404Spjd err = dmu_tx_assign(tx, zfsvfs->z_assign); 2845168404Spjd if (err) { 2846168404Spjd if (attrzp) 2847168404Spjd VN_RELE(ZTOV(attrzp)); 2848185029Spjd 2849185029Spjd if (aclp) { 2850185029Spjd zfs_acl_free(aclp); 2851185029Spjd aclp = NULL; 2852185029Spjd } 2853185029Spjd 2854168404Spjd if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2855168404Spjd dmu_tx_wait(tx); 2856168404Spjd dmu_tx_abort(tx); 2857168404Spjd goto top; 2858168404Spjd } 2859168404Spjd dmu_tx_abort(tx); 2860168404Spjd ZFS_EXIT(zfsvfs); 2861168404Spjd return (err); 2862168404Spjd } 2863168404Spjd 2864168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2865168404Spjd 2866168404Spjd /* 2867168404Spjd * Set each attribute requested. 2868168404Spjd * We group settings according to the locks they need to acquire. 2869168404Spjd * 2870168404Spjd * Note: you cannot set ctime directly, although it will be 2871168404Spjd * updated as a side-effect of calling this function. 2872168404Spjd */ 2873168404Spjd 2874168404Spjd mutex_enter(&zp->z_lock); 2875168404Spjd 2876168404Spjd if (mask & AT_MODE) { 2877185029Spjd mutex_enter(&zp->z_acl_lock); 2878185029Spjd zp->z_phys->zp_mode = new_mode; 2879185029Spjd err = zfs_aclset_common(zp, aclp, cr, &fuidp, tx); 2880168404Spjd ASSERT3U(err, ==, 0); 2881185029Spjd mutex_exit(&zp->z_acl_lock); 2882168404Spjd } 2883168404Spjd 2884168404Spjd if (attrzp) 2885168404Spjd mutex_enter(&attrzp->z_lock); 2886168404Spjd 2887168404Spjd if (mask & AT_UID) { 2888185029Spjd pzp->zp_uid = zfs_fuid_create(zfsvfs, 2889185029Spjd vap->va_uid, cr, ZFS_OWNER, tx, &fuidp); 2890168404Spjd if (attrzp) { 2891185029Spjd attrzp->z_phys->zp_uid = zfs_fuid_create(zfsvfs, 2892185029Spjd vap->va_uid, cr, ZFS_OWNER, tx, &fuidp); 2893168404Spjd } 2894168404Spjd } 2895168404Spjd 2896168404Spjd if (mask & AT_GID) { 2897185029Spjd pzp->zp_gid = zfs_fuid_create(zfsvfs, vap->va_gid, 2898185029Spjd cr, ZFS_GROUP, tx, &fuidp); 2899168404Spjd if (attrzp) 2900185029Spjd attrzp->z_phys->zp_gid = zfs_fuid_create(zfsvfs, 2901185029Spjd vap->va_gid, cr, ZFS_GROUP, tx, &fuidp); 2902168404Spjd } 2903168404Spjd 2904185029Spjd if (aclp) 2905185029Spjd zfs_acl_free(aclp); 2906185029Spjd 2907168404Spjd if (attrzp) 2908168404Spjd mutex_exit(&attrzp->z_lock); 2909168404Spjd 2910168404Spjd if (mask & AT_ATIME) 2911168404Spjd ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); 2912168404Spjd 2913168404Spjd if (mask & AT_MTIME) 2914168404Spjd ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime); 2915168404Spjd 2916185029Spjd /* XXX - shouldn't this be done *before* the ATIME/MTIME checks? */ 2917168404Spjd if (mask & AT_SIZE) 2918168404Spjd zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx); 2919168404Spjd else if (mask != 0) 2920168404Spjd zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 2921185029Spjd /* 2922185029Spjd * Do this after setting timestamps to prevent timestamp 2923185029Spjd * update from toggling bit 2924185029Spjd */ 2925168404Spjd 2926185029Spjd if (xoap && (mask & AT_XVATTR)) { 2927185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { 2928185029Spjd size_t len; 2929185029Spjd dmu_object_info_t doi; 2930185029Spjd 2931185029Spjd ASSERT(vp->v_type == VREG); 2932185029Spjd 2933185029Spjd /* Grow the bonus buffer if necessary. */ 2934185029Spjd dmu_object_info_from_db(zp->z_dbuf, &doi); 2935185029Spjd len = sizeof (xoap->xoa_av_scanstamp) + 2936185029Spjd sizeof (znode_phys_t); 2937185029Spjd if (len > doi.doi_bonus_size) 2938185029Spjd VERIFY(dmu_set_bonus(zp->z_dbuf, len, tx) == 0); 2939185029Spjd } 2940185029Spjd zfs_xvattr_set(zp, xvap); 2941185029Spjd } 2942185029Spjd 2943168404Spjd if (mask != 0) 2944185029Spjd zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp); 2945168404Spjd 2946185029Spjd if (fuidp) 2947185029Spjd zfs_fuid_info_free(fuidp); 2948168404Spjd mutex_exit(&zp->z_lock); 2949168404Spjd 2950168404Spjd if (attrzp) 2951168404Spjd VN_RELE(ZTOV(attrzp)); 2952168404Spjd 2953168404Spjd dmu_tx_commit(tx); 2954168404Spjd 2955168404Spjd ZFS_EXIT(zfsvfs); 2956168404Spjd return (err); 2957168404Spjd} 2958168404Spjd 2959168404Spjdtypedef struct zfs_zlock { 2960168404Spjd krwlock_t *zl_rwlock; /* lock we acquired */ 2961168404Spjd znode_t *zl_znode; /* znode we held */ 2962168404Spjd struct zfs_zlock *zl_next; /* next in list */ 2963168404Spjd} zfs_zlock_t; 2964168404Spjd 2965168404Spjd/* 2966168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock(). 2967168404Spjd */ 2968168404Spjdstatic void 2969168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp) 2970168404Spjd{ 2971168404Spjd zfs_zlock_t *zl; 2972168404Spjd 2973168404Spjd while ((zl = *zlpp) != NULL) { 2974168404Spjd if (zl->zl_znode != NULL) 2975168404Spjd VN_RELE(ZTOV(zl->zl_znode)); 2976168404Spjd rw_exit(zl->zl_rwlock); 2977168404Spjd *zlpp = zl->zl_next; 2978168404Spjd kmem_free(zl, sizeof (*zl)); 2979168404Spjd } 2980168404Spjd} 2981168404Spjd 2982168404Spjd/* 2983168404Spjd * Search back through the directory tree, using the ".." entries. 2984168404Spjd * Lock each directory in the chain to prevent concurrent renames. 2985168404Spjd * Fail any attempt to move a directory into one of its own descendants. 2986168404Spjd * XXX - z_parent_lock can overlap with map or grow locks 2987168404Spjd */ 2988168404Spjdstatic int 2989168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) 2990168404Spjd{ 2991168404Spjd zfs_zlock_t *zl; 2992168404Spjd znode_t *zp = tdzp; 2993168404Spjd uint64_t rootid = zp->z_zfsvfs->z_root; 2994168404Spjd uint64_t *oidp = &zp->z_id; 2995168404Spjd krwlock_t *rwlp = &szp->z_parent_lock; 2996168404Spjd krw_t rw = RW_WRITER; 2997168404Spjd 2998168404Spjd /* 2999168404Spjd * First pass write-locks szp and compares to zp->z_id. 3000168404Spjd * Later passes read-lock zp and compare to zp->z_parent. 3001168404Spjd */ 3002168404Spjd do { 3003168404Spjd if (!rw_tryenter(rwlp, rw)) { 3004168404Spjd /* 3005168404Spjd * Another thread is renaming in this path. 3006168404Spjd * Note that if we are a WRITER, we don't have any 3007168404Spjd * parent_locks held yet. 3008168404Spjd */ 3009168404Spjd if (rw == RW_READER && zp->z_id > szp->z_id) { 3010168404Spjd /* 3011168404Spjd * Drop our locks and restart 3012168404Spjd */ 3013168404Spjd zfs_rename_unlock(&zl); 3014168404Spjd *zlpp = NULL; 3015168404Spjd zp = tdzp; 3016168404Spjd oidp = &zp->z_id; 3017168404Spjd rwlp = &szp->z_parent_lock; 3018168404Spjd rw = RW_WRITER; 3019168404Spjd continue; 3020168404Spjd } else { 3021168404Spjd /* 3022168404Spjd * Wait for other thread to drop its locks 3023168404Spjd */ 3024168404Spjd rw_enter(rwlp, rw); 3025168404Spjd } 3026168404Spjd } 3027168404Spjd 3028168404Spjd zl = kmem_alloc(sizeof (*zl), KM_SLEEP); 3029168404Spjd zl->zl_rwlock = rwlp; 3030168404Spjd zl->zl_znode = NULL; 3031168404Spjd zl->zl_next = *zlpp; 3032168404Spjd *zlpp = zl; 3033168404Spjd 3034168404Spjd if (*oidp == szp->z_id) /* We're a descendant of szp */ 3035168404Spjd return (EINVAL); 3036168404Spjd 3037168404Spjd if (*oidp == rootid) /* We've hit the top */ 3038168404Spjd return (0); 3039168404Spjd 3040168404Spjd if (rw == RW_READER) { /* i.e. not the first pass */ 3041168404Spjd int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp); 3042168404Spjd if (error) 3043168404Spjd return (error); 3044168404Spjd zl->zl_znode = zp; 3045168404Spjd } 3046168404Spjd oidp = &zp->z_phys->zp_parent; 3047168404Spjd rwlp = &zp->z_parent_lock; 3048168404Spjd rw = RW_READER; 3049168404Spjd 3050168404Spjd } while (zp->z_id != sdzp->z_id); 3051168404Spjd 3052168404Spjd return (0); 3053168404Spjd} 3054168404Spjd 3055168404Spjd/* 3056168404Spjd * Move an entry from the provided source directory to the target 3057168404Spjd * directory. Change the entry name as indicated. 3058168404Spjd * 3059168404Spjd * IN: sdvp - Source directory containing the "old entry". 3060168404Spjd * snm - Old entry name. 3061168404Spjd * tdvp - Target directory to contain the "new entry". 3062168404Spjd * tnm - New entry name. 3063168404Spjd * cr - credentials of caller. 3064185029Spjd * ct - caller context 3065185029Spjd * flags - case flags 3066168404Spjd * 3067168404Spjd * RETURN: 0 if success 3068168404Spjd * error code if failure 3069168404Spjd * 3070168404Spjd * Timestamps: 3071168404Spjd * sdvp,tdvp - ctime|mtime updated 3072168404Spjd */ 3073185029Spjd/*ARGSUSED*/ 3074168404Spjdstatic int 3075185029Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, 3076185029Spjd caller_context_t *ct, int flags) 3077168404Spjd{ 3078168404Spjd znode_t *tdzp, *szp, *tzp; 3079168404Spjd znode_t *sdzp = VTOZ(sdvp); 3080168404Spjd zfsvfs_t *zfsvfs = sdzp->z_zfsvfs; 3081185029Spjd zilog_t *zilog; 3082168962Spjd vnode_t *realvp; 3083168404Spjd zfs_dirlock_t *sdl, *tdl; 3084168404Spjd dmu_tx_t *tx; 3085168404Spjd zfs_zlock_t *zl; 3086185029Spjd int cmp, serr, terr; 3087185029Spjd int error = 0; 3088185029Spjd int zflg = 0; 3089168404Spjd 3090168404Spjd ZFS_ENTER(zfsvfs); 3091185029Spjd ZFS_VERIFY_ZP(sdzp); 3092185029Spjd zilog = zfsvfs->z_log; 3093168404Spjd 3094168962Spjd /* 3095168962Spjd * Make sure we have the real vp for the target directory. 3096168962Spjd */ 3097185029Spjd if (VOP_REALVP(tdvp, &realvp, ct) == 0) 3098168962Spjd tdvp = realvp; 3099168962Spjd 3100168404Spjd if (tdvp->v_vfsp != sdvp->v_vfsp) { 3101168404Spjd ZFS_EXIT(zfsvfs); 3102168962Spjd return (EXDEV); 3103168404Spjd } 3104168404Spjd 3105168404Spjd tdzp = VTOZ(tdvp); 3106185029Spjd ZFS_VERIFY_ZP(tdzp); 3107185029Spjd if (zfsvfs->z_utf8 && u8_validate(tnm, 3108185029Spjd strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 3109185029Spjd ZFS_EXIT(zfsvfs); 3110185029Spjd return (EILSEQ); 3111185029Spjd } 3112185029Spjd 3113185029Spjd if (flags & FIGNORECASE) 3114185029Spjd zflg |= ZCILOOK; 3115185029Spjd 3116168404Spjdtop: 3117168404Spjd szp = NULL; 3118168404Spjd tzp = NULL; 3119168404Spjd zl = NULL; 3120168404Spjd 3121168404Spjd /* 3122168404Spjd * This is to prevent the creation of links into attribute space 3123168404Spjd * by renaming a linked file into/outof an attribute directory. 3124168404Spjd * See the comment in zfs_link() for why this is considered bad. 3125168404Spjd */ 3126168404Spjd if ((tdzp->z_phys->zp_flags & ZFS_XATTR) != 3127168404Spjd (sdzp->z_phys->zp_flags & ZFS_XATTR)) { 3128168962Spjd ZFS_EXIT(zfsvfs); 3129168962Spjd return (EINVAL); 3130168404Spjd } 3131168404Spjd 3132168404Spjd /* 3133168404Spjd * Lock source and target directory entries. To prevent deadlock, 3134168404Spjd * a lock ordering must be defined. We lock the directory with 3135168404Spjd * the smallest object id first, or if it's a tie, the one with 3136168404Spjd * the lexically first name. 3137168404Spjd */ 3138168404Spjd if (sdzp->z_id < tdzp->z_id) { 3139168962Spjd cmp = -1; 3140168962Spjd } else if (sdzp->z_id > tdzp->z_id) { 3141168962Spjd cmp = 1; 3142168962Spjd } else { 3143185029Spjd /* 3144185029Spjd * First compare the two name arguments without 3145185029Spjd * considering any case folding. 3146185029Spjd */ 3147185029Spjd int nofold = (zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER); 3148185029Spjd 3149185029Spjd cmp = u8_strcmp(snm, tnm, 0, nofold, U8_UNICODE_LATEST, &error); 3150185029Spjd ASSERT(error == 0 || !zfsvfs->z_utf8); 3151168962Spjd if (cmp == 0) { 3152168962Spjd /* 3153168962Spjd * POSIX: "If the old argument and the new argument 3154168962Spjd * both refer to links to the same existing file, 3155168962Spjd * the rename() function shall return successfully 3156168962Spjd * and perform no other action." 3157168962Spjd */ 3158168962Spjd ZFS_EXIT(zfsvfs); 3159168962Spjd return (0); 3160168962Spjd } 3161185029Spjd /* 3162185029Spjd * If the file system is case-folding, then we may 3163185029Spjd * have some more checking to do. A case-folding file 3164185029Spjd * system is either supporting mixed case sensitivity 3165185029Spjd * access or is completely case-insensitive. Note 3166185029Spjd * that the file system is always case preserving. 3167185029Spjd * 3168185029Spjd * In mixed sensitivity mode case sensitive behavior 3169185029Spjd * is the default. FIGNORECASE must be used to 3170185029Spjd * explicitly request case insensitive behavior. 3171185029Spjd * 3172185029Spjd * If the source and target names provided differ only 3173185029Spjd * by case (e.g., a request to rename 'tim' to 'Tim'), 3174185029Spjd * we will treat this as a special case in the 3175185029Spjd * case-insensitive mode: as long as the source name 3176185029Spjd * is an exact match, we will allow this to proceed as 3177185029Spjd * a name-change request. 3178185029Spjd */ 3179185029Spjd if ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE || 3180185029Spjd (zfsvfs->z_case == ZFS_CASE_MIXED && 3181185029Spjd flags & FIGNORECASE)) && 3182185029Spjd u8_strcmp(snm, tnm, 0, zfsvfs->z_norm, U8_UNICODE_LATEST, 3183185029Spjd &error) == 0) { 3184185029Spjd /* 3185185029Spjd * case preserving rename request, require exact 3186185029Spjd * name matches 3187185029Spjd */ 3188185029Spjd zflg |= ZCIEXACT; 3189185029Spjd zflg &= ~ZCILOOK; 3190185029Spjd } 3191168962Spjd } 3192185029Spjd 3193168962Spjd if (cmp < 0) { 3194185029Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, 3195185029Spjd ZEXISTS | zflg, NULL, NULL); 3196185029Spjd terr = zfs_dirent_lock(&tdl, 3197185029Spjd tdzp, tnm, &tzp, ZRENAMING | zflg, NULL, NULL); 3198168962Spjd } else { 3199185029Spjd terr = zfs_dirent_lock(&tdl, 3200185029Spjd tdzp, tnm, &tzp, zflg, NULL, NULL); 3201185029Spjd serr = zfs_dirent_lock(&sdl, 3202185029Spjd sdzp, snm, &szp, ZEXISTS | ZRENAMING | zflg, 3203185029Spjd NULL, NULL); 3204168404Spjd } 3205168404Spjd 3206168962Spjd if (serr) { 3207168404Spjd /* 3208168404Spjd * Source entry invalid or not there. 3209168404Spjd */ 3210168962Spjd if (!terr) { 3211168404Spjd zfs_dirent_unlock(tdl); 3212168962Spjd if (tzp) 3213168962Spjd VN_RELE(ZTOV(tzp)); 3214168962Spjd } 3215168404Spjd if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0) 3216168404Spjd serr = EINVAL; 3217168962Spjd ZFS_EXIT(zfsvfs); 3218168962Spjd return (serr); 3219168404Spjd } 3220168404Spjd if (terr) { 3221168404Spjd zfs_dirent_unlock(sdl); 3222168962Spjd VN_RELE(ZTOV(szp)); 3223168404Spjd if (strcmp(tnm, "..") == 0) 3224168404Spjd terr = EINVAL; 3225168962Spjd ZFS_EXIT(zfsvfs); 3226168962Spjd return (terr); 3227168404Spjd } 3228168404Spjd 3229168404Spjd /* 3230168404Spjd * Must have write access at the source to remove the old entry 3231168404Spjd * and write access at the target to create the new entry. 3232168404Spjd * Note that if target and source are the same, this can be 3233168404Spjd * done in a single check. 3234168404Spjd */ 3235168404Spjd 3236168404Spjd if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) 3237168404Spjd goto out; 3238168404Spjd 3239168962Spjd if (ZTOV(szp)->v_type == VDIR) { 3240168404Spjd /* 3241168404Spjd * Check to make sure rename is valid. 3242168404Spjd * Can't do a move like this: /usr/a/b to /usr/a/b/c/d 3243168404Spjd */ 3244168404Spjd if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl)) 3245168404Spjd goto out; 3246168404Spjd } 3247168404Spjd 3248168404Spjd /* 3249168404Spjd * Does target exist? 3250168404Spjd */ 3251168404Spjd if (tzp) { 3252168404Spjd /* 3253168404Spjd * Source and target must be the same type. 3254168404Spjd */ 3255168962Spjd if (ZTOV(szp)->v_type == VDIR) { 3256168962Spjd if (ZTOV(tzp)->v_type != VDIR) { 3257168404Spjd error = ENOTDIR; 3258168404Spjd goto out; 3259168404Spjd } 3260168404Spjd } else { 3261168962Spjd if (ZTOV(tzp)->v_type == VDIR) { 3262168404Spjd error = EISDIR; 3263168404Spjd goto out; 3264168404Spjd } 3265168404Spjd } 3266168404Spjd /* 3267168404Spjd * POSIX dictates that when the source and target 3268168404Spjd * entries refer to the same file object, rename 3269168404Spjd * must do nothing and exit without error. 3270168404Spjd */ 3271168404Spjd if (szp->z_id == tzp->z_id) { 3272168404Spjd error = 0; 3273168404Spjd goto out; 3274168404Spjd } 3275168404Spjd } 3276168404Spjd 3277185029Spjd vnevent_rename_src(ZTOV(szp), sdvp, snm, ct); 3278168962Spjd if (tzp) 3279185029Spjd vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct); 3280168962Spjd 3281185029Spjd /* 3282185029Spjd * notify the target directory if it is not the same 3283185029Spjd * as source directory. 3284185029Spjd */ 3285185029Spjd if (tdvp != sdvp) { 3286185029Spjd vnevent_rename_dest_dir(tdvp, ct); 3287185029Spjd } 3288185029Spjd 3289168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 3290168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); /* nlink changes */ 3291168404Spjd dmu_tx_hold_bonus(tx, sdzp->z_id); /* nlink changes */ 3292168404Spjd dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm); 3293168404Spjd dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm); 3294168404Spjd if (sdzp != tdzp) 3295168404Spjd dmu_tx_hold_bonus(tx, tdzp->z_id); /* nlink changes */ 3296168404Spjd if (tzp) 3297168404Spjd dmu_tx_hold_bonus(tx, tzp->z_id); /* parent changes */ 3298168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 3299168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 3300168404Spjd if (error) { 3301168404Spjd if (zl != NULL) 3302168404Spjd zfs_rename_unlock(&zl); 3303168404Spjd zfs_dirent_unlock(sdl); 3304168404Spjd zfs_dirent_unlock(tdl); 3305168962Spjd VN_RELE(ZTOV(szp)); 3306168962Spjd if (tzp) 3307168962Spjd VN_RELE(ZTOV(tzp)); 3308168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 3309168404Spjd dmu_tx_wait(tx); 3310168404Spjd dmu_tx_abort(tx); 3311168404Spjd goto top; 3312168404Spjd } 3313168404Spjd dmu_tx_abort(tx); 3314168962Spjd ZFS_EXIT(zfsvfs); 3315168962Spjd return (error); 3316168404Spjd } 3317168404Spjd 3318168404Spjd if (tzp) /* Attempt to remove the existing target */ 3319185029Spjd error = zfs_link_destroy(tdl, tzp, tx, zflg, NULL); 3320168404Spjd 3321168404Spjd if (error == 0) { 3322168404Spjd error = zfs_link_create(tdl, szp, tx, ZRENAMING); 3323168404Spjd if (error == 0) { 3324185029Spjd szp->z_phys->zp_flags |= ZFS_AV_MODIFIED; 3325185029Spjd 3326168404Spjd error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL); 3327168404Spjd ASSERT(error == 0); 3328185029Spjd 3329185029Spjd zfs_log_rename(zilog, tx, 3330185029Spjd TX_RENAME | (flags & FIGNORECASE ? TX_CI : 0), 3331185029Spjd sdzp, sdl->dl_name, tdzp, tdl->dl_name, szp); 3332185029Spjd 3333185029Spjd /* Update path information for the target vnode */ 3334185029Spjd vn_renamepath(tdvp, ZTOV(szp), tnm, strlen(tnm)); 3335168404Spjd } 3336168404Spjd#ifdef FREEBSD_NAMECACHE 3337168404Spjd if (error == 0) { 3338168404Spjd cache_purge(sdvp); 3339168404Spjd cache_purge(tdvp); 3340168404Spjd } 3341168404Spjd#endif 3342168404Spjd } 3343168404Spjd 3344168404Spjd dmu_tx_commit(tx); 3345168404Spjdout: 3346168404Spjd if (zl != NULL) 3347168404Spjd zfs_rename_unlock(&zl); 3348168404Spjd 3349168404Spjd zfs_dirent_unlock(sdl); 3350168404Spjd zfs_dirent_unlock(tdl); 3351168404Spjd 3352168962Spjd VN_RELE(ZTOV(szp)); 3353168404Spjd if (tzp) 3354168962Spjd VN_RELE(ZTOV(tzp)); 3355168404Spjd 3356168404Spjd ZFS_EXIT(zfsvfs); 3357168404Spjd 3358168404Spjd return (error); 3359168404Spjd} 3360168404Spjd 3361168404Spjd/* 3362168404Spjd * Insert the indicated symbolic reference entry into the directory. 3363168404Spjd * 3364168404Spjd * IN: dvp - Directory to contain new symbolic link. 3365168404Spjd * link - Name for new symlink entry. 3366168404Spjd * vap - Attributes of new entry. 3367168404Spjd * target - Target path of new symlink. 3368168404Spjd * cr - credentials of caller. 3369185029Spjd * ct - caller context 3370185029Spjd * flags - case flags 3371168404Spjd * 3372168404Spjd * RETURN: 0 if success 3373168404Spjd * error code if failure 3374168404Spjd * 3375168404Spjd * Timestamps: 3376168404Spjd * dvp - ctime|mtime updated 3377168404Spjd */ 3378185029Spjd/*ARGSUSED*/ 3379168404Spjdstatic int 3380185029Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, 3381185029Spjd cred_t *cr, kthread_t *td) 3382168404Spjd{ 3383168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 3384168404Spjd zfs_dirlock_t *dl; 3385168404Spjd dmu_tx_t *tx; 3386168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 3387185029Spjd zilog_t *zilog; 3388168404Spjd int len = strlen(link); 3389168404Spjd int error; 3390185029Spjd int zflg = ZNEW; 3391185029Spjd zfs_fuid_info_t *fuidp = NULL; 3392185029Spjd int flags = 0; 3393168404Spjd 3394168962Spjd ASSERT(vap->va_type == VLNK); 3395168404Spjd 3396168404Spjd ZFS_ENTER(zfsvfs); 3397185029Spjd ZFS_VERIFY_ZP(dzp); 3398185029Spjd zilog = zfsvfs->z_log; 3399185029Spjd 3400185029Spjd if (zfsvfs->z_utf8 && u8_validate(name, strlen(name), 3401185029Spjd NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 3402185029Spjd ZFS_EXIT(zfsvfs); 3403185029Spjd return (EILSEQ); 3404185029Spjd } 3405185029Spjd if (flags & FIGNORECASE) 3406185029Spjd zflg |= ZCILOOK; 3407168404Spjdtop: 3408185029Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { 3409168404Spjd ZFS_EXIT(zfsvfs); 3410168404Spjd return (error); 3411168404Spjd } 3412168404Spjd 3413168404Spjd if (len > MAXPATHLEN) { 3414168404Spjd ZFS_EXIT(zfsvfs); 3415168404Spjd return (ENAMETOOLONG); 3416168404Spjd } 3417168404Spjd 3418168404Spjd /* 3419168404Spjd * Attempt to lock directory; fail if entry already exists. 3420168404Spjd */ 3421185029Spjd error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL); 3422185029Spjd if (error) { 3423168404Spjd ZFS_EXIT(zfsvfs); 3424168404Spjd return (error); 3425168404Spjd } 3426168404Spjd 3427168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 3428168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len)); 3429168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 3430168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 3431168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 3432168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE); 3433185029Spjd if (IS_EPHEMERAL(crgetuid(cr)) || IS_EPHEMERAL(crgetgid(cr))) { 3434185029Spjd if (zfsvfs->z_fuid_obj == 0) { 3435185029Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 3436185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 3437185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 3438185029Spjd dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 3439185029Spjd } else { 3440185029Spjd dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 3441185029Spjd dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 3442185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 3443185029Spjd } 3444185029Spjd } 3445168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 3446168404Spjd if (error) { 3447168404Spjd zfs_dirent_unlock(dl); 3448168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 3449168404Spjd dmu_tx_wait(tx); 3450168404Spjd dmu_tx_abort(tx); 3451168404Spjd goto top; 3452168404Spjd } 3453168404Spjd dmu_tx_abort(tx); 3454168404Spjd ZFS_EXIT(zfsvfs); 3455168404Spjd return (error); 3456168404Spjd } 3457168404Spjd 3458168404Spjd dmu_buf_will_dirty(dzp->z_dbuf, tx); 3459168404Spjd 3460168404Spjd /* 3461168404Spjd * Create a new object for the symlink. 3462168404Spjd * Put the link content into bonus buffer if it will fit; 3463168404Spjd * otherwise, store it just like any other file data. 3464168404Spjd */ 3465168404Spjd if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) { 3466185029Spjd zfs_mknode(dzp, vap, tx, cr, 0, &zp, len, NULL, &fuidp); 3467168404Spjd if (len != 0) 3468168404Spjd bcopy(link, zp->z_phys + 1, len); 3469168404Spjd } else { 3470168404Spjd dmu_buf_t *dbp; 3471168404Spjd 3472185029Spjd zfs_mknode(dzp, vap, tx, cr, 0, &zp, 0, NULL, &fuidp); 3473168404Spjd /* 3474168404Spjd * Nothing can access the znode yet so no locking needed 3475168404Spjd * for growing the znode's blocksize. 3476168404Spjd */ 3477168404Spjd zfs_grow_blocksize(zp, len, tx); 3478168404Spjd 3479185029Spjd VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, 3480185029Spjd zp->z_id, 0, FTAG, &dbp)); 3481168404Spjd dmu_buf_will_dirty(dbp, tx); 3482168404Spjd 3483168404Spjd ASSERT3U(len, <=, dbp->db_size); 3484168404Spjd bcopy(link, dbp->db_data, len); 3485168404Spjd dmu_buf_rele(dbp, FTAG); 3486168404Spjd } 3487168404Spjd zp->z_phys->zp_size = len; 3488168404Spjd 3489168404Spjd /* 3490168404Spjd * Insert the new object into the directory. 3491168404Spjd */ 3492168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 3493168962Spjdout: 3494168404Spjd if (error == 0) { 3495185029Spjd uint64_t txtype = TX_SYMLINK; 3496185029Spjd if (flags & FIGNORECASE) 3497185029Spjd txtype |= TX_CI; 3498185029Spjd zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link); 3499168962Spjd *vpp = ZTOV(zp); 3500168404Spjd } 3501185029Spjd if (fuidp) 3502185029Spjd zfs_fuid_info_free(fuidp); 3503168404Spjd 3504168404Spjd dmu_tx_commit(tx); 3505168404Spjd 3506168404Spjd zfs_dirent_unlock(dl); 3507168404Spjd 3508168404Spjd ZFS_EXIT(zfsvfs); 3509168404Spjd return (error); 3510168404Spjd} 3511168404Spjd 3512168404Spjd/* 3513168404Spjd * Return, in the buffer contained in the provided uio structure, 3514168404Spjd * the symbolic path referred to by vp. 3515168404Spjd * 3516168404Spjd * IN: vp - vnode of symbolic link. 3517168404Spjd * uoip - structure to contain the link path. 3518168404Spjd * cr - credentials of caller. 3519185029Spjd * ct - caller context 3520168404Spjd * 3521168404Spjd * OUT: uio - structure to contain the link path. 3522168404Spjd * 3523168404Spjd * RETURN: 0 if success 3524168404Spjd * error code if failure 3525168404Spjd * 3526168404Spjd * Timestamps: 3527168404Spjd * vp - atime updated 3528168404Spjd */ 3529168404Spjd/* ARGSUSED */ 3530168404Spjdstatic int 3531185029Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct) 3532168404Spjd{ 3533168404Spjd znode_t *zp = VTOZ(vp); 3534168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3535168404Spjd size_t bufsz; 3536168404Spjd int error; 3537168404Spjd 3538168404Spjd ZFS_ENTER(zfsvfs); 3539185029Spjd ZFS_VERIFY_ZP(zp); 3540168404Spjd 3541168404Spjd bufsz = (size_t)zp->z_phys->zp_size; 3542168404Spjd if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) { 3543168404Spjd error = uiomove(zp->z_phys + 1, 3544168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 3545168404Spjd } else { 3546168404Spjd dmu_buf_t *dbp; 3547168404Spjd error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp); 3548168404Spjd if (error) { 3549168404Spjd ZFS_EXIT(zfsvfs); 3550168404Spjd return (error); 3551168404Spjd } 3552168404Spjd error = uiomove(dbp->db_data, 3553168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 3554168404Spjd dmu_buf_rele(dbp, FTAG); 3555168404Spjd } 3556168404Spjd 3557168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 3558168404Spjd ZFS_EXIT(zfsvfs); 3559168404Spjd return (error); 3560168404Spjd} 3561168404Spjd 3562168404Spjd/* 3563168404Spjd * Insert a new entry into directory tdvp referencing svp. 3564168404Spjd * 3565168404Spjd * IN: tdvp - Directory to contain new entry. 3566168404Spjd * svp - vnode of new entry. 3567168404Spjd * name - name of new entry. 3568168404Spjd * cr - credentials of caller. 3569185029Spjd * ct - caller context 3570168404Spjd * 3571168404Spjd * RETURN: 0 if success 3572168404Spjd * error code if failure 3573168404Spjd * 3574168404Spjd * Timestamps: 3575168404Spjd * tdvp - ctime|mtime updated 3576168404Spjd * svp - ctime updated 3577168404Spjd */ 3578168404Spjd/* ARGSUSED */ 3579168404Spjdstatic int 3580185029Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr, 3581185029Spjd caller_context_t *ct, int flags) 3582168404Spjd{ 3583168404Spjd znode_t *dzp = VTOZ(tdvp); 3584168404Spjd znode_t *tzp, *szp; 3585168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 3586185029Spjd zilog_t *zilog; 3587168404Spjd zfs_dirlock_t *dl; 3588168404Spjd dmu_tx_t *tx; 3589168962Spjd vnode_t *realvp; 3590168404Spjd int error; 3591185029Spjd int zf = ZNEW; 3592185029Spjd uid_t owner; 3593168404Spjd 3594168404Spjd ASSERT(tdvp->v_type == VDIR); 3595168404Spjd 3596168404Spjd ZFS_ENTER(zfsvfs); 3597185029Spjd ZFS_VERIFY_ZP(dzp); 3598185029Spjd zilog = zfsvfs->z_log; 3599168404Spjd 3600185029Spjd if (VOP_REALVP(svp, &realvp, ct) == 0) 3601168962Spjd svp = realvp; 3602168962Spjd 3603168404Spjd if (svp->v_vfsp != tdvp->v_vfsp) { 3604168404Spjd ZFS_EXIT(zfsvfs); 3605168404Spjd return (EXDEV); 3606168404Spjd } 3607185029Spjd szp = VTOZ(svp); 3608185029Spjd ZFS_VERIFY_ZP(szp); 3609168404Spjd 3610185029Spjd if (zfsvfs->z_utf8 && u8_validate(name, 3611185029Spjd strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { 3612185029Spjd ZFS_EXIT(zfsvfs); 3613185029Spjd return (EILSEQ); 3614185029Spjd } 3615185029Spjd if (flags & FIGNORECASE) 3616185029Spjd zf |= ZCILOOK; 3617185029Spjd 3618168404Spjdtop: 3619168404Spjd /* 3620168404Spjd * We do not support links between attributes and non-attributes 3621168404Spjd * because of the potential security risk of creating links 3622168404Spjd * into "normal" file space in order to circumvent restrictions 3623168404Spjd * imposed in attribute space. 3624168404Spjd */ 3625168404Spjd if ((szp->z_phys->zp_flags & ZFS_XATTR) != 3626168404Spjd (dzp->z_phys->zp_flags & ZFS_XATTR)) { 3627168404Spjd ZFS_EXIT(zfsvfs); 3628168404Spjd return (EINVAL); 3629168404Spjd } 3630168404Spjd 3631168404Spjd /* 3632168404Spjd * POSIX dictates that we return EPERM here. 3633168404Spjd * Better choices include ENOTSUP or EISDIR. 3634168404Spjd */ 3635168404Spjd if (svp->v_type == VDIR) { 3636168404Spjd ZFS_EXIT(zfsvfs); 3637168404Spjd return (EPERM); 3638168404Spjd } 3639168404Spjd 3640185029Spjd owner = zfs_fuid_map_id(zfsvfs, szp->z_phys->zp_uid, cr, ZFS_OWNER); 3641185029Spjd if (owner != crgetuid(cr) && 3642185029Spjd secpolicy_basic_link(svp, cr) != 0) { 3643168404Spjd ZFS_EXIT(zfsvfs); 3644168404Spjd return (EPERM); 3645168404Spjd } 3646168404Spjd 3647185029Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { 3648168404Spjd ZFS_EXIT(zfsvfs); 3649168404Spjd return (error); 3650168404Spjd } 3651168404Spjd 3652168404Spjd /* 3653168404Spjd * Attempt to lock directory; fail if entry already exists. 3654168404Spjd */ 3655185029Spjd error = zfs_dirent_lock(&dl, dzp, name, &tzp, zf, NULL, NULL); 3656185029Spjd if (error) { 3657168404Spjd ZFS_EXIT(zfsvfs); 3658168404Spjd return (error); 3659168404Spjd } 3660168404Spjd 3661168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 3662168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); 3663168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 3664168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 3665168404Spjd if (error) { 3666168404Spjd zfs_dirent_unlock(dl); 3667168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 3668168404Spjd dmu_tx_wait(tx); 3669168404Spjd dmu_tx_abort(tx); 3670168404Spjd goto top; 3671168404Spjd } 3672168404Spjd dmu_tx_abort(tx); 3673168404Spjd ZFS_EXIT(zfsvfs); 3674168404Spjd return (error); 3675168404Spjd } 3676168404Spjd 3677168404Spjd error = zfs_link_create(dl, szp, tx, 0); 3678168404Spjd 3679185029Spjd if (error == 0) { 3680185029Spjd uint64_t txtype = TX_LINK; 3681185029Spjd if (flags & FIGNORECASE) 3682185029Spjd txtype |= TX_CI; 3683185029Spjd zfs_log_link(zilog, tx, txtype, dzp, szp, name); 3684185029Spjd } 3685168404Spjd 3686168404Spjd dmu_tx_commit(tx); 3687168404Spjd 3688168404Spjd zfs_dirent_unlock(dl); 3689168404Spjd 3690185029Spjd if (error == 0) { 3691185029Spjd vnevent_link(svp, ct); 3692185029Spjd } 3693185029Spjd 3694168404Spjd ZFS_EXIT(zfsvfs); 3695168404Spjd return (error); 3696168404Spjd} 3697168404Spjd 3698185029Spjd/*ARGSUSED*/ 3699168962Spjdvoid 3700185029Spjdzfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 3701168404Spjd{ 3702168962Spjd znode_t *zp = VTOZ(vp); 3703168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3704168962Spjd int error; 3705168404Spjd 3706185029Spjd rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER); 3707185029Spjd if (zp->z_dbuf == NULL) { 3708185029Spjd /* 3709185029Spjd * The fs has been unmounted, or we did a 3710185029Spjd * suspend/resume and this file no longer exists. 3711185029Spjd */ 3712168404Spjd mutex_enter(&zp->z_lock); 3713168404Spjd VI_LOCK(vp); 3714168404Spjd vp->v_count = 0; /* count arrives as 1 */ 3715185029Spjd mutex_exit(&zp->z_lock); 3716185029Spjd rw_exit(&zfsvfs->z_teardown_inactive_lock); 3717185029Spjd zfs_znode_free(zp); 3718168962Spjd return; 3719168404Spjd } 3720168404Spjd 3721168404Spjd if (zp->z_atime_dirty && zp->z_unlinked == 0) { 3722168404Spjd dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 3723168404Spjd 3724168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 3725168404Spjd error = dmu_tx_assign(tx, TXG_WAIT); 3726168404Spjd if (error) { 3727168404Spjd dmu_tx_abort(tx); 3728168404Spjd } else { 3729168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 3730168404Spjd mutex_enter(&zp->z_lock); 3731168404Spjd zp->z_atime_dirty = 0; 3732168404Spjd mutex_exit(&zp->z_lock); 3733168404Spjd dmu_tx_commit(tx); 3734168404Spjd } 3735168404Spjd } 3736168404Spjd 3737168404Spjd zfs_zinactive(zp); 3738185029Spjd rw_exit(&zfsvfs->z_teardown_inactive_lock); 3739168404Spjd} 3740168404Spjd 3741168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid)); 3742168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid)); 3743168404Spjd 3744185029Spjd/*ARGSUSED*/ 3745168404Spjdstatic int 3746185029Spjdzfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct) 3747168404Spjd{ 3748168404Spjd znode_t *zp = VTOZ(vp); 3749168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3750185029Spjd uint32_t gen; 3751168404Spjd uint64_t object = zp->z_id; 3752168404Spjd zfid_short_t *zfid; 3753168404Spjd int size, i; 3754168404Spjd 3755168404Spjd ZFS_ENTER(zfsvfs); 3756185029Spjd ZFS_VERIFY_ZP(zp); 3757185029Spjd gen = (uint32_t)zp->z_gen; 3758168404Spjd 3759168404Spjd size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN; 3760168404Spjd fidp->fid_len = size; 3761168404Spjd 3762168404Spjd zfid = (zfid_short_t *)fidp; 3763168404Spjd 3764168404Spjd zfid->zf_len = size; 3765168404Spjd 3766168404Spjd for (i = 0; i < sizeof (zfid->zf_object); i++) 3767168404Spjd zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 3768168404Spjd 3769168404Spjd /* Must have a non-zero generation number to distinguish from .zfs */ 3770168404Spjd if (gen == 0) 3771168404Spjd gen = 1; 3772168404Spjd for (i = 0; i < sizeof (zfid->zf_gen); i++) 3773168404Spjd zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i)); 3774168404Spjd 3775168404Spjd if (size == LONG_FID_LEN) { 3776168404Spjd uint64_t objsetid = dmu_objset_id(zfsvfs->z_os); 3777169023Spjd zfid_long_t *zlfid; 3778168404Spjd 3779168404Spjd zlfid = (zfid_long_t *)fidp; 3780168404Spjd 3781168404Spjd for (i = 0; i < sizeof (zlfid->zf_setid); i++) 3782168404Spjd zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i)); 3783168404Spjd 3784168404Spjd /* XXX - this should be the generation number for the objset */ 3785168404Spjd for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 3786168404Spjd zlfid->zf_setgen[i] = 0; 3787168404Spjd } 3788168404Spjd 3789168404Spjd ZFS_EXIT(zfsvfs); 3790168404Spjd return (0); 3791168404Spjd} 3792168404Spjd 3793168404Spjdstatic int 3794185029Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 3795185029Spjd caller_context_t *ct) 3796168404Spjd{ 3797168404Spjd znode_t *zp, *xzp; 3798168404Spjd zfsvfs_t *zfsvfs; 3799168404Spjd zfs_dirlock_t *dl; 3800168404Spjd int error; 3801168404Spjd 3802168404Spjd switch (cmd) { 3803168404Spjd case _PC_LINK_MAX: 3804168404Spjd *valp = INT_MAX; 3805168404Spjd return (0); 3806168404Spjd 3807168404Spjd case _PC_FILESIZEBITS: 3808168404Spjd *valp = 64; 3809168404Spjd return (0); 3810168404Spjd 3811168404Spjd#if 0 3812168404Spjd case _PC_XATTR_EXISTS: 3813168404Spjd zp = VTOZ(vp); 3814168404Spjd zfsvfs = zp->z_zfsvfs; 3815168404Spjd ZFS_ENTER(zfsvfs); 3816185029Spjd ZFS_VERIFY_ZP(zp); 3817168404Spjd *valp = 0; 3818168404Spjd error = zfs_dirent_lock(&dl, zp, "", &xzp, 3819185029Spjd ZXATTR | ZEXISTS | ZSHARED, NULL, NULL); 3820168404Spjd if (error == 0) { 3821168404Spjd zfs_dirent_unlock(dl); 3822168404Spjd if (!zfs_dirempty(xzp)) 3823168404Spjd *valp = 1; 3824168404Spjd VN_RELE(ZTOV(xzp)); 3825168404Spjd } else if (error == ENOENT) { 3826168404Spjd /* 3827168404Spjd * If there aren't extended attributes, it's the 3828168404Spjd * same as having zero of them. 3829168404Spjd */ 3830168404Spjd error = 0; 3831168404Spjd } 3832168404Spjd ZFS_EXIT(zfsvfs); 3833168404Spjd return (error); 3834168404Spjd#endif 3835168404Spjd 3836168404Spjd case _PC_ACL_EXTENDED: 3837168404Spjd *valp = 0; /* TODO */ 3838168404Spjd return (0); 3839168404Spjd 3840168404Spjd case _PC_MIN_HOLE_SIZE: 3841168404Spjd *valp = (int)SPA_MINBLOCKSIZE; 3842168404Spjd return (0); 3843168404Spjd 3844168404Spjd default: 3845168962Spjd return (EOPNOTSUPP); 3846168404Spjd } 3847168404Spjd} 3848168404Spjd 3849168404Spjd/*ARGSUSED*/ 3850168404Spjdstatic int 3851185029Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr, 3852185029Spjd caller_context_t *ct) 3853168404Spjd{ 3854168404Spjd znode_t *zp = VTOZ(vp); 3855168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3856168404Spjd int error; 3857185029Spjd boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; 3858168404Spjd 3859168404Spjd ZFS_ENTER(zfsvfs); 3860185029Spjd ZFS_VERIFY_ZP(zp); 3861185029Spjd error = zfs_getacl(zp, vsecp, skipaclchk, cr); 3862168404Spjd ZFS_EXIT(zfsvfs); 3863168404Spjd 3864168404Spjd return (error); 3865168404Spjd} 3866168404Spjd 3867168404Spjd/*ARGSUSED*/ 3868168404Spjdstatic int 3869185029Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr, 3870185029Spjd caller_context_t *ct) 3871168404Spjd{ 3872168404Spjd znode_t *zp = VTOZ(vp); 3873168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3874168404Spjd int error; 3875185029Spjd boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; 3876168404Spjd 3877168404Spjd ZFS_ENTER(zfsvfs); 3878185029Spjd ZFS_VERIFY_ZP(zp); 3879185029Spjd error = zfs_setacl(zp, vsecp, skipaclchk, cr); 3880168404Spjd ZFS_EXIT(zfsvfs); 3881168404Spjd return (error); 3882168404Spjd} 3883168404Spjd 3884168962Spjdstatic int 3885168962Spjdzfs_freebsd_open(ap) 3886168962Spjd struct vop_open_args /* { 3887168962Spjd struct vnode *a_vp; 3888168962Spjd int a_mode; 3889168962Spjd struct ucred *a_cred; 3890168962Spjd struct thread *a_td; 3891168962Spjd } */ *ap; 3892168962Spjd{ 3893168962Spjd vnode_t *vp = ap->a_vp; 3894168962Spjd znode_t *zp = VTOZ(vp); 3895168962Spjd int error; 3896168962Spjd 3897185029Spjd error = zfs_open(&vp, ap->a_mode, ap->a_cred, NULL); 3898168962Spjd if (error == 0) 3899168962Spjd vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); 3900168962Spjd return (error); 3901168962Spjd} 3902168962Spjd 3903168962Spjdstatic int 3904168962Spjdzfs_freebsd_close(ap) 3905168962Spjd struct vop_close_args /* { 3906168962Spjd struct vnode *a_vp; 3907168962Spjd int a_fflag; 3908168962Spjd struct ucred *a_cred; 3909168962Spjd struct thread *a_td; 3910168962Spjd } */ *ap; 3911168962Spjd{ 3912168962Spjd 3913185029Spjd return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred, NULL)); 3914168962Spjd} 3915168962Spjd 3916168962Spjdstatic int 3917168962Spjdzfs_freebsd_ioctl(ap) 3918168962Spjd struct vop_ioctl_args /* { 3919168962Spjd struct vnode *a_vp; 3920168962Spjd u_long a_command; 3921168962Spjd caddr_t a_data; 3922168962Spjd int a_fflag; 3923168962Spjd struct ucred *cred; 3924168962Spjd struct thread *td; 3925168962Spjd } */ *ap; 3926168962Spjd{ 3927168962Spjd 3928168978Spjd return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data, 3929185029Spjd ap->a_fflag, ap->a_cred, NULL, NULL)); 3930168962Spjd} 3931168962Spjd 3932168962Spjdstatic int 3933168962Spjdzfs_freebsd_read(ap) 3934168962Spjd struct vop_read_args /* { 3935168962Spjd struct vnode *a_vp; 3936168962Spjd struct uio *a_uio; 3937168962Spjd int a_ioflag; 3938168962Spjd struct ucred *a_cred; 3939168962Spjd } */ *ap; 3940168962Spjd{ 3941168962Spjd 3942168962Spjd return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3943168962Spjd} 3944168962Spjd 3945168962Spjdstatic int 3946168962Spjdzfs_freebsd_write(ap) 3947168962Spjd struct vop_write_args /* { 3948168962Spjd struct vnode *a_vp; 3949168962Spjd struct uio *a_uio; 3950168962Spjd int a_ioflag; 3951168962Spjd struct ucred *a_cred; 3952168962Spjd } */ *ap; 3953168962Spjd{ 3954168962Spjd 3955168962Spjd return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3956168962Spjd} 3957168962Spjd 3958168962Spjdstatic int 3959168962Spjdzfs_freebsd_access(ap) 3960168962Spjd struct vop_access_args /* { 3961168962Spjd struct vnode *a_vp; 3962192689Strasz accmode_t a_accmode; 3963168962Spjd struct ucred *a_cred; 3964168962Spjd struct thread *a_td; 3965168962Spjd } */ *ap; 3966168962Spjd{ 3967168962Spjd 3968185172Spjd /* 3969185172Spjd * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest 3970185172Spjd * we have to handle by calling vaccess(). 3971185172Spjd */ 3972185172Spjd if ((ap->a_accmode & ~(VREAD|VWRITE|VEXEC)) != 0) { 3973185172Spjd vnode_t *vp = ap->a_vp; 3974185172Spjd znode_t *zp = VTOZ(vp); 3975185172Spjd znode_phys_t *zphys = zp->z_phys; 3976185172Spjd 3977185172Spjd return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid, 3978185172Spjd zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL)); 3979185172Spjd } 3980185172Spjd 3981185029Spjd return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL)); 3982168962Spjd} 3983168962Spjd 3984168962Spjdstatic int 3985168962Spjdzfs_freebsd_lookup(ap) 3986168962Spjd struct vop_lookup_args /* { 3987168962Spjd struct vnode *a_dvp; 3988168962Spjd struct vnode **a_vpp; 3989168962Spjd struct componentname *a_cnp; 3990168962Spjd } */ *ap; 3991168962Spjd{ 3992168962Spjd struct componentname *cnp = ap->a_cnp; 3993168962Spjd char nm[NAME_MAX + 1]; 3994168962Spjd 3995168962Spjd ASSERT(cnp->cn_namelen < sizeof(nm)); 3996168962Spjd strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm))); 3997168962Spjd 3998168962Spjd return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop, 3999185029Spjd cnp->cn_cred, cnp->cn_thread, 0)); 4000168962Spjd} 4001168962Spjd 4002168962Spjdstatic int 4003168962Spjdzfs_freebsd_create(ap) 4004168962Spjd struct vop_create_args /* { 4005168962Spjd struct vnode *a_dvp; 4006168962Spjd struct vnode **a_vpp; 4007168962Spjd struct componentname *a_cnp; 4008168962Spjd struct vattr *a_vap; 4009168962Spjd } */ *ap; 4010168962Spjd{ 4011168962Spjd struct componentname *cnp = ap->a_cnp; 4012168962Spjd vattr_t *vap = ap->a_vap; 4013168962Spjd int mode; 4014168962Spjd 4015168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 4016168962Spjd 4017168962Spjd vattr_init_mask(vap); 4018168962Spjd mode = vap->va_mode & ALLPERMS; 4019168962Spjd 4020168962Spjd return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode, 4021185029Spjd ap->a_vpp, cnp->cn_cred, cnp->cn_thread)); 4022168962Spjd} 4023168962Spjd 4024168962Spjdstatic int 4025168962Spjdzfs_freebsd_remove(ap) 4026168962Spjd struct vop_remove_args /* { 4027168962Spjd struct vnode *a_dvp; 4028168962Spjd struct vnode *a_vp; 4029168962Spjd struct componentname *a_cnp; 4030168962Spjd } */ *ap; 4031168962Spjd{ 4032168962Spjd 4033168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 4034168962Spjd 4035168962Spjd return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr, 4036185029Spjd ap->a_cnp->cn_cred, NULL, 0)); 4037168962Spjd} 4038168962Spjd 4039168962Spjdstatic int 4040168962Spjdzfs_freebsd_mkdir(ap) 4041168962Spjd struct vop_mkdir_args /* { 4042168962Spjd struct vnode *a_dvp; 4043168962Spjd struct vnode **a_vpp; 4044168962Spjd struct componentname *a_cnp; 4045168962Spjd struct vattr *a_vap; 4046168962Spjd } */ *ap; 4047168962Spjd{ 4048168962Spjd vattr_t *vap = ap->a_vap; 4049168962Spjd 4050168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 4051168962Spjd 4052168962Spjd vattr_init_mask(vap); 4053168962Spjd 4054168962Spjd return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp, 4055185029Spjd ap->a_cnp->cn_cred, NULL, 0, NULL)); 4056168962Spjd} 4057168962Spjd 4058168962Spjdstatic int 4059168962Spjdzfs_freebsd_rmdir(ap) 4060168962Spjd struct vop_rmdir_args /* { 4061168962Spjd struct vnode *a_dvp; 4062168962Spjd struct vnode *a_vp; 4063168962Spjd struct componentname *a_cnp; 4064168962Spjd } */ *ap; 4065168962Spjd{ 4066168962Spjd struct componentname *cnp = ap->a_cnp; 4067168962Spjd 4068168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 4069168962Spjd 4070185029Spjd return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred, NULL, 0)); 4071168962Spjd} 4072168962Spjd 4073168962Spjdstatic int 4074168962Spjdzfs_freebsd_readdir(ap) 4075168962Spjd struct vop_readdir_args /* { 4076168962Spjd struct vnode *a_vp; 4077168962Spjd struct uio *a_uio; 4078168962Spjd struct ucred *a_cred; 4079168962Spjd int *a_eofflag; 4080168962Spjd int *a_ncookies; 4081168962Spjd u_long **a_cookies; 4082168962Spjd } */ *ap; 4083168962Spjd{ 4084168962Spjd 4085168962Spjd return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, 4086168962Spjd ap->a_ncookies, ap->a_cookies)); 4087168962Spjd} 4088168962Spjd 4089168962Spjdstatic int 4090168962Spjdzfs_freebsd_fsync(ap) 4091168962Spjd struct vop_fsync_args /* { 4092168962Spjd struct vnode *a_vp; 4093168962Spjd int a_waitfor; 4094168962Spjd struct thread *a_td; 4095168962Spjd } */ *ap; 4096168962Spjd{ 4097168962Spjd 4098168962Spjd vop_stdfsync(ap); 4099185029Spjd return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred, NULL)); 4100168962Spjd} 4101168962Spjd 4102168962Spjdstatic int 4103168962Spjdzfs_freebsd_getattr(ap) 4104168962Spjd struct vop_getattr_args /* { 4105168962Spjd struct vnode *a_vp; 4106168962Spjd struct vattr *a_vap; 4107168962Spjd struct ucred *a_cred; 4108185029Spjd struct thread *a_td; 4109168962Spjd } */ *ap; 4110168962Spjd{ 4111185029Spjd vattr_t *vap = ap->a_vap; 4112185029Spjd xvattr_t xvap; 4113185029Spjd u_long fflags = 0; 4114185029Spjd int error; 4115168962Spjd 4116185029Spjd xva_init(&xvap); 4117185029Spjd xvap.xva_vattr = *vap; 4118185029Spjd xvap.xva_vattr.va_mask |= AT_XVATTR; 4119185029Spjd 4120185029Spjd /* Convert chflags into ZFS-type flags. */ 4121185029Spjd /* XXX: what about SF_SETTABLE?. */ 4122185029Spjd XVA_SET_REQ(&xvap, XAT_IMMUTABLE); 4123185029Spjd XVA_SET_REQ(&xvap, XAT_APPENDONLY); 4124185029Spjd XVA_SET_REQ(&xvap, XAT_NOUNLINK); 4125185029Spjd XVA_SET_REQ(&xvap, XAT_NODUMP); 4126185029Spjd error = zfs_getattr(ap->a_vp, (vattr_t *)&xvap, 0, ap->a_cred, NULL); 4127185029Spjd if (error != 0) 4128185029Spjd return (error); 4129185029Spjd 4130185029Spjd /* Convert ZFS xattr into chflags. */ 4131185029Spjd#define FLAG_CHECK(fflag, xflag, xfield) do { \ 4132185029Spjd if (XVA_ISSET_RTN(&xvap, (xflag)) && (xfield) != 0) \ 4133185029Spjd fflags |= (fflag); \ 4134185029Spjd} while (0) 4135185029Spjd FLAG_CHECK(SF_IMMUTABLE, XAT_IMMUTABLE, 4136185029Spjd xvap.xva_xoptattrs.xoa_immutable); 4137185029Spjd FLAG_CHECK(SF_APPEND, XAT_APPENDONLY, 4138185029Spjd xvap.xva_xoptattrs.xoa_appendonly); 4139185029Spjd FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK, 4140185029Spjd xvap.xva_xoptattrs.xoa_nounlink); 4141185029Spjd FLAG_CHECK(UF_NODUMP, XAT_NODUMP, 4142185029Spjd xvap.xva_xoptattrs.xoa_nodump); 4143185029Spjd#undef FLAG_CHECK 4144185029Spjd *vap = xvap.xva_vattr; 4145185029Spjd vap->va_flags = fflags; 4146185029Spjd return (0); 4147168962Spjd} 4148168962Spjd 4149168962Spjdstatic int 4150168962Spjdzfs_freebsd_setattr(ap) 4151168962Spjd struct vop_setattr_args /* { 4152168962Spjd struct vnode *a_vp; 4153168962Spjd struct vattr *a_vap; 4154168962Spjd struct ucred *a_cred; 4155185029Spjd struct thread *a_td; 4156168962Spjd } */ *ap; 4157168962Spjd{ 4158185172Spjd vnode_t *vp = ap->a_vp; 4159168962Spjd vattr_t *vap = ap->a_vap; 4160185172Spjd cred_t *cred = ap->a_cred; 4161185029Spjd xvattr_t xvap; 4162185029Spjd u_long fflags; 4163185029Spjd uint64_t zflags; 4164168962Spjd 4165168962Spjd vattr_init_mask(vap); 4166170044Spjd vap->va_mask &= ~AT_NOSET; 4167168962Spjd 4168185029Spjd xva_init(&xvap); 4169185029Spjd xvap.xva_vattr = *vap; 4170185029Spjd 4171185172Spjd zflags = VTOZ(vp)->z_phys->zp_flags; 4172185172Spjd 4173185029Spjd if (vap->va_flags != VNOVAL) { 4174185172Spjd int error; 4175185172Spjd 4176185029Spjd fflags = vap->va_flags; 4177185029Spjd if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0) 4178185029Spjd return (EOPNOTSUPP); 4179185172Spjd /* 4180185172Spjd * Callers may only modify the file flags on objects they 4181185172Spjd * have VADMIN rights for. 4182185172Spjd */ 4183185172Spjd if ((error = VOP_ACCESS(vp, VADMIN, cred, curthread)) != 0) 4184185172Spjd return (error); 4185185172Spjd /* 4186185172Spjd * Unprivileged processes are not permitted to unset system 4187185172Spjd * flags, or modify flags if any system flags are set. 4188185172Spjd * Privileged non-jail processes may not modify system flags 4189185172Spjd * if securelevel > 0 and any existing system flags are set. 4190185172Spjd * Privileged jail processes behave like privileged non-jail 4191185172Spjd * processes if the security.jail.chflags_allowed sysctl is 4192185172Spjd * is non-zero; otherwise, they behave like unprivileged 4193185172Spjd * processes. 4194185172Spjd */ 4195185172Spjd if (priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0) == 0) { 4196185172Spjd if (zflags & 4197185172Spjd (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) { 4198185172Spjd error = securelevel_gt(cred, 0); 4199185172Spjd if (error) 4200185172Spjd return (error); 4201185172Spjd } 4202185172Spjd } else { 4203185172Spjd if (zflags & 4204185172Spjd (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) { 4205185172Spjd return (EPERM); 4206185172Spjd } 4207185172Spjd if (fflags & 4208185172Spjd (SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK)) { 4209185172Spjd return (EPERM); 4210185172Spjd } 4211185172Spjd } 4212185029Spjd 4213185029Spjd#define FLAG_CHANGE(fflag, zflag, xflag, xfield) do { \ 4214185029Spjd if (((fflags & (fflag)) && !(zflags & (zflag))) || \ 4215185029Spjd ((zflags & (zflag)) && !(fflags & (fflag)))) { \ 4216185029Spjd XVA_SET_REQ(&xvap, (xflag)); \ 4217185029Spjd (xfield) = ((fflags & (fflag)) != 0); \ 4218185029Spjd } \ 4219185029Spjd} while (0) 4220185029Spjd /* Convert chflags into ZFS-type flags. */ 4221185029Spjd /* XXX: what about SF_SETTABLE?. */ 4222185029Spjd FLAG_CHANGE(SF_IMMUTABLE, ZFS_IMMUTABLE, XAT_IMMUTABLE, 4223185029Spjd xvap.xva_xoptattrs.xoa_immutable); 4224185029Spjd FLAG_CHANGE(SF_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY, 4225185029Spjd xvap.xva_xoptattrs.xoa_appendonly); 4226185029Spjd FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK, 4227185029Spjd xvap.xva_xoptattrs.xoa_nounlink); 4228185029Spjd FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP, 4229185172Spjd xvap.xva_xoptattrs.xoa_nodump); 4230185029Spjd#undef FLAG_CHANGE 4231185029Spjd } 4232185172Spjd return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL)); 4233168962Spjd} 4234168962Spjd 4235168962Spjdstatic int 4236168962Spjdzfs_freebsd_rename(ap) 4237168962Spjd struct vop_rename_args /* { 4238168962Spjd struct vnode *a_fdvp; 4239168962Spjd struct vnode *a_fvp; 4240168962Spjd struct componentname *a_fcnp; 4241168962Spjd struct vnode *a_tdvp; 4242168962Spjd struct vnode *a_tvp; 4243168962Spjd struct componentname *a_tcnp; 4244168962Spjd } */ *ap; 4245168962Spjd{ 4246168962Spjd vnode_t *fdvp = ap->a_fdvp; 4247168962Spjd vnode_t *fvp = ap->a_fvp; 4248168962Spjd vnode_t *tdvp = ap->a_tdvp; 4249168962Spjd vnode_t *tvp = ap->a_tvp; 4250168962Spjd int error; 4251168962Spjd 4252192237Skmacy ASSERT(ap->a_fcnp->cn_flags & (SAVENAME|SAVESTART)); 4253192237Skmacy ASSERT(ap->a_tcnp->cn_flags & (SAVENAME|SAVESTART)); 4254168962Spjd 4255168962Spjd error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp, 4256185029Spjd ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred, NULL, 0); 4257168962Spjd 4258168962Spjd if (tdvp == tvp) 4259168962Spjd VN_RELE(tdvp); 4260168962Spjd else 4261168962Spjd VN_URELE(tdvp); 4262168962Spjd if (tvp) 4263168962Spjd VN_URELE(tvp); 4264168962Spjd VN_RELE(fdvp); 4265168962Spjd VN_RELE(fvp); 4266168962Spjd 4267168962Spjd return (error); 4268168962Spjd} 4269168962Spjd 4270168962Spjdstatic int 4271168962Spjdzfs_freebsd_symlink(ap) 4272168962Spjd struct vop_symlink_args /* { 4273168962Spjd struct vnode *a_dvp; 4274168962Spjd struct vnode **a_vpp; 4275168962Spjd struct componentname *a_cnp; 4276168962Spjd struct vattr *a_vap; 4277168962Spjd char *a_target; 4278168962Spjd } */ *ap; 4279168962Spjd{ 4280168962Spjd struct componentname *cnp = ap->a_cnp; 4281168962Spjd vattr_t *vap = ap->a_vap; 4282168962Spjd 4283168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 4284168962Spjd 4285168962Spjd vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ 4286168962Spjd vattr_init_mask(vap); 4287168962Spjd 4288168962Spjd return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap, 4289168962Spjd ap->a_target, cnp->cn_cred, cnp->cn_thread)); 4290168962Spjd} 4291168962Spjd 4292168962Spjdstatic int 4293168962Spjdzfs_freebsd_readlink(ap) 4294168962Spjd struct vop_readlink_args /* { 4295168962Spjd struct vnode *a_vp; 4296168962Spjd struct uio *a_uio; 4297168962Spjd struct ucred *a_cred; 4298168962Spjd } */ *ap; 4299168962Spjd{ 4300168962Spjd 4301185029Spjd return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred, NULL)); 4302168962Spjd} 4303168962Spjd 4304168962Spjdstatic int 4305168962Spjdzfs_freebsd_link(ap) 4306168962Spjd struct vop_link_args /* { 4307168962Spjd struct vnode *a_tdvp; 4308168962Spjd struct vnode *a_vp; 4309168962Spjd struct componentname *a_cnp; 4310168962Spjd } */ *ap; 4311168962Spjd{ 4312168962Spjd struct componentname *cnp = ap->a_cnp; 4313168962Spjd 4314168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 4315168962Spjd 4316185029Spjd return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred, NULL, 0)); 4317168962Spjd} 4318168962Spjd 4319168962Spjdstatic int 4320168962Spjdzfs_freebsd_inactive(ap) 4321169170Spjd struct vop_inactive_args /* { 4322169170Spjd struct vnode *a_vp; 4323169170Spjd struct thread *a_td; 4324169170Spjd } */ *ap; 4325168962Spjd{ 4326168962Spjd vnode_t *vp = ap->a_vp; 4327168962Spjd 4328185029Spjd zfs_inactive(vp, ap->a_td->td_ucred, NULL); 4329168962Spjd return (0); 4330168962Spjd} 4331168962Spjd 4332185029Spjdstatic void 4333185029Spjdzfs_reclaim_complete(void *arg, int pending) 4334185029Spjd{ 4335185029Spjd znode_t *zp = arg; 4336185029Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 4337185029Spjd 4338185029Spjd ZFS_LOG(1, "zp=%p", zp); 4339185029Spjd ZFS_OBJ_HOLD_ENTER(zfsvfs, zp->z_id); 4340185029Spjd zfs_znode_dmu_fini(zp); 4341185029Spjd ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id); 4342185029Spjd zfs_znode_free(zp); 4343185029Spjd} 4344185029Spjd 4345168962Spjdstatic int 4346168962Spjdzfs_freebsd_reclaim(ap) 4347168962Spjd struct vop_reclaim_args /* { 4348168962Spjd struct vnode *a_vp; 4349168962Spjd struct thread *a_td; 4350168962Spjd } */ *ap; 4351168962Spjd{ 4352169170Spjd vnode_t *vp = ap->a_vp; 4353168962Spjd znode_t *zp = VTOZ(vp); 4354169025Spjd zfsvfs_t *zfsvfs; 4355168962Spjd 4356169025Spjd ASSERT(zp != NULL); 4357169025Spjd 4358168962Spjd /* 4359168962Spjd * Destroy the vm object and flush associated pages. 4360168962Spjd */ 4361168962Spjd vnode_destroy_vobject(vp); 4362169025Spjd 4363169025Spjd mutex_enter(&zp->z_lock); 4364169025Spjd ASSERT(zp->z_phys); 4365185029Spjd ZTOV(zp) = NULL; 4366169025Spjd if (!zp->z_unlinked) { 4367185029Spjd int locked; 4368185029Spjd 4369185029Spjd zfsvfs = zp->z_zfsvfs; 4370169025Spjd mutex_exit(&zp->z_lock); 4371185029Spjd locked = MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)) ? 2 : 4372185029Spjd ZFS_OBJ_HOLD_TRYENTER(zfsvfs, zp->z_id); 4373185029Spjd if (locked == 0) { 4374185029Spjd /* 4375185029Spjd * Lock can't be obtained due to deadlock possibility, 4376185029Spjd * so defer znode destruction. 4377185029Spjd */ 4378185029Spjd TASK_INIT(&zp->z_task, 0, zfs_reclaim_complete, zp); 4379185029Spjd taskqueue_enqueue(taskqueue_thread, &zp->z_task); 4380185029Spjd } else { 4381185029Spjd zfs_znode_dmu_fini(zp); 4382185029Spjd if (locked == 1) 4383185029Spjd ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id); 4384185029Spjd zfs_znode_free(zp); 4385185029Spjd } 4386169025Spjd } else { 4387169025Spjd mutex_exit(&zp->z_lock); 4388169025Spjd } 4389168962Spjd VI_LOCK(vp); 4390168962Spjd vp->v_data = NULL; 4391171567Spjd ASSERT(vp->v_holdcnt >= 1); 4392171316Sdfr VI_UNLOCK(vp); 4393168962Spjd return (0); 4394168962Spjd} 4395168962Spjd 4396168962Spjdstatic int 4397168962Spjdzfs_freebsd_fid(ap) 4398168962Spjd struct vop_fid_args /* { 4399168962Spjd struct vnode *a_vp; 4400168962Spjd struct fid *a_fid; 4401168962Spjd } */ *ap; 4402168962Spjd{ 4403168962Spjd 4404185029Spjd return (zfs_fid(ap->a_vp, (void *)ap->a_fid, NULL)); 4405168962Spjd} 4406168962Spjd 4407168962Spjdstatic int 4408168962Spjdzfs_freebsd_pathconf(ap) 4409168962Spjd struct vop_pathconf_args /* { 4410168962Spjd struct vnode *a_vp; 4411168962Spjd int a_name; 4412168962Spjd register_t *a_retval; 4413168962Spjd } */ *ap; 4414168962Spjd{ 4415168962Spjd ulong_t val; 4416168962Spjd int error; 4417168962Spjd 4418185029Spjd error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred, NULL); 4419168962Spjd if (error == 0) 4420168962Spjd *ap->a_retval = val; 4421168962Spjd else if (error == EOPNOTSUPP) 4422168962Spjd error = vop_stdpathconf(ap); 4423168962Spjd return (error); 4424168962Spjd} 4425168962Spjd 4426185029Spjd/* 4427185029Spjd * FreeBSD's extended attributes namespace defines file name prefix for ZFS' 4428185029Spjd * extended attribute name: 4429185029Spjd * 4430185029Spjd * NAMESPACE PREFIX 4431185029Spjd * system freebsd:system: 4432185029Spjd * user (none, can be used to access ZFS fsattr(5) attributes 4433185029Spjd * created on Solaris) 4434185029Spjd */ 4435185029Spjdstatic int 4436185029Spjdzfs_create_attrname(int attrnamespace, const char *name, char *attrname, 4437185029Spjd size_t size) 4438185029Spjd{ 4439185029Spjd const char *namespace, *prefix, *suffix; 4440185029Spjd 4441185029Spjd /* We don't allow '/' character in attribute name. */ 4442185029Spjd if (strchr(name, '/') != NULL) 4443185029Spjd return (EINVAL); 4444185029Spjd /* We don't allow attribute names that start with "freebsd:" string. */ 4445185029Spjd if (strncmp(name, "freebsd:", 8) == 0) 4446185029Spjd return (EINVAL); 4447185029Spjd 4448185029Spjd bzero(attrname, size); 4449185029Spjd 4450185029Spjd switch (attrnamespace) { 4451185029Spjd case EXTATTR_NAMESPACE_USER: 4452185029Spjd#if 0 4453185029Spjd prefix = "freebsd:"; 4454185029Spjd namespace = EXTATTR_NAMESPACE_USER_STRING; 4455185029Spjd suffix = ":"; 4456185029Spjd#else 4457185029Spjd /* 4458185029Spjd * This is the default namespace by which we can access all 4459185029Spjd * attributes created on Solaris. 4460185029Spjd */ 4461185029Spjd prefix = namespace = suffix = ""; 4462185029Spjd#endif 4463185029Spjd break; 4464185029Spjd case EXTATTR_NAMESPACE_SYSTEM: 4465185029Spjd prefix = "freebsd:"; 4466185029Spjd namespace = EXTATTR_NAMESPACE_SYSTEM_STRING; 4467185029Spjd suffix = ":"; 4468185029Spjd break; 4469185029Spjd case EXTATTR_NAMESPACE_EMPTY: 4470185029Spjd default: 4471185029Spjd return (EINVAL); 4472185029Spjd } 4473185029Spjd if (snprintf(attrname, size, "%s%s%s%s", prefix, namespace, suffix, 4474185029Spjd name) >= size) { 4475185029Spjd return (ENAMETOOLONG); 4476185029Spjd } 4477185029Spjd return (0); 4478185029Spjd} 4479185029Spjd 4480185029Spjd/* 4481185029Spjd * Vnode operating to retrieve a named extended attribute. 4482185029Spjd */ 4483185029Spjdstatic int 4484185029Spjdzfs_getextattr(struct vop_getextattr_args *ap) 4485185029Spjd/* 4486185029Spjdvop_getextattr { 4487185029Spjd IN struct vnode *a_vp; 4488185029Spjd IN int a_attrnamespace; 4489185029Spjd IN const char *a_name; 4490185029Spjd INOUT struct uio *a_uio; 4491185029Spjd OUT size_t *a_size; 4492185029Spjd IN struct ucred *a_cred; 4493185029Spjd IN struct thread *a_td; 4494185029Spjd}; 4495185029Spjd*/ 4496185029Spjd{ 4497185029Spjd zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; 4498185029Spjd struct thread *td = ap->a_td; 4499185029Spjd struct nameidata nd; 4500185029Spjd char attrname[255]; 4501185029Spjd struct vattr va; 4502185029Spjd vnode_t *xvp = NULL, *vp; 4503185029Spjd int error, flags; 4504185029Spjd 4505195785Strasz error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, 4506195785Strasz ap->a_cred, ap->a_td, VREAD); 4507195785Strasz if (error != 0) 4508195785Strasz return (error); 4509195785Strasz 4510185029Spjd error = zfs_create_attrname(ap->a_attrnamespace, ap->a_name, attrname, 4511185029Spjd sizeof(attrname)); 4512185029Spjd if (error != 0) 4513185029Spjd return (error); 4514185029Spjd 4515185029Spjd ZFS_ENTER(zfsvfs); 4516185029Spjd 4517185029Spjd error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td, 4518185029Spjd LOOKUP_XATTR); 4519185029Spjd if (error != 0) { 4520185029Spjd ZFS_EXIT(zfsvfs); 4521185029Spjd return (error); 4522185029Spjd } 4523185029Spjd 4524185029Spjd flags = FREAD; 4525185029Spjd NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, attrname, 4526185029Spjd xvp, td); 4527194586Skib error = vn_open_cred(&nd, &flags, 0, 0, ap->a_cred, NULL); 4528185029Spjd vp = nd.ni_vp; 4529185029Spjd NDFREE(&nd, NDF_ONLY_PNBUF); 4530185029Spjd if (error != 0) { 4531195785Strasz if (error == ENOENT) 4532195785Strasz error = ENOATTR; 4533185029Spjd ZFS_EXIT(zfsvfs); 4534185029Spjd return (error); 4535185029Spjd } 4536185029Spjd 4537185029Spjd if (ap->a_size != NULL) { 4538185029Spjd error = VOP_GETATTR(vp, &va, ap->a_cred); 4539185029Spjd if (error == 0) 4540185029Spjd *ap->a_size = (size_t)va.va_size; 4541185029Spjd } else if (ap->a_uio != NULL) 4542185029Spjd error = VOP_READ(vp, ap->a_uio, IO_UNIT | IO_SYNC, ap->a_cred); 4543185029Spjd 4544185029Spjd VOP_UNLOCK(vp, 0); 4545185029Spjd vn_close(vp, flags, ap->a_cred, td); 4546185029Spjd ZFS_EXIT(zfsvfs); 4547185029Spjd 4548185029Spjd return (error); 4549185029Spjd} 4550185029Spjd 4551185029Spjd/* 4552185029Spjd * Vnode operation to remove a named attribute. 4553185029Spjd */ 4554185029Spjdint 4555185029Spjdzfs_deleteextattr(struct vop_deleteextattr_args *ap) 4556185029Spjd/* 4557185029Spjdvop_deleteextattr { 4558185029Spjd IN struct vnode *a_vp; 4559185029Spjd IN int a_attrnamespace; 4560185029Spjd IN const char *a_name; 4561185029Spjd IN struct ucred *a_cred; 4562185029Spjd IN struct thread *a_td; 4563185029Spjd}; 4564185029Spjd*/ 4565185029Spjd{ 4566185029Spjd zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; 4567185029Spjd struct thread *td = ap->a_td; 4568185029Spjd struct nameidata nd; 4569185029Spjd char attrname[255]; 4570185029Spjd struct vattr va; 4571185029Spjd vnode_t *xvp = NULL, *vp; 4572185029Spjd int error, flags; 4573185029Spjd 4574195785Strasz error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, 4575195785Strasz ap->a_cred, ap->a_td, VWRITE); 4576195785Strasz if (error != 0) 4577195785Strasz return (error); 4578195785Strasz 4579185029Spjd error = zfs_create_attrname(ap->a_attrnamespace, ap->a_name, attrname, 4580185029Spjd sizeof(attrname)); 4581185029Spjd if (error != 0) 4582185029Spjd return (error); 4583185029Spjd 4584185029Spjd ZFS_ENTER(zfsvfs); 4585185029Spjd 4586185029Spjd error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td, 4587185029Spjd LOOKUP_XATTR); 4588185029Spjd if (error != 0) { 4589185029Spjd ZFS_EXIT(zfsvfs); 4590185029Spjd return (error); 4591185029Spjd } 4592185029Spjd 4593185029Spjd NDINIT_ATVP(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF | MPSAFE, 4594185029Spjd UIO_SYSSPACE, attrname, xvp, td); 4595185029Spjd error = namei(&nd); 4596185029Spjd vp = nd.ni_vp; 4597185029Spjd NDFREE(&nd, NDF_ONLY_PNBUF); 4598185029Spjd if (error != 0) { 4599195785Strasz if (error == ENOENT) 4600195785Strasz error = ENOATTR; 4601185029Spjd ZFS_EXIT(zfsvfs); 4602185029Spjd return (error); 4603185029Spjd } 4604185029Spjd error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 4605185029Spjd 4606185029Spjd vput(nd.ni_dvp); 4607185029Spjd if (vp == nd.ni_dvp) 4608185029Spjd vrele(vp); 4609185029Spjd else 4610185029Spjd vput(vp); 4611185029Spjd ZFS_EXIT(zfsvfs); 4612185029Spjd 4613185029Spjd return (error); 4614185029Spjd} 4615185029Spjd 4616185029Spjd/* 4617185029Spjd * Vnode operation to set a named attribute. 4618185029Spjd */ 4619185029Spjdstatic int 4620185029Spjdzfs_setextattr(struct vop_setextattr_args *ap) 4621185029Spjd/* 4622185029Spjdvop_setextattr { 4623185029Spjd IN struct vnode *a_vp; 4624185029Spjd IN int a_attrnamespace; 4625185029Spjd IN const char *a_name; 4626185029Spjd INOUT struct uio *a_uio; 4627185029Spjd IN struct ucred *a_cred; 4628185029Spjd IN struct thread *a_td; 4629185029Spjd}; 4630185029Spjd*/ 4631185029Spjd{ 4632185029Spjd zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; 4633185029Spjd struct thread *td = ap->a_td; 4634185029Spjd struct nameidata nd; 4635185029Spjd char attrname[255]; 4636185029Spjd struct vattr va; 4637185029Spjd vnode_t *xvp = NULL, *vp; 4638185029Spjd int error, flags; 4639185029Spjd 4640195785Strasz error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, 4641195785Strasz ap->a_cred, ap->a_td, VWRITE); 4642195785Strasz if (error != 0) 4643195785Strasz return (error); 4644195785Strasz 4645185029Spjd error = zfs_create_attrname(ap->a_attrnamespace, ap->a_name, attrname, 4646185029Spjd sizeof(attrname)); 4647185029Spjd if (error != 0) 4648185029Spjd return (error); 4649185029Spjd 4650185029Spjd ZFS_ENTER(zfsvfs); 4651185029Spjd 4652185029Spjd error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td, 4653195785Strasz LOOKUP_XATTR | CREATE_XATTR_DIR); 4654185029Spjd if (error != 0) { 4655185029Spjd ZFS_EXIT(zfsvfs); 4656185029Spjd return (error); 4657185029Spjd } 4658185029Spjd 4659185029Spjd flags = FFLAGS(O_WRONLY | O_CREAT); 4660185029Spjd NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, attrname, 4661185029Spjd xvp, td); 4662194586Skib error = vn_open_cred(&nd, &flags, 0600, 0, ap->a_cred, NULL); 4663185029Spjd vp = nd.ni_vp; 4664185029Spjd NDFREE(&nd, NDF_ONLY_PNBUF); 4665185029Spjd if (error != 0) { 4666185029Spjd ZFS_EXIT(zfsvfs); 4667185029Spjd return (error); 4668185029Spjd } 4669185029Spjd 4670185029Spjd VATTR_NULL(&va); 4671185029Spjd va.va_size = 0; 4672185029Spjd error = VOP_SETATTR(vp, &va, ap->a_cred); 4673185029Spjd if (error == 0) 4674185029Spjd VOP_WRITE(vp, ap->a_uio, IO_UNIT | IO_SYNC, ap->a_cred); 4675185029Spjd 4676185029Spjd VOP_UNLOCK(vp, 0); 4677185029Spjd vn_close(vp, flags, ap->a_cred, td); 4678185029Spjd ZFS_EXIT(zfsvfs); 4679185029Spjd 4680185029Spjd return (error); 4681185029Spjd} 4682185029Spjd 4683185029Spjd/* 4684185029Spjd * Vnode operation to retrieve extended attributes on a vnode. 4685185029Spjd */ 4686185029Spjdstatic int 4687185029Spjdzfs_listextattr(struct vop_listextattr_args *ap) 4688185029Spjd/* 4689185029Spjdvop_listextattr { 4690185029Spjd IN struct vnode *a_vp; 4691185029Spjd IN int a_attrnamespace; 4692185029Spjd INOUT struct uio *a_uio; 4693185029Spjd OUT size_t *a_size; 4694185029Spjd IN struct ucred *a_cred; 4695185029Spjd IN struct thread *a_td; 4696185029Spjd}; 4697185029Spjd*/ 4698185029Spjd{ 4699185029Spjd zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; 4700185029Spjd struct thread *td = ap->a_td; 4701185029Spjd struct nameidata nd; 4702185029Spjd char attrprefix[16]; 4703185029Spjd u_char dirbuf[sizeof(struct dirent)]; 4704185029Spjd struct dirent *dp; 4705185029Spjd struct iovec aiov; 4706185029Spjd struct uio auio, *uio = ap->a_uio; 4707185029Spjd size_t *sizep = ap->a_size; 4708185029Spjd size_t plen; 4709185029Spjd vnode_t *xvp = NULL, *vp; 4710185029Spjd int done, error, eof, pos; 4711185029Spjd 4712195785Strasz error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, 4713195785Strasz ap->a_cred, ap->a_td, VREAD); 4714195785Strasz if (error) 4715195785Strasz return (error); 4716195785Strasz 4717185029Spjd error = zfs_create_attrname(ap->a_attrnamespace, "", attrprefix, 4718185029Spjd sizeof(attrprefix)); 4719185029Spjd if (error != 0) 4720185029Spjd return (error); 4721185029Spjd plen = strlen(attrprefix); 4722185029Spjd 4723185029Spjd ZFS_ENTER(zfsvfs); 4724185029Spjd 4725185029Spjd error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td, 4726185029Spjd LOOKUP_XATTR); 4727185029Spjd if (error != 0) { 4728195785Strasz /* 4729195785Strasz * ENOATTR means that the EA directory does not yet exist, 4730195785Strasz * i.e. there are no extended attributes there. 4731195785Strasz */ 4732195785Strasz if (error == ENOATTR) 4733195785Strasz error = 0; 4734185029Spjd ZFS_EXIT(zfsvfs); 4735185029Spjd return (error); 4736185029Spjd } 4737185029Spjd 4738188588Sjhb NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE, 4739188588Sjhb UIO_SYSSPACE, ".", xvp, td); 4740185029Spjd error = namei(&nd); 4741185029Spjd vp = nd.ni_vp; 4742185029Spjd NDFREE(&nd, NDF_ONLY_PNBUF); 4743185029Spjd if (error != 0) { 4744185029Spjd ZFS_EXIT(zfsvfs); 4745185029Spjd return (error); 4746185029Spjd } 4747185029Spjd 4748185029Spjd auio.uio_iov = &aiov; 4749185029Spjd auio.uio_iovcnt = 1; 4750185029Spjd auio.uio_segflg = UIO_SYSSPACE; 4751185029Spjd auio.uio_td = td; 4752185029Spjd auio.uio_rw = UIO_READ; 4753185029Spjd auio.uio_offset = 0; 4754185029Spjd 4755185029Spjd if (sizep != NULL) 4756185029Spjd *sizep = 0; 4757185029Spjd 4758185029Spjd do { 4759185029Spjd u_char nlen; 4760185029Spjd 4761185029Spjd aiov.iov_base = (void *)dirbuf; 4762185029Spjd aiov.iov_len = sizeof(dirbuf); 4763185029Spjd auio.uio_resid = sizeof(dirbuf); 4764185029Spjd error = VOP_READDIR(vp, &auio, ap->a_cred, &eof, NULL, NULL); 4765185029Spjd done = sizeof(dirbuf) - auio.uio_resid; 4766185029Spjd if (error != 0) 4767185029Spjd break; 4768185029Spjd for (pos = 0; pos < done;) { 4769185029Spjd dp = (struct dirent *)(dirbuf + pos); 4770185029Spjd pos += dp->d_reclen; 4771185029Spjd /* 4772185029Spjd * XXX: Temporarily we also accept DT_UNKNOWN, as this 4773185029Spjd * is what we get when attribute was created on Solaris. 4774185029Spjd */ 4775185029Spjd if (dp->d_type != DT_REG && dp->d_type != DT_UNKNOWN) 4776185029Spjd continue; 4777185029Spjd if (plen == 0 && strncmp(dp->d_name, "freebsd:", 8) == 0) 4778185029Spjd continue; 4779185029Spjd else if (strncmp(dp->d_name, attrprefix, plen) != 0) 4780185029Spjd continue; 4781185029Spjd nlen = dp->d_namlen - plen; 4782185029Spjd if (sizep != NULL) 4783185029Spjd *sizep += 1 + nlen; 4784185029Spjd else if (uio != NULL) { 4785185029Spjd /* 4786185029Spjd * Format of extattr name entry is one byte for 4787185029Spjd * length and the rest for name. 4788185029Spjd */ 4789185029Spjd error = uiomove(&nlen, 1, uio->uio_rw, uio); 4790185029Spjd if (error == 0) { 4791185029Spjd error = uiomove(dp->d_name + plen, nlen, 4792185029Spjd uio->uio_rw, uio); 4793185029Spjd } 4794185029Spjd if (error != 0) 4795185029Spjd break; 4796185029Spjd } 4797185029Spjd } 4798185029Spjd } while (!eof && error == 0); 4799185029Spjd 4800185029Spjd vput(vp); 4801185029Spjd ZFS_EXIT(zfsvfs); 4802185029Spjd 4803185029Spjd return (error); 4804185029Spjd} 4805185029Spjd 4806192800Straszint 4807192800Straszzfs_freebsd_getacl(ap) 4808192800Strasz struct vop_getacl_args /* { 4809192800Strasz struct vnode *vp; 4810192800Strasz acl_type_t type; 4811192800Strasz struct acl *aclp; 4812192800Strasz struct ucred *cred; 4813192800Strasz struct thread *td; 4814192800Strasz } */ *ap; 4815192800Strasz{ 4816192800Strasz int error; 4817192800Strasz vsecattr_t vsecattr; 4818192800Strasz 4819192800Strasz if (ap->a_type != ACL_TYPE_NFS4) 4820192800Strasz return (EOPNOTSUPP); 4821192800Strasz 4822192800Strasz vsecattr.vsa_mask = VSA_ACE | VSA_ACECNT; 4823192800Strasz if (error = zfs_getsecattr(ap->a_vp, &vsecattr, 0, ap->a_cred, NULL)) 4824192800Strasz return (error); 4825192800Strasz 4826192800Strasz error = acl_from_aces(ap->a_aclp, vsecattr.vsa_aclentp, vsecattr.vsa_aclcnt); 4827192800Strasz if (vsecattr.vsa_aclentp != NULL) 4828192800Strasz kmem_free(vsecattr.vsa_aclentp, vsecattr.vsa_aclentsz); 4829192800Strasz 4830192800Strasz return (error); 4831192800Strasz} 4832192800Strasz 4833192800Straszint 4834192800Straszzfs_freebsd_setacl(ap) 4835192800Strasz struct vop_setacl_args /* { 4836192800Strasz struct vnode *vp; 4837192800Strasz acl_type_t type; 4838192800Strasz struct acl *aclp; 4839192800Strasz struct ucred *cred; 4840192800Strasz struct thread *td; 4841192800Strasz } */ *ap; 4842192800Strasz{ 4843192800Strasz int error; 4844192800Strasz vsecattr_t vsecattr; 4845192800Strasz int aclbsize; /* size of acl list in bytes */ 4846192800Strasz aclent_t *aaclp; 4847192800Strasz 4848192800Strasz if (ap->a_type != ACL_TYPE_NFS4) 4849192800Strasz return (EOPNOTSUPP); 4850192800Strasz 4851192800Strasz if (ap->a_aclp->acl_cnt < 1 || ap->a_aclp->acl_cnt > MAX_ACL_ENTRIES) 4852192800Strasz return (EINVAL); 4853192800Strasz 4854192800Strasz /* 4855192800Strasz * With NFS4 ACLs, chmod(2) may need to add additional entries, 4856192800Strasz * splitting every entry into two and appending "canonical six" 4857192800Strasz * entries at the end. Don't allow for setting an ACL that would 4858192800Strasz * cause chmod(2) to run out of ACL entries. 4859192800Strasz */ 4860192800Strasz if (ap->a_aclp->acl_cnt * 2 + 6 > ACL_MAX_ENTRIES) 4861192800Strasz return (ENOSPC); 4862192800Strasz 4863192800Strasz vsecattr.vsa_mask = VSA_ACE; 4864192800Strasz aclbsize = ap->a_aclp->acl_cnt * sizeof(ace_t); 4865192800Strasz vsecattr.vsa_aclentp = kmem_alloc(aclbsize, KM_SLEEP); 4866192800Strasz aaclp = vsecattr.vsa_aclentp; 4867192800Strasz vsecattr.vsa_aclentsz = aclbsize; 4868192800Strasz 4869192800Strasz aces_from_acl(vsecattr.vsa_aclentp, &vsecattr.vsa_aclcnt, ap->a_aclp); 4870192800Strasz error = zfs_setsecattr(ap->a_vp, &vsecattr, 0, ap->a_cred, NULL); 4871192800Strasz kmem_free(aaclp, aclbsize); 4872192800Strasz 4873192800Strasz return (error); 4874192800Strasz} 4875192800Strasz 4876192800Straszint 4877192800Straszzfs_freebsd_aclcheck(ap) 4878192800Strasz struct vop_aclcheck_args /* { 4879192800Strasz struct vnode *vp; 4880192800Strasz acl_type_t type; 4881192800Strasz struct acl *aclp; 4882192800Strasz struct ucred *cred; 4883192800Strasz struct thread *td; 4884192800Strasz } */ *ap; 4885192800Strasz{ 4886192800Strasz 4887192800Strasz return (EOPNOTSUPP); 4888192800Strasz} 4889192800Strasz 4890168404Spjdstruct vop_vector zfs_vnodeops; 4891168404Spjdstruct vop_vector zfs_fifoops; 4892168404Spjd 4893168404Spjdstruct vop_vector zfs_vnodeops = { 4894185029Spjd .vop_default = &default_vnodeops, 4895185029Spjd .vop_inactive = zfs_freebsd_inactive, 4896185029Spjd .vop_reclaim = zfs_freebsd_reclaim, 4897185029Spjd .vop_access = zfs_freebsd_access, 4898168404Spjd#ifdef FREEBSD_NAMECACHE 4899185029Spjd .vop_lookup = vfs_cache_lookup, 4900185029Spjd .vop_cachedlookup = zfs_freebsd_lookup, 4901168404Spjd#else 4902185029Spjd .vop_lookup = zfs_freebsd_lookup, 4903168404Spjd#endif 4904185029Spjd .vop_getattr = zfs_freebsd_getattr, 4905185029Spjd .vop_setattr = zfs_freebsd_setattr, 4906185029Spjd .vop_create = zfs_freebsd_create, 4907185029Spjd .vop_mknod = zfs_freebsd_create, 4908185029Spjd .vop_mkdir = zfs_freebsd_mkdir, 4909185029Spjd .vop_readdir = zfs_freebsd_readdir, 4910185029Spjd .vop_fsync = zfs_freebsd_fsync, 4911185029Spjd .vop_open = zfs_freebsd_open, 4912185029Spjd .vop_close = zfs_freebsd_close, 4913185029Spjd .vop_rmdir = zfs_freebsd_rmdir, 4914185029Spjd .vop_ioctl = zfs_freebsd_ioctl, 4915185029Spjd .vop_link = zfs_freebsd_link, 4916185029Spjd .vop_symlink = zfs_freebsd_symlink, 4917185029Spjd .vop_readlink = zfs_freebsd_readlink, 4918185029Spjd .vop_read = zfs_freebsd_read, 4919185029Spjd .vop_write = zfs_freebsd_write, 4920185029Spjd .vop_remove = zfs_freebsd_remove, 4921185029Spjd .vop_rename = zfs_freebsd_rename, 4922185029Spjd .vop_pathconf = zfs_freebsd_pathconf, 4923185029Spjd .vop_bmap = VOP_EOPNOTSUPP, 4924185029Spjd .vop_fid = zfs_freebsd_fid, 4925185029Spjd .vop_getextattr = zfs_getextattr, 4926185029Spjd .vop_deleteextattr = zfs_deleteextattr, 4927185029Spjd .vop_setextattr = zfs_setextattr, 4928185029Spjd .vop_listextattr = zfs_listextattr, 4929192800Strasz#ifdef notyet 4930192800Strasz .vop_getacl = zfs_freebsd_getacl, 4931192800Strasz .vop_setacl = zfs_freebsd_setacl, 4932192800Strasz .vop_aclcheck = zfs_freebsd_aclcheck, 4933192800Strasz#endif 4934168404Spjd}; 4935168404Spjd 4936169170Spjdstruct vop_vector zfs_fifoops = { 4937185029Spjd .vop_default = &fifo_specops, 4938185029Spjd .vop_fsync = VOP_PANIC, 4939185029Spjd .vop_access = zfs_freebsd_access, 4940185029Spjd .vop_getattr = zfs_freebsd_getattr, 4941185029Spjd .vop_inactive = zfs_freebsd_inactive, 4942185029Spjd .vop_read = VOP_PANIC, 4943185029Spjd .vop_reclaim = zfs_freebsd_reclaim, 4944185029Spjd .vop_setattr = zfs_freebsd_setattr, 4945185029Spjd .vop_write = VOP_PANIC, 4946185029Spjd .vop_fid = zfs_freebsd_fid, 4947192800Strasz#ifdef notyet 4948192800Strasz .vop_getacl = zfs_freebsd_getacl, 4949192800Strasz .vop_setacl = zfs_freebsd_setacl, 4950192800Strasz .vop_aclcheck = zfs_freebsd_aclcheck, 4951192800Strasz#endif 4952168404Spjd}; 4953