zfs_vnops.c revision 169057
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/* 22168404Spjd * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 27168404Spjd 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_vfsops.h> 48168404Spjd#include <sys/zfs_dir.h> 49168404Spjd#include <sys/zfs_acl.h> 50168404Spjd#include <sys/zfs_ioctl.h> 51168404Spjd#include <sys/fs/zfs.h> 52168404Spjd#include <sys/dmu.h> 53168404Spjd#include <sys/spa.h> 54168404Spjd#include <sys/txg.h> 55168404Spjd#include <sys/dbuf.h> 56168404Spjd#include <sys/zap.h> 57168404Spjd#include <sys/dirent.h> 58168962Spjd#include <sys/policy.h> 59168962Spjd#include <sys/sunddi.h> 60168404Spjd#include <sys/filio.h> 61168404Spjd#include <sys/zfs_ctldir.h> 62168404Spjd#include <sys/dnlc.h> 63168404Spjd#include <sys/zfs_rlock.h> 64168404Spjd#include <sys/bio.h> 65168404Spjd#include <sys/buf.h> 66168404Spjd#include <sys/sf_buf.h> 67168404Spjd#include <sys/sched.h> 68168404Spjd 69168404Spjd/* 70168404Spjd * Programming rules. 71168404Spjd * 72168404Spjd * Each vnode op performs some logical unit of work. To do this, the ZPL must 73168404Spjd * properly lock its in-core state, create a DMU transaction, do the work, 74168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction, 75168404Spjd * and wait the the intent log to commit if it's is a synchronous operation. 76168404Spjd * Morover, the vnode ops must work in both normal and log replay context. 77168404Spjd * The ordering of events is important to avoid deadlocks and references 78168404Spjd * to freed memory. The example below illustrates the following Big Rules: 79168404Spjd * 80168404Spjd * (1) A check must be made in each zfs thread for a mounted file system. 81168404Spjd * This is done avoiding races using ZFS_ENTER(zfsvfs). 82168404Spjd * A ZFS_EXIT(zfsvfs) is needed before all returns. 83168404Spjd * 84168404Spjd * (2) VN_RELE() should always be the last thing except for zil_commit() 85168404Spjd * (if necessary) and ZFS_EXIT(). This is for 3 reasons: 86168404Spjd * First, if it's the last reference, the vnode/znode 87168404Spjd * can be freed, so the zp may point to freed memory. Second, the last 88168404Spjd * reference will call zfs_zinactive(), which may induce a lot of work -- 89168404Spjd * pushing cached pages (which acquires range locks) and syncing out 90168404Spjd * cached atime changes. Third, zfs_zinactive() may require a new tx, 91168404Spjd * which could deadlock the system if you were already holding one. 92168404Spjd * 93168404Spjd * (3) All range locks must be grabbed before calling dmu_tx_assign(), 94168404Spjd * as they can span dmu_tx_assign() calls. 95168404Spjd * 96168404Spjd * (4) Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign(). 97168404Spjd * In normal operation, this will be TXG_NOWAIT. During ZIL replay, 98168404Spjd * it will be a specific txg. Either way, dmu_tx_assign() never blocks. 99168404Spjd * This is critical because we don't want to block while holding locks. 100168404Spjd * Note, in particular, that if a lock is sometimes acquired before 101168404Spjd * the tx assigns, and sometimes after (e.g. z_lock), then failing to 102168404Spjd * use a non-blocking assign can deadlock the system. The scenario: 103168404Spjd * 104168404Spjd * Thread A has grabbed a lock before calling dmu_tx_assign(). 105168404Spjd * Thread B is in an already-assigned tx, and blocks for this lock. 106168404Spjd * Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open() 107168404Spjd * forever, because the previous txg can't quiesce until B's tx commits. 108168404Spjd * 109168404Spjd * If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT, 110168404Spjd * then drop all locks, call dmu_tx_wait(), and try again. 111168404Spjd * 112168404Spjd * (5) If the operation succeeded, generate the intent log entry for it 113168404Spjd * before dropping locks. This ensures that the ordering of events 114168404Spjd * in the intent log matches the order in which they actually occurred. 115168404Spjd * 116168404Spjd * (6) At the end of each vnode op, the DMU tx must always commit, 117168404Spjd * regardless of whether there were any errors. 118168404Spjd * 119168404Spjd * (7) After dropping all locks, invoke zil_commit(zilog, seq, foid) 120168404Spjd * to ensure that synchronous semantics are provided when necessary. 121168404Spjd * 122168404Spjd * In general, this is how things should be ordered in each vnode op: 123168404Spjd * 124168404Spjd * ZFS_ENTER(zfsvfs); // exit if unmounted 125168404Spjd * top: 126168404Spjd * zfs_dirent_lock(&dl, ...) // lock directory entry (may VN_HOLD()) 127168404Spjd * rw_enter(...); // grab any other locks you need 128168404Spjd * tx = dmu_tx_create(...); // get DMU tx 129168404Spjd * dmu_tx_hold_*(); // hold each object you might modify 130168404Spjd * error = dmu_tx_assign(tx, zfsvfs->z_assign); // try to assign 131168404Spjd * if (error) { 132168404Spjd * rw_exit(...); // drop locks 133168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 134168404Spjd * VN_RELE(...); // release held vnodes 135168404Spjd * if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 136168404Spjd * dmu_tx_wait(tx); 137168404Spjd * dmu_tx_abort(tx); 138168404Spjd * goto top; 139168404Spjd * } 140168404Spjd * dmu_tx_abort(tx); // abort DMU tx 141168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 142168404Spjd * return (error); // really out of space 143168404Spjd * } 144168404Spjd * error = do_real_work(); // do whatever this VOP does 145168404Spjd * if (error == 0) 146168404Spjd * zfs_log_*(...); // on success, make ZIL entry 147168404Spjd * dmu_tx_commit(tx); // commit DMU tx -- error or not 148168404Spjd * rw_exit(...); // drop locks 149168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 150168404Spjd * VN_RELE(...); // release held vnodes 151168404Spjd * zil_commit(zilog, seq, foid); // synchronous when necessary 152168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 153168404Spjd * return (error); // done, report error 154168404Spjd */ 155168404Spjd/* ARGSUSED */ 156168404Spjdstatic int 157168962Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr) 158168404Spjd{ 159168962Spjd znode_t *zp = VTOZ(*vpp); 160168404Spjd 161168404Spjd /* Keep a count of the synchronous opens in the znode */ 162168962Spjd if (flag & (FSYNC | FDSYNC)) 163168404Spjd atomic_inc_32(&zp->z_sync_cnt); 164168404Spjd return (0); 165168404Spjd} 166168404Spjd 167168404Spjd/* ARGSUSED */ 168168404Spjdstatic int 169168962Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) 170168404Spjd{ 171168962Spjd znode_t *zp = VTOZ(vp); 172168404Spjd 173168404Spjd /* Decrement the synchronous opens in the znode */ 174168962Spjd if (flag & (FSYNC | FDSYNC)) 175168404Spjd atomic_dec_32(&zp->z_sync_cnt); 176168404Spjd 177168962Spjd /* 178168962Spjd * Clean up any locks held by this process on the vp. 179168962Spjd */ 180168962Spjd cleanlocks(vp, ddi_get_pid(), 0); 181168962Spjd cleanshares(vp, ddi_get_pid()); 182168962Spjd 183168404Spjd return (0); 184168404Spjd} 185168404Spjd 186168404Spjd/* 187168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and 188168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. 189168404Spjd */ 190168404Spjdstatic int 191168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off) 192168404Spjd{ 193168404Spjd znode_t *zp = VTOZ(vp); 194168404Spjd uint64_t noff = (uint64_t)*off; /* new offset */ 195168404Spjd uint64_t file_sz; 196168404Spjd int error; 197168404Spjd boolean_t hole; 198168404Spjd 199168404Spjd file_sz = zp->z_phys->zp_size; 200168404Spjd if (noff >= file_sz) { 201168404Spjd return (ENXIO); 202168404Spjd } 203168404Spjd 204168962Spjd if (cmd == _FIO_SEEK_HOLE) 205168404Spjd hole = B_TRUE; 206168404Spjd else 207168404Spjd hole = B_FALSE; 208168404Spjd 209168404Spjd error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); 210168404Spjd 211168404Spjd /* end of file? */ 212168404Spjd if ((error == ESRCH) || (noff > file_sz)) { 213168404Spjd /* 214168404Spjd * Handle the virtual hole at the end of file. 215168404Spjd */ 216168404Spjd if (hole) { 217168404Spjd *off = file_sz; 218168404Spjd return (0); 219168404Spjd } 220168404Spjd return (ENXIO); 221168404Spjd } 222168404Spjd 223168404Spjd if (noff < *off) 224168404Spjd return (error); 225168404Spjd *off = noff; 226168404Spjd return (error); 227168404Spjd} 228168404Spjd 229168404Spjd/* ARGSUSED */ 230168404Spjdstatic int 231168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred, 232168962Spjd int *rvalp) 233168404Spjd{ 234168962Spjd offset_t off; 235168962Spjd int error; 236168962Spjd zfsvfs_t *zfsvfs; 237168404Spjd 238168404Spjd switch (com) { 239168962Spjd case _FIOFFS: 240168962Spjd return (0); 241168404Spjd 242168962Spjd /* 243168962Spjd * The following two ioctls are used by bfu. Faking out, 244168962Spjd * necessary to avoid bfu errors. 245168962Spjd */ 246168962Spjd case _FIOGDIO: 247168962Spjd case _FIOSDIO: 248168962Spjd return (0); 249168962Spjd 250168962Spjd case _FIO_SEEK_DATA: 251168962Spjd case _FIO_SEEK_HOLE: 252168962Spjd if (ddi_copyin((void *)data, &off, sizeof (off), flag)) 253168962Spjd return (EFAULT); 254168962Spjd 255168404Spjd zfsvfs = VTOZ(vp)->z_zfsvfs; 256168404Spjd ZFS_ENTER(zfsvfs); 257168404Spjd 258168404Spjd /* offset parameter is in/out */ 259168404Spjd error = zfs_holey(vp, com, &off); 260168404Spjd ZFS_EXIT(zfsvfs); 261168404Spjd if (error) 262168404Spjd return (error); 263168962Spjd if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) 264168962Spjd return (EFAULT); 265168404Spjd return (0); 266168404Spjd } 267168404Spjd return (ENOTTY); 268168404Spjd} 269168404Spjd 270168404Spjd/* 271168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 272168404Spjd * between the DMU cache and the memory mapped pages. What this means: 273168404Spjd * 274168404Spjd * On Write: If we find a memory mapped page, we write to *both* 275168404Spjd * the page and the dmu buffer. 276168404Spjd * 277168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 278168404Spjd * the file is memory mapped. 279168404Spjd */ 280168404Spjdstatic int 281168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) 282168404Spjd{ 283168404Spjd znode_t *zp = VTOZ(vp); 284168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 285168404Spjd vm_object_t obj; 286168404Spjd vm_page_t m; 287168404Spjd struct sf_buf *sf; 288168404Spjd int64_t start, off; 289168404Spjd int len = nbytes; 290168404Spjd int error = 0; 291168404Spjd 292168404Spjd ASSERT(vp->v_mount != NULL); 293168404Spjd obj = vp->v_object; 294168404Spjd ASSERT(obj != NULL); 295168404Spjd 296168404Spjd start = uio->uio_loffset; 297168404Spjd off = start & PAGEOFFSET; 298168404Spjd VM_OBJECT_LOCK(obj); 299168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 300168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 301168404Spjd 302168404Spjdagain: 303168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 304168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 305169057Spjd uint64_t woff, dmubytes; 306168404Spjd caddr_t va; 307168404Spjd 308168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) 309168404Spjd goto again; 310169057Spjd woff = uio->uio_loffset; 311169057Spjd dmubytes = MIN(PAGESIZE, 312169057Spjd obj->un_pager.vnp.vnp_size - (woff - off)); 313168404Spjd vm_page_busy(m); 314169057Spjd vm_page_lock_queues(); 315169057Spjd vm_page_undirty(m); 316169057Spjd vm_page_unlock_queues(); 317168404Spjd VM_OBJECT_UNLOCK(obj); 318168404Spjd sched_pin(); 319168404Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 320168404Spjd va = (caddr_t)sf_buf_kva(sf); 321169057Spjd error = uiomove(va + off, bytes, UIO_WRITE, uio); 322169057Spjd dmu_write(os, zp->z_id, woff - off, dmubytes, va, tx); 323168404Spjd sf_buf_free(sf); 324168404Spjd sched_unpin(); 325168404Spjd VM_OBJECT_LOCK(obj); 326168404Spjd vm_page_wakeup(m); 327168404Spjd } else { 328168404Spjd VM_OBJECT_UNLOCK(obj); 329168404Spjd error = dmu_write_uio(os, zp->z_id, uio, bytes, tx); 330168404Spjd VM_OBJECT_LOCK(obj); 331168404Spjd } 332168404Spjd len -= bytes; 333168404Spjd off = 0; 334168404Spjd if (error) 335168404Spjd break; 336168404Spjd } 337168404Spjd VM_OBJECT_UNLOCK(obj); 338168404Spjd return (error); 339168404Spjd} 340168404Spjd 341168404Spjd/* 342168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 343168404Spjd * between the DMU cache and the memory mapped pages. What this means: 344168404Spjd * 345168404Spjd * On Read: We "read" preferentially from memory mapped pages, 346168404Spjd * else we default from the dmu buffer. 347168404Spjd * 348168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 349168404Spjd * the file is memory mapped. 350168404Spjd */ 351168404Spjdstatic int 352168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio) 353168404Spjd{ 354168404Spjd znode_t *zp = VTOZ(vp); 355168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 356168404Spjd vm_object_t obj; 357168404Spjd vm_page_t m; 358168404Spjd struct sf_buf *sf; 359168404Spjd int64_t start, off; 360168926Spjd caddr_t va; 361168404Spjd int len = nbytes; 362168404Spjd int error = 0; 363168404Spjd 364168404Spjd ASSERT(vp->v_mount != NULL); 365168404Spjd obj = vp->v_object; 366168404Spjd ASSERT(obj != NULL); 367168404Spjd 368168404Spjd start = uio->uio_loffset; 369168404Spjd off = start & PAGEOFFSET; 370168404Spjd VM_OBJECT_LOCK(obj); 371168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 372168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 373168404Spjd 374168404Spjdagain: 375168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 376168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 377168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 378168404Spjd goto again; 379168404Spjd vm_page_busy(m); 380168404Spjd VM_OBJECT_UNLOCK(obj); 381168404Spjd sched_pin(); 382168404Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 383168404Spjd va = (caddr_t)sf_buf_kva(sf); 384168404Spjd error = uiomove(va + off, bytes, UIO_READ, uio); 385168404Spjd sf_buf_free(sf); 386168404Spjd sched_unpin(); 387168404Spjd VM_OBJECT_LOCK(obj); 388168404Spjd vm_page_wakeup(m); 389168926Spjd } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { 390168962Spjd /* 391168962Spjd * The code below is here to make sendfile(2) work 392168962Spjd * correctly with ZFS. As pointed out by ups@ 393168962Spjd * sendfile(2) should be changed to use VOP_GETPAGES(), 394168962Spjd * but it pessimize performance of sendfile/UFS, that's 395168962Spjd * why I handle this special case in ZFS code. 396168962Spjd */ 397168926Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 398168926Spjd goto again; 399168926Spjd vm_page_busy(m); 400168926Spjd VM_OBJECT_UNLOCK(obj); 401168926Spjd sched_pin(); 402168926Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 403168926Spjd va = (caddr_t)sf_buf_kva(sf); 404168926Spjd error = dmu_read(os, zp->z_id, start + off, bytes, 405168926Spjd (void *)(va + off)); 406168926Spjd sf_buf_free(sf); 407168926Spjd sched_unpin(); 408168926Spjd VM_OBJECT_LOCK(obj); 409168926Spjd vm_page_wakeup(m); 410168926Spjd uio->uio_resid -= bytes; 411168404Spjd } else { 412168404Spjd VM_OBJECT_UNLOCK(obj); 413168404Spjd error = dmu_read_uio(os, zp->z_id, uio, bytes); 414168404Spjd VM_OBJECT_LOCK(obj); 415168404Spjd } 416168404Spjd len -= bytes; 417168404Spjd off = 0; 418168404Spjd if (error) 419168404Spjd break; 420168404Spjd } 421168404Spjd VM_OBJECT_UNLOCK(obj); 422168404Spjd return (error); 423168404Spjd} 424168404Spjd 425168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */ 426168404Spjd 427168404Spjd/* 428168404Spjd * Read bytes from specified file into supplied buffer. 429168404Spjd * 430168404Spjd * IN: vp - vnode of file to be read from. 431168404Spjd * uio - structure supplying read location, range info, 432168404Spjd * and return buffer. 433168404Spjd * ioflag - SYNC flags; used to provide FRSYNC semantics. 434168404Spjd * cr - credentials of caller. 435168404Spjd * 436168404Spjd * OUT: uio - updated offset and range, buffer filled. 437168404Spjd * 438168404Spjd * RETURN: 0 if success 439168404Spjd * error code if failure 440168404Spjd * 441168404Spjd * Side Effects: 442168404Spjd * vp - atime updated if byte count > 0 443168404Spjd */ 444168404Spjd/* ARGSUSED */ 445168404Spjdstatic int 446168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 447168404Spjd{ 448168404Spjd znode_t *zp = VTOZ(vp); 449168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 450168404Spjd objset_t *os = zfsvfs->z_os; 451168404Spjd ssize_t n, nbytes; 452168404Spjd int error; 453168404Spjd rl_t *rl; 454168404Spjd 455168404Spjd ZFS_ENTER(zfsvfs); 456168404Spjd 457168404Spjd /* 458168404Spjd * Validate file offset 459168404Spjd */ 460168404Spjd if (uio->uio_loffset < (offset_t)0) { 461168404Spjd ZFS_EXIT(zfsvfs); 462168404Spjd return (EINVAL); 463168404Spjd } 464168404Spjd 465168404Spjd /* 466168404Spjd * Fasttrack empty reads 467168404Spjd */ 468168404Spjd if (uio->uio_resid == 0) { 469168404Spjd ZFS_EXIT(zfsvfs); 470168404Spjd return (0); 471168404Spjd } 472168404Spjd 473168404Spjd /* 474168962Spjd * Check for mandatory locks 475168962Spjd */ 476168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode)) { 477168962Spjd if (error = chklock(vp, FREAD, 478168962Spjd uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { 479168962Spjd ZFS_EXIT(zfsvfs); 480168962Spjd return (error); 481168962Spjd } 482168962Spjd } 483168962Spjd 484168962Spjd /* 485168404Spjd * If we're in FRSYNC mode, sync out this znode before reading it. 486168404Spjd */ 487168962Spjd if (ioflag & FRSYNC) 488168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 489168404Spjd 490168404Spjd /* 491168404Spjd * Lock the range against changes. 492168404Spjd */ 493168404Spjd rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER); 494168404Spjd 495168404Spjd /* 496168404Spjd * If we are reading past end-of-file we can skip 497168404Spjd * to the end; but we might still need to set atime. 498168404Spjd */ 499168404Spjd if (uio->uio_loffset >= zp->z_phys->zp_size) { 500168404Spjd error = 0; 501168404Spjd goto out; 502168404Spjd } 503168404Spjd 504168404Spjd ASSERT(uio->uio_loffset < zp->z_phys->zp_size); 505168404Spjd n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset); 506168404Spjd 507168404Spjd while (n > 0) { 508168404Spjd nbytes = MIN(n, zfs_read_chunk_size - 509168404Spjd P2PHASE(uio->uio_loffset, zfs_read_chunk_size)); 510168404Spjd 511168404Spjd if (vn_has_cached_data(vp)) 512168404Spjd error = mappedread(vp, nbytes, uio); 513168404Spjd else 514168404Spjd error = dmu_read_uio(os, zp->z_id, uio, nbytes); 515168404Spjd if (error) 516168404Spjd break; 517168962Spjd 518168404Spjd n -= nbytes; 519168404Spjd } 520168404Spjd 521168404Spjdout: 522168404Spjd zfs_range_unlock(rl); 523168404Spjd 524168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 525168404Spjd ZFS_EXIT(zfsvfs); 526168404Spjd return (error); 527168404Spjd} 528168404Spjd 529168404Spjd/* 530168404Spjd * Fault in the pages of the first n bytes specified by the uio structure. 531168404Spjd * 1 byte in each page is touched and the uio struct is unmodified. 532168404Spjd * Any error will exit this routine as this is only a best 533168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch(). 534168404Spjd */ 535168404Spjdstatic void 536168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio) 537168404Spjd{ 538168404Spjd struct iovec *iov; 539168404Spjd ulong_t cnt, incr; 540168404Spjd caddr_t p; 541168404Spjd 542168404Spjd if (uio->uio_segflg != UIO_USERSPACE) 543168404Spjd return; 544168404Spjd 545168404Spjd iov = uio->uio_iov; 546168404Spjd 547168404Spjd while (n) { 548168404Spjd cnt = MIN(iov->iov_len, n); 549168404Spjd if (cnt == 0) { 550168404Spjd /* empty iov entry */ 551168404Spjd iov++; 552168404Spjd continue; 553168404Spjd } 554168404Spjd n -= cnt; 555168404Spjd /* 556168404Spjd * touch each page in this segment. 557168404Spjd */ 558168404Spjd p = iov->iov_base; 559168404Spjd while (cnt) { 560168404Spjd if (fubyte(p) == -1) 561168404Spjd return; 562168404Spjd incr = MIN(cnt, PAGESIZE); 563168404Spjd p += incr; 564168404Spjd cnt -= incr; 565168404Spjd } 566168404Spjd /* 567168404Spjd * touch the last byte in case it straddles a page. 568168404Spjd */ 569168404Spjd p--; 570168404Spjd if (fubyte(p) == -1) 571168404Spjd return; 572168404Spjd iov++; 573168404Spjd } 574168404Spjd} 575168404Spjd 576168404Spjd/* 577168404Spjd * Write the bytes to a file. 578168404Spjd * 579168404Spjd * IN: vp - vnode of file to be written to. 580168404Spjd * uio - structure supplying write location, range info, 581168404Spjd * and data buffer. 582168404Spjd * ioflag - IO_APPEND flag set if in append mode. 583168404Spjd * cr - credentials of caller. 584168404Spjd * 585168404Spjd * OUT: uio - updated offset and range. 586168404Spjd * 587168404Spjd * RETURN: 0 if success 588168404Spjd * error code if failure 589168404Spjd * 590168404Spjd * Timestamps: 591168404Spjd * vp - ctime|mtime updated if byte count > 0 592168404Spjd */ 593168404Spjd/* ARGSUSED */ 594168404Spjdstatic int 595168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 596168404Spjd{ 597168404Spjd znode_t *zp = VTOZ(vp); 598168962Spjd rlim64_t limit = MAXOFFSET_T; 599168404Spjd ssize_t start_resid = uio->uio_resid; 600168404Spjd ssize_t tx_bytes; 601168404Spjd uint64_t end_size; 602168404Spjd dmu_tx_t *tx; 603168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 604168404Spjd zilog_t *zilog = zfsvfs->z_log; 605168404Spjd offset_t woff; 606168404Spjd ssize_t n, nbytes; 607168404Spjd rl_t *rl; 608168404Spjd int max_blksz = zfsvfs->z_max_blksz; 609168404Spjd int error; 610168404Spjd 611168404Spjd /* 612168404Spjd * Fasttrack empty write 613168404Spjd */ 614168404Spjd n = start_resid; 615168404Spjd if (n == 0) 616168404Spjd return (0); 617168404Spjd 618168962Spjd if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 619168962Spjd limit = MAXOFFSET_T; 620168962Spjd 621168404Spjd ZFS_ENTER(zfsvfs); 622168404Spjd 623168404Spjd /* 624168404Spjd * Pre-fault the pages to ensure slow (eg NFS) pages 625168404Spjd * don't hold up txg. 626168404Spjd */ 627168404Spjd zfs_prefault_write(n, uio); 628168404Spjd 629168404Spjd /* 630168404Spjd * If in append mode, set the io offset pointer to eof. 631168404Spjd */ 632168404Spjd if (ioflag & IO_APPEND) { 633168404Spjd /* 634168404Spjd * Range lock for a file append: 635168404Spjd * The value for the start of range will be determined by 636168404Spjd * zfs_range_lock() (to guarantee append semantics). 637168404Spjd * If this write will cause the block size to increase, 638168404Spjd * zfs_range_lock() will lock the entire file, so we must 639168404Spjd * later reduce the range after we grow the block size. 640168404Spjd */ 641168404Spjd rl = zfs_range_lock(zp, 0, n, RL_APPEND); 642168404Spjd if (rl->r_len == UINT64_MAX) { 643168404Spjd /* overlocked, zp_size can't change */ 644168404Spjd woff = uio->uio_loffset = zp->z_phys->zp_size; 645168404Spjd } else { 646168404Spjd woff = uio->uio_loffset = rl->r_off; 647168404Spjd } 648168404Spjd } else { 649168404Spjd woff = uio->uio_loffset; 650168404Spjd /* 651168404Spjd * Validate file offset 652168404Spjd */ 653168404Spjd if (woff < 0) { 654168404Spjd ZFS_EXIT(zfsvfs); 655168404Spjd return (EINVAL); 656168404Spjd } 657168404Spjd 658168404Spjd /* 659168404Spjd * If we need to grow the block size then zfs_range_lock() 660168404Spjd * will lock a wider range than we request here. 661168404Spjd * Later after growing the block size we reduce the range. 662168404Spjd */ 663168404Spjd rl = zfs_range_lock(zp, woff, n, RL_WRITER); 664168404Spjd } 665168404Spjd 666168962Spjd if (woff >= limit) { 667168962Spjd zfs_range_unlock(rl); 668168962Spjd ZFS_EXIT(zfsvfs); 669168962Spjd return (EFBIG); 670168962Spjd } 671168962Spjd 672168962Spjd if ((woff + n) > limit || woff > (limit - n)) 673168962Spjd n = limit - woff; 674168962Spjd 675168962Spjd /* 676168962Spjd * Check for mandatory locks 677168962Spjd */ 678168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode) && 679168962Spjd (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { 680168962Spjd zfs_range_unlock(rl); 681168962Spjd ZFS_EXIT(zfsvfs); 682168962Spjd return (error); 683168962Spjd } 684168404Spjd end_size = MAX(zp->z_phys->zp_size, woff + n); 685168404Spjd 686168404Spjd /* 687168404Spjd * Write the file in reasonable size chunks. Each chunk is written 688168404Spjd * in a separate transaction; this keeps the intent log records small 689168404Spjd * and allows us to do more fine-grained space accounting. 690168404Spjd */ 691168404Spjd while (n > 0) { 692168404Spjd /* 693168404Spjd * Start a transaction. 694168404Spjd */ 695168404Spjd woff = uio->uio_loffset; 696168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 697168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 698168404Spjd dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); 699168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 700168404Spjd if (error) { 701168404Spjd if (error == ERESTART && 702168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 703168404Spjd dmu_tx_wait(tx); 704168404Spjd dmu_tx_abort(tx); 705168404Spjd continue; 706168404Spjd } 707168404Spjd dmu_tx_abort(tx); 708168404Spjd break; 709168404Spjd } 710168404Spjd 711168404Spjd /* 712168404Spjd * If zfs_range_lock() over-locked we grow the blocksize 713168404Spjd * and then reduce the lock range. This will only happen 714168404Spjd * on the first iteration since zfs_range_reduce() will 715168404Spjd * shrink down r_len to the appropriate size. 716168404Spjd */ 717168404Spjd if (rl->r_len == UINT64_MAX) { 718168404Spjd uint64_t new_blksz; 719168404Spjd 720168404Spjd if (zp->z_blksz > max_blksz) { 721168404Spjd ASSERT(!ISP2(zp->z_blksz)); 722168404Spjd new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE); 723168404Spjd } else { 724168404Spjd new_blksz = MIN(end_size, max_blksz); 725168404Spjd } 726168404Spjd zfs_grow_blocksize(zp, new_blksz, tx); 727168404Spjd zfs_range_reduce(rl, woff, n); 728168404Spjd } 729168404Spjd 730168404Spjd /* 731168404Spjd * XXX - should we really limit each write to z_max_blksz? 732168404Spjd * Perhaps we should use SPA_MAXBLOCKSIZE chunks? 733168404Spjd */ 734168404Spjd nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz)); 735168404Spjd rw_enter(&zp->z_map_lock, RW_READER); 736168404Spjd 737168404Spjd if (woff + nbytes > zp->z_phys->zp_size) 738168404Spjd vnode_pager_setsize(vp, woff + nbytes); 739168404Spjd 740168962Spjd tx_bytes = uio->uio_resid; 741168404Spjd if (vn_has_cached_data(vp)) { 742168404Spjd rw_exit(&zp->z_map_lock); 743168404Spjd error = mappedwrite(vp, nbytes, uio, tx); 744168404Spjd } else { 745168404Spjd error = dmu_write_uio(zfsvfs->z_os, zp->z_id, 746168404Spjd uio, nbytes, tx); 747168404Spjd rw_exit(&zp->z_map_lock); 748168404Spjd } 749168404Spjd tx_bytes -= uio->uio_resid; 750168404Spjd 751168404Spjd /* 752168404Spjd * If we made no progress, we're done. If we made even 753168404Spjd * partial progress, update the znode and ZIL accordingly. 754168404Spjd */ 755168404Spjd if (tx_bytes == 0) { 756168404Spjd dmu_tx_commit(tx); 757168404Spjd ASSERT(error != 0); 758168404Spjd break; 759168404Spjd } 760168404Spjd 761168404Spjd /* 762168404Spjd * Clear Set-UID/Set-GID bits on successful write if not 763168404Spjd * privileged and at least one of the excute bits is set. 764168404Spjd * 765168404Spjd * It would be nice to to this after all writes have 766168404Spjd * been done, but that would still expose the ISUID/ISGID 767168404Spjd * to another app after the partial write is committed. 768168404Spjd */ 769168404Spjd mutex_enter(&zp->z_acl_lock); 770168404Spjd if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) | 771168404Spjd (S_IXUSR >> 6))) != 0 && 772168404Spjd (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 && 773168404Spjd secpolicy_vnode_setid_retain(cr, 774168404Spjd (zp->z_phys->zp_mode & S_ISUID) != 0 && 775168404Spjd zp->z_phys->zp_uid == 0) != 0) { 776168404Spjd zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID); 777168404Spjd } 778168404Spjd mutex_exit(&zp->z_acl_lock); 779168404Spjd 780168404Spjd /* 781168404Spjd * Update time stamp. NOTE: This marks the bonus buffer as 782168404Spjd * dirty, so we don't have to do it again for zp_size. 783168404Spjd */ 784168404Spjd zfs_time_stamper(zp, CONTENT_MODIFIED, tx); 785168404Spjd 786168404Spjd /* 787168404Spjd * Update the file size (zp_size) if it has changed; 788168404Spjd * account for possible concurrent updates. 789168404Spjd */ 790168404Spjd while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset) 791168404Spjd (void) atomic_cas_64(&zp->z_phys->zp_size, end_size, 792168404Spjd uio->uio_loffset); 793168404Spjd zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); 794168404Spjd dmu_tx_commit(tx); 795168404Spjd 796168404Spjd if (error != 0) 797168404Spjd break; 798168404Spjd ASSERT(tx_bytes == nbytes); 799168404Spjd n -= nbytes; 800168404Spjd } 801168404Spjd 802168404Spjd zfs_range_unlock(rl); 803168404Spjd 804168404Spjd /* 805168404Spjd * If we're in replay mode, or we made no progress, return error. 806168404Spjd * Otherwise, it's at least a partial write, so it's successful. 807168404Spjd */ 808168404Spjd if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) { 809168404Spjd ZFS_EXIT(zfsvfs); 810168404Spjd return (error); 811168404Spjd } 812168404Spjd 813168962Spjd if (ioflag & (FSYNC | FDSYNC)) 814168404Spjd zil_commit(zilog, zp->z_last_itx, zp->z_id); 815168404Spjd 816168404Spjd ZFS_EXIT(zfsvfs); 817168404Spjd return (0); 818168404Spjd} 819168404Spjd 820168404Spjdvoid 821168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd) 822168404Spjd{ 823168404Spjd zgd_t *zgd = (zgd_t *)vzgd; 824168404Spjd rl_t *rl = zgd->zgd_rl; 825168404Spjd vnode_t *vp = ZTOV(rl->r_zp); 826168404Spjd int vfslocked; 827168404Spjd 828168404Spjd vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); 829168404Spjd dmu_buf_rele(db, vzgd); 830168404Spjd zfs_range_unlock(rl); 831168404Spjd VN_RELE(vp); 832168404Spjd zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp))); 833168404Spjd kmem_free(zgd, sizeof (zgd_t)); 834168404Spjd VFS_UNLOCK_GIANT(vfslocked); 835168404Spjd} 836168404Spjd 837168404Spjd/* 838168404Spjd * Get data to generate a TX_WRITE intent log record. 839168404Spjd */ 840168404Spjdint 841168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) 842168404Spjd{ 843168404Spjd zfsvfs_t *zfsvfs = arg; 844168404Spjd objset_t *os = zfsvfs->z_os; 845168404Spjd znode_t *zp; 846168404Spjd uint64_t off = lr->lr_offset; 847168404Spjd dmu_buf_t *db; 848168404Spjd rl_t *rl; 849168404Spjd zgd_t *zgd; 850168404Spjd int dlen = lr->lr_length; /* length of user data */ 851168404Spjd int error = 0; 852168404Spjd 853168404Spjd ASSERT(zio); 854168404Spjd ASSERT(dlen != 0); 855168404Spjd 856168404Spjd /* 857168404Spjd * Nothing to do if the file has been removed 858168404Spjd */ 859168404Spjd if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0) 860168404Spjd return (ENOENT); 861168404Spjd if (zp->z_unlinked) { 862168404Spjd VN_RELE(ZTOV(zp)); 863168404Spjd return (ENOENT); 864168404Spjd } 865168404Spjd 866168404Spjd /* 867168404Spjd * Write records come in two flavors: immediate and indirect. 868168404Spjd * For small writes it's cheaper to store the data with the 869168404Spjd * log record (immediate); for large writes it's cheaper to 870168404Spjd * sync the data and get a pointer to it (indirect) so that 871168404Spjd * we don't have to write the data twice. 872168404Spjd */ 873168404Spjd if (buf != NULL) { /* immediate write */ 874168404Spjd rl = zfs_range_lock(zp, off, dlen, RL_READER); 875168404Spjd /* test for truncation needs to be done while range locked */ 876168404Spjd if (off >= zp->z_phys->zp_size) { 877168404Spjd error = ENOENT; 878168404Spjd goto out; 879168404Spjd } 880168404Spjd VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf)); 881168404Spjd } else { /* indirect write */ 882168404Spjd uint64_t boff; /* block starting offset */ 883168404Spjd 884168404Spjd /* 885168404Spjd * Have to lock the whole block to ensure when it's 886168404Spjd * written out and it's checksum is being calculated 887168404Spjd * that no one can change the data. We need to re-check 888168404Spjd * blocksize after we get the lock in case it's changed! 889168404Spjd */ 890168404Spjd for (;;) { 891168404Spjd if (ISP2(zp->z_blksz)) { 892168404Spjd boff = P2ALIGN_TYPED(off, zp->z_blksz, 893168404Spjd uint64_t); 894168404Spjd } else { 895168404Spjd boff = 0; 896168404Spjd } 897168404Spjd dlen = zp->z_blksz; 898168404Spjd rl = zfs_range_lock(zp, boff, dlen, RL_READER); 899168404Spjd if (zp->z_blksz == dlen) 900168404Spjd break; 901168404Spjd zfs_range_unlock(rl); 902168404Spjd } 903168404Spjd /* test for truncation needs to be done while range locked */ 904168404Spjd if (off >= zp->z_phys->zp_size) { 905168404Spjd error = ENOENT; 906168404Spjd goto out; 907168404Spjd } 908168404Spjd zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP); 909168404Spjd zgd->zgd_rl = rl; 910168404Spjd zgd->zgd_zilog = zfsvfs->z_log; 911168404Spjd zgd->zgd_bp = &lr->lr_blkptr; 912168404Spjd VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db)); 913168404Spjd ASSERT(boff == db->db_offset); 914168404Spjd lr->lr_blkoff = off - boff; 915168404Spjd error = dmu_sync(zio, db, &lr->lr_blkptr, 916168404Spjd lr->lr_common.lrc_txg, zfs_get_done, zgd); 917168404Spjd ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz); 918168404Spjd if (error == 0) { 919168404Spjd zil_add_vdev(zfsvfs->z_log, 920168404Spjd DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr))); 921168404Spjd } 922168404Spjd /* 923168404Spjd * If we get EINPROGRESS, then we need to wait for a 924168404Spjd * write IO initiated by dmu_sync() to complete before 925168404Spjd * we can release this dbuf. We will finish everything 926168404Spjd * up in the zfs_get_done() callback. 927168404Spjd */ 928168404Spjd if (error == EINPROGRESS) 929168404Spjd return (0); 930168404Spjd dmu_buf_rele(db, zgd); 931168404Spjd kmem_free(zgd, sizeof (zgd_t)); 932168404Spjd } 933168404Spjdout: 934168404Spjd zfs_range_unlock(rl); 935168404Spjd VN_RELE(ZTOV(zp)); 936168404Spjd return (error); 937168404Spjd} 938168404Spjd 939168404Spjd/*ARGSUSED*/ 940168404Spjdstatic int 941168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr) 942168404Spjd{ 943168404Spjd znode_t *zp = VTOZ(vp); 944168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 945168404Spjd int error; 946168404Spjd 947168404Spjd ZFS_ENTER(zfsvfs); 948168962Spjd error = zfs_zaccess_rwx(zp, mode, cr); 949168404Spjd ZFS_EXIT(zfsvfs); 950168404Spjd return (error); 951168404Spjd} 952168404Spjd 953168404Spjd/* 954168404Spjd * Lookup an entry in a directory, or an extended attribute directory. 955168404Spjd * If it exists, return a held vnode reference for it. 956168404Spjd * 957168404Spjd * IN: dvp - vnode of directory to search. 958168404Spjd * nm - name of entry to lookup. 959168404Spjd * pnp - full pathname to lookup [UNUSED]. 960168404Spjd * flags - LOOKUP_XATTR set if looking for an attribute. 961168404Spjd * rdir - root directory vnode [UNUSED]. 962168404Spjd * cr - credentials of caller. 963168404Spjd * 964168404Spjd * OUT: vpp - vnode of located entry, NULL if not found. 965168404Spjd * 966168404Spjd * RETURN: 0 if success 967168404Spjd * error code if failure 968168404Spjd * 969168404Spjd * Timestamps: 970168404Spjd * NA 971168404Spjd */ 972168404Spjd/* ARGSUSED */ 973168962Spjdstatic int 974168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, 975168962Spjd int nameiop, cred_t *cr, kthread_t *td) 976168404Spjd{ 977168404Spjd 978168962Spjd znode_t *zdp = VTOZ(dvp); 979168962Spjd zfsvfs_t *zfsvfs = zdp->z_zfsvfs; 980168962Spjd int error; 981168404Spjd 982168404Spjd ZFS_ENTER(zfsvfs); 983168404Spjd 984168404Spjd *vpp = NULL; 985168404Spjd 986168404Spjd#ifdef TODO 987168404Spjd if (flags & LOOKUP_XATTR) { 988168404Spjd /* 989168404Spjd * If the xattr property is off, refuse the lookup request. 990168404Spjd */ 991168404Spjd if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) { 992168404Spjd ZFS_EXIT(zfsvfs); 993168404Spjd return (EINVAL); 994168404Spjd } 995168404Spjd 996168404Spjd /* 997168404Spjd * We don't allow recursive attributes.. 998168404Spjd * Maybe someday we will. 999168404Spjd */ 1000168404Spjd if (zdp->z_phys->zp_flags & ZFS_XATTR) { 1001168404Spjd ZFS_EXIT(zfsvfs); 1002168404Spjd return (EINVAL); 1003168404Spjd } 1004168404Spjd 1005168404Spjd if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) { 1006168404Spjd ZFS_EXIT(zfsvfs); 1007168404Spjd return (error); 1008168404Spjd } 1009168404Spjd 1010168404Spjd /* 1011168404Spjd * Do we have permission to get into attribute directory? 1012168404Spjd */ 1013168404Spjd 1014168404Spjd if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) { 1015168404Spjd VN_RELE(*vpp); 1016168404Spjd } 1017168404Spjd 1018168404Spjd ZFS_EXIT(zfsvfs); 1019168404Spjd return (error); 1020168404Spjd } 1021168404Spjd#endif /* TODO */ 1022168404Spjd 1023168404Spjd if (dvp->v_type != VDIR) { 1024168404Spjd ZFS_EXIT(zfsvfs); 1025168404Spjd return (ENOTDIR); 1026168404Spjd } 1027168404Spjd 1028168404Spjd /* 1029168404Spjd * Check accessibility of directory. 1030168404Spjd */ 1031168404Spjd 1032168404Spjd if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) { 1033168404Spjd ZFS_EXIT(zfsvfs); 1034168404Spjd return (error); 1035168404Spjd } 1036168404Spjd 1037168962Spjd if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) { 1038168404Spjd 1039168962Spjd /* 1040168962Spjd * Convert device special files 1041168962Spjd */ 1042168962Spjd if (IS_DEVVP(*vpp)) { 1043168962Spjd vnode_t *svp; 1044168962Spjd 1045168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1046168962Spjd VN_RELE(*vpp); 1047168962Spjd if (svp == NULL) 1048168962Spjd error = ENOSYS; 1049168962Spjd else 1050168962Spjd *vpp = svp; 1051168962Spjd } 1052168962Spjd } 1053168962Spjd 1054168404Spjd ZFS_EXIT(zfsvfs); 1055168404Spjd 1056168404Spjd /* Translate errors and add SAVENAME when needed. */ 1057168404Spjd if (cnp->cn_flags & ISLASTCN) { 1058168404Spjd switch (nameiop) { 1059168404Spjd case CREATE: 1060168404Spjd case RENAME: 1061168404Spjd if (error == ENOENT) { 1062168404Spjd error = EJUSTRETURN; 1063168404Spjd cnp->cn_flags |= SAVENAME; 1064168404Spjd break; 1065168404Spjd } 1066168404Spjd /* FALLTHROUGH */ 1067168404Spjd case DELETE: 1068168404Spjd if (error == 0) 1069168404Spjd cnp->cn_flags |= SAVENAME; 1070168404Spjd break; 1071168404Spjd } 1072168404Spjd } 1073168404Spjd if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) { 1074168962Spjd if (cnp->cn_flags & ISDOTDOT) 1075168404Spjd VOP_UNLOCK(dvp, 0, td); 1076168404Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 1077168962Spjd if (cnp->cn_flags & ISDOTDOT) 1078168404Spjd vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); 1079168404Spjd } 1080168404Spjd 1081168404Spjd#ifdef FREEBSD_NAMECACHE 1082168404Spjd /* 1083168404Spjd * Insert name into cache (as non-existent) if appropriate. 1084168404Spjd */ 1085168404Spjd if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 1086168404Spjd cache_enter(dvp, *vpp, cnp); 1087168404Spjd /* 1088168404Spjd * Insert name into cache if appropriate. 1089168404Spjd */ 1090168404Spjd if (error == 0 && (cnp->cn_flags & MAKEENTRY)) { 1091168404Spjd if (!(cnp->cn_flags & ISLASTCN) || 1092168404Spjd (nameiop != DELETE && nameiop != RENAME)) { 1093168404Spjd cache_enter(dvp, *vpp, cnp); 1094168404Spjd } 1095168404Spjd } 1096168404Spjd#endif 1097168404Spjd 1098168404Spjd return (error); 1099168404Spjd} 1100168404Spjd 1101168404Spjd/* 1102168404Spjd * Attempt to create a new entry in a directory. If the entry 1103168404Spjd * already exists, truncate the file if permissible, else return 1104168404Spjd * an error. Return the vp of the created or trunc'd file. 1105168404Spjd * 1106168404Spjd * IN: dvp - vnode of directory to put new file entry in. 1107168404Spjd * name - name of new file entry. 1108168404Spjd * vap - attributes of new file. 1109168404Spjd * excl - flag indicating exclusive or non-exclusive mode. 1110168404Spjd * mode - mode to open file with. 1111168404Spjd * cr - credentials of caller. 1112168404Spjd * flag - large file flag [UNUSED]. 1113168404Spjd * 1114168404Spjd * OUT: vpp - vnode of created or trunc'd entry. 1115168404Spjd * 1116168404Spjd * RETURN: 0 if success 1117168404Spjd * error code if failure 1118168404Spjd * 1119168404Spjd * Timestamps: 1120168404Spjd * dvp - ctime|mtime updated if new entry created 1121168404Spjd * vp - ctime|mtime always, atime if new 1122168404Spjd */ 1123168404Spjd/* ARGSUSED */ 1124168404Spjdstatic int 1125168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode, 1126168962Spjd vnode_t **vpp, cred_t *cr, kthread_t *td) 1127168404Spjd{ 1128168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1129168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1130168404Spjd zilog_t *zilog = zfsvfs->z_log; 1131168404Spjd objset_t *os = zfsvfs->z_os; 1132168404Spjd zfs_dirlock_t *dl; 1133168404Spjd dmu_tx_t *tx; 1134168404Spjd int error; 1135168404Spjd uint64_t zoid; 1136168404Spjd 1137168404Spjd ZFS_ENTER(zfsvfs); 1138168404Spjd 1139168404Spjdtop: 1140168404Spjd *vpp = NULL; 1141168404Spjd 1142168404Spjd if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr)) 1143168404Spjd vap->va_mode &= ~VSVTX; 1144168404Spjd 1145168404Spjd if (*name == '\0') { 1146168404Spjd /* 1147168404Spjd * Null component name refers to the directory itself. 1148168404Spjd */ 1149168404Spjd VN_HOLD(dvp); 1150168404Spjd zp = dzp; 1151168404Spjd dl = NULL; 1152168404Spjd error = 0; 1153168404Spjd } else { 1154168404Spjd /* possible VN_HOLD(zp) */ 1155168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) { 1156168404Spjd if (strcmp(name, "..") == 0) 1157168404Spjd error = EISDIR; 1158168404Spjd ZFS_EXIT(zfsvfs); 1159168404Spjd return (error); 1160168404Spjd } 1161168404Spjd } 1162168404Spjd 1163168404Spjd zoid = zp ? zp->z_id : -1ULL; 1164168404Spjd 1165168404Spjd if (zp == NULL) { 1166168404Spjd /* 1167168404Spjd * Create a new file object and update the directory 1168168404Spjd * to reference it. 1169168404Spjd */ 1170168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 1171168404Spjd goto out; 1172168404Spjd } 1173168404Spjd 1174168404Spjd /* 1175168404Spjd * We only support the creation of regular files in 1176168404Spjd * extended attribute directories. 1177168404Spjd */ 1178168404Spjd if ((dzp->z_phys->zp_flags & ZFS_XATTR) && 1179168404Spjd (vap->va_type != VREG)) { 1180168404Spjd error = EINVAL; 1181168404Spjd goto out; 1182168404Spjd } 1183168404Spjd 1184168404Spjd tx = dmu_tx_create(os); 1185168404Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1186168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 1187168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 1188168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1189168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1190168404Spjd 0, SPA_MAXBLOCKSIZE); 1191168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1192168404Spjd if (error) { 1193168404Spjd zfs_dirent_unlock(dl); 1194168404Spjd if (error == ERESTART && 1195168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1196168404Spjd dmu_tx_wait(tx); 1197168404Spjd dmu_tx_abort(tx); 1198168404Spjd goto top; 1199168404Spjd } 1200168404Spjd dmu_tx_abort(tx); 1201168404Spjd ZFS_EXIT(zfsvfs); 1202168404Spjd return (error); 1203168404Spjd } 1204168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1205168404Spjd ASSERT(zp->z_id == zoid); 1206168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1207168404Spjd zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name); 1208168404Spjd dmu_tx_commit(tx); 1209168404Spjd } else { 1210168404Spjd /* 1211168404Spjd * A directory entry already exists for this name. 1212168404Spjd */ 1213168404Spjd /* 1214168962Spjd * Can't truncate an existing file if in exclusive mode. 1215168962Spjd */ 1216168962Spjd if (excl == EXCL) { 1217168962Spjd error = EEXIST; 1218168962Spjd goto out; 1219168962Spjd } 1220168962Spjd /* 1221168404Spjd * Can't open a directory for writing. 1222168404Spjd */ 1223168404Spjd if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) { 1224168404Spjd error = EISDIR; 1225168404Spjd goto out; 1226168404Spjd } 1227168404Spjd /* 1228168404Spjd * Verify requested access to file. 1229168404Spjd */ 1230168404Spjd if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) { 1231168404Spjd goto out; 1232168404Spjd } 1233168404Spjd 1234168404Spjd mutex_enter(&dzp->z_lock); 1235168404Spjd dzp->z_seq++; 1236168404Spjd mutex_exit(&dzp->z_lock); 1237168404Spjd 1238168404Spjd /* 1239168404Spjd * Truncate regular files if requested. 1240168404Spjd */ 1241168404Spjd if ((ZTOV(zp)->v_type == VREG) && 1242168404Spjd (zp->z_phys->zp_size != 0) && 1243168404Spjd (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) { 1244168404Spjd error = zfs_freesp(zp, 0, 0, mode, TRUE); 1245168404Spjd if (error == ERESTART && 1246168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1247168404Spjd /* NB: we already did dmu_tx_wait() */ 1248168404Spjd zfs_dirent_unlock(dl); 1249168404Spjd VN_RELE(ZTOV(zp)); 1250168404Spjd goto top; 1251168404Spjd } 1252168404Spjd } 1253168404Spjd } 1254168404Spjdout: 1255168404Spjd 1256168404Spjd if (error == 0) { 1257168404Spjd *vpp = ZTOV(zp); 1258168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 1259168404Spjd } 1260168404Spjd 1261168404Spjd if (dl) 1262168404Spjd zfs_dirent_unlock(dl); 1263168404Spjd 1264168404Spjd if (error) { 1265168404Spjd if (zp) 1266168404Spjd VN_RELE(ZTOV(zp)); 1267168962Spjd } else { 1268168962Spjd *vpp = ZTOV(zp); 1269168962Spjd /* 1270168962Spjd * If vnode is for a device return a specfs vnode instead. 1271168962Spjd */ 1272168962Spjd if (IS_DEVVP(*vpp)) { 1273168962Spjd struct vnode *svp; 1274168962Spjd 1275168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1276168962Spjd VN_RELE(*vpp); 1277168962Spjd if (svp == NULL) { 1278168962Spjd error = ENOSYS; 1279168962Spjd } 1280168962Spjd *vpp = svp; 1281168962Spjd } 1282168404Spjd } 1283168404Spjd 1284168404Spjd ZFS_EXIT(zfsvfs); 1285168404Spjd return (error); 1286168404Spjd} 1287168404Spjd 1288168404Spjd/* 1289168404Spjd * Remove an entry from a directory. 1290168404Spjd * 1291168404Spjd * IN: dvp - vnode of directory to remove entry from. 1292168404Spjd * name - name of entry to remove. 1293168404Spjd * cr - credentials of caller. 1294168404Spjd * 1295168404Spjd * RETURN: 0 if success 1296168404Spjd * error code if failure 1297168404Spjd * 1298168404Spjd * Timestamps: 1299168404Spjd * dvp - ctime|mtime 1300168404Spjd * vp - ctime (if nlink > 0) 1301168404Spjd */ 1302168404Spjdstatic int 1303168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr) 1304168404Spjd{ 1305168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1306168404Spjd znode_t *xzp = NULL; 1307168404Spjd vnode_t *vp; 1308168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1309168404Spjd zilog_t *zilog = zfsvfs->z_log; 1310168962Spjd uint64_t acl_obj, xattr_obj; 1311168404Spjd zfs_dirlock_t *dl; 1312168404Spjd dmu_tx_t *tx; 1313168962Spjd boolean_t may_delete_now, delete_now = FALSE; 1314168404Spjd boolean_t unlinked; 1315168404Spjd int error; 1316168404Spjd 1317168404Spjd ZFS_ENTER(zfsvfs); 1318168404Spjd 1319168404Spjdtop: 1320168404Spjd /* 1321168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1322168404Spjd */ 1323168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1324168404Spjd ZFS_EXIT(zfsvfs); 1325168404Spjd return (error); 1326168404Spjd } 1327168404Spjd 1328168404Spjd vp = ZTOV(zp); 1329168404Spjd 1330168962Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1331168404Spjd goto out; 1332168962Spjd } 1333168404Spjd 1334168962Spjd /* 1335168962Spjd * Need to use rmdir for removing directories. 1336168962Spjd */ 1337168962Spjd if (vp->v_type == VDIR) { 1338168962Spjd error = EPERM; 1339168962Spjd goto out; 1340168962Spjd } 1341168962Spjd 1342168962Spjd vnevent_remove(vp); 1343168962Spjd 1344168404Spjd dnlc_remove(dvp, name); 1345168404Spjd 1346168962Spjd may_delete_now = FALSE; 1347168962Spjd 1348168404Spjd /* 1349168404Spjd * We may delete the znode now, or we may put it in the unlinked set; 1350168404Spjd * it depends on whether we're the last link, and on whether there are 1351168404Spjd * other holds on the vnode. So we dmu_tx_hold() the right things to 1352168404Spjd * allow for either case. 1353168404Spjd */ 1354168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1355168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1356168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1357168962Spjd if (may_delete_now) 1358168962Spjd dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END); 1359168404Spjd 1360168404Spjd /* are there any extended attributes? */ 1361168404Spjd if ((xattr_obj = zp->z_phys->zp_xattr) != 0) { 1362168404Spjd /* XXX - do we need this if we are deleting? */ 1363168404Spjd dmu_tx_hold_bonus(tx, xattr_obj); 1364168404Spjd } 1365168404Spjd 1366168962Spjd /* are there any additional acls */ 1367168962Spjd if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 && 1368168962Spjd may_delete_now) 1369168962Spjd dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); 1370168962Spjd 1371168404Spjd /* charge as an update -- would be nice not to charge at all */ 1372168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1373168404Spjd 1374168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1375168404Spjd if (error) { 1376168404Spjd zfs_dirent_unlock(dl); 1377168962Spjd VN_RELE(vp); 1378168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1379168404Spjd dmu_tx_wait(tx); 1380168404Spjd dmu_tx_abort(tx); 1381168404Spjd goto top; 1382168404Spjd } 1383168404Spjd dmu_tx_abort(tx); 1384168404Spjd ZFS_EXIT(zfsvfs); 1385168404Spjd return (error); 1386168404Spjd } 1387168404Spjd 1388168404Spjd /* 1389168404Spjd * Remove the directory entry. 1390168404Spjd */ 1391168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, &unlinked); 1392168404Spjd 1393168404Spjd if (error) { 1394168404Spjd dmu_tx_commit(tx); 1395168404Spjd goto out; 1396168404Spjd } 1397168404Spjd 1398168962Spjd if (0 && unlinked) { 1399168962Spjd VI_LOCK(vp); 1400168962Spjd delete_now = may_delete_now && 1401168962Spjd vp->v_count == 1 && !vn_has_cached_data(vp) && 1402168962Spjd zp->z_phys->zp_xattr == xattr_obj && 1403168962Spjd zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj; 1404168962Spjd VI_UNLOCK(vp); 1405168962Spjd } 1406168962Spjd 1407168962Spjd if (delete_now) { 1408168962Spjd if (zp->z_phys->zp_xattr) { 1409168962Spjd error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp); 1410168962Spjd ASSERT3U(error, ==, 0); 1411168962Spjd ASSERT3U(xzp->z_phys->zp_links, ==, 2); 1412168962Spjd dmu_buf_will_dirty(xzp->z_dbuf, tx); 1413168962Spjd mutex_enter(&xzp->z_lock); 1414168962Spjd xzp->z_unlinked = 1; 1415168962Spjd xzp->z_phys->zp_links = 0; 1416168962Spjd mutex_exit(&xzp->z_lock); 1417168962Spjd zfs_unlinked_add(xzp, tx); 1418168962Spjd zp->z_phys->zp_xattr = 0; /* probably unnecessary */ 1419168962Spjd } 1420168962Spjd mutex_enter(&zp->z_lock); 1421168962Spjd VI_LOCK(vp); 1422168962Spjd vp->v_count--; 1423168962Spjd ASSERT3U(vp->v_count, ==, 0); 1424168962Spjd VI_UNLOCK(vp); 1425168962Spjd mutex_exit(&zp->z_lock); 1426168962Spjd zfs_znode_delete(zp, tx); 1427168962Spjd VFS_RELE(zfsvfs->z_vfs); 1428168962Spjd } else if (unlinked) { 1429168404Spjd zfs_unlinked_add(zp, tx); 1430168962Spjd } 1431168404Spjd 1432168404Spjd zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name); 1433168404Spjd 1434168404Spjd dmu_tx_commit(tx); 1435168404Spjdout: 1436168404Spjd zfs_dirent_unlock(dl); 1437168404Spjd 1438168962Spjd if (!delete_now) { 1439168962Spjd VN_RELE(vp); 1440168962Spjd } else if (xzp) { 1441168962Spjd /* this rele delayed to prevent nesting transactions */ 1442168962Spjd VN_RELE(ZTOV(xzp)); 1443168962Spjd } 1444168962Spjd 1445168404Spjd ZFS_EXIT(zfsvfs); 1446168404Spjd return (error); 1447168404Spjd} 1448168404Spjd 1449168404Spjd/* 1450168404Spjd * Create a new directory and insert it into dvp using the name 1451168404Spjd * provided. Return a pointer to the inserted directory. 1452168404Spjd * 1453168404Spjd * IN: dvp - vnode of directory to add subdir to. 1454168404Spjd * dirname - name of new directory. 1455168404Spjd * vap - attributes of new directory. 1456168404Spjd * cr - credentials of caller. 1457168404Spjd * 1458168404Spjd * OUT: vpp - vnode of created directory. 1459168404Spjd * 1460168404Spjd * RETURN: 0 if success 1461168404Spjd * error code if failure 1462168404Spjd * 1463168404Spjd * Timestamps: 1464168404Spjd * dvp - ctime|mtime updated 1465168404Spjd * vp - ctime|mtime|atime updated 1466168404Spjd */ 1467168404Spjdstatic int 1468168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr) 1469168404Spjd{ 1470168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1471168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1472168404Spjd zilog_t *zilog = zfsvfs->z_log; 1473168404Spjd zfs_dirlock_t *dl; 1474168404Spjd uint64_t zoid = 0; 1475168404Spjd dmu_tx_t *tx; 1476168404Spjd int error; 1477168404Spjd 1478168404Spjd ASSERT(vap->va_type == VDIR); 1479168404Spjd 1480168404Spjd ZFS_ENTER(zfsvfs); 1481168404Spjd 1482168404Spjd if (dzp->z_phys->zp_flags & ZFS_XATTR) { 1483168404Spjd ZFS_EXIT(zfsvfs); 1484168404Spjd return (EINVAL); 1485168404Spjd } 1486168404Spjdtop: 1487168404Spjd *vpp = NULL; 1488168404Spjd 1489168404Spjd /* 1490168404Spjd * First make sure the new directory doesn't exist. 1491168404Spjd */ 1492168404Spjd if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) { 1493168404Spjd ZFS_EXIT(zfsvfs); 1494168404Spjd return (error); 1495168404Spjd } 1496168404Spjd 1497168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) { 1498168404Spjd zfs_dirent_unlock(dl); 1499168404Spjd ZFS_EXIT(zfsvfs); 1500168404Spjd return (error); 1501168404Spjd } 1502168404Spjd 1503168404Spjd /* 1504168404Spjd * Add a new entry to the directory. 1505168404Spjd */ 1506168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1507168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname); 1508168404Spjd dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 1509168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1510168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1511168404Spjd 0, SPA_MAXBLOCKSIZE); 1512168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1513168404Spjd if (error) { 1514168404Spjd zfs_dirent_unlock(dl); 1515168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1516168404Spjd dmu_tx_wait(tx); 1517168404Spjd dmu_tx_abort(tx); 1518168404Spjd goto top; 1519168404Spjd } 1520168404Spjd dmu_tx_abort(tx); 1521168404Spjd ZFS_EXIT(zfsvfs); 1522168404Spjd return (error); 1523168404Spjd } 1524168404Spjd 1525168404Spjd /* 1526168404Spjd * Create new node. 1527168404Spjd */ 1528168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1529168404Spjd 1530168404Spjd /* 1531168404Spjd * Now put new name in parent dir. 1532168404Spjd */ 1533168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1534168404Spjd 1535168404Spjd *vpp = ZTOV(zp); 1536168404Spjd 1537168404Spjd zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname); 1538168404Spjd dmu_tx_commit(tx); 1539168404Spjd 1540168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread); 1541168404Spjd 1542168404Spjd zfs_dirent_unlock(dl); 1543168404Spjd 1544168404Spjd ZFS_EXIT(zfsvfs); 1545168404Spjd return (0); 1546168404Spjd} 1547168404Spjd 1548168404Spjd/* 1549168404Spjd * Remove a directory subdir entry. If the current working 1550168404Spjd * directory is the same as the subdir to be removed, the 1551168404Spjd * remove will fail. 1552168404Spjd * 1553168404Spjd * IN: dvp - vnode of directory to remove from. 1554168404Spjd * name - name of directory to be removed. 1555168404Spjd * cwd - vnode of current working directory. 1556168404Spjd * cr - credentials of caller. 1557168404Spjd * 1558168404Spjd * RETURN: 0 if success 1559168404Spjd * error code if failure 1560168404Spjd * 1561168404Spjd * Timestamps: 1562168404Spjd * dvp - ctime|mtime updated 1563168404Spjd */ 1564168404Spjdstatic int 1565168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr) 1566168404Spjd{ 1567168404Spjd znode_t *dzp = VTOZ(dvp); 1568168404Spjd znode_t *zp; 1569168404Spjd vnode_t *vp; 1570168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1571168404Spjd zilog_t *zilog = zfsvfs->z_log; 1572168404Spjd zfs_dirlock_t *dl; 1573168404Spjd dmu_tx_t *tx; 1574168404Spjd int error; 1575168404Spjd 1576168962Spjd ZFS_ENTER(zfsvfs); 1577168404Spjd 1578168404Spjdtop: 1579168404Spjd zp = NULL; 1580168404Spjd 1581168404Spjd /* 1582168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1583168404Spjd */ 1584168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1585168404Spjd ZFS_EXIT(zfsvfs); 1586168404Spjd return (error); 1587168404Spjd } 1588168404Spjd 1589168404Spjd vp = ZTOV(zp); 1590168404Spjd 1591168404Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1592168404Spjd goto out; 1593168404Spjd } 1594168404Spjd 1595168962Spjd if (vp->v_type != VDIR) { 1596168962Spjd error = ENOTDIR; 1597168962Spjd goto out; 1598168962Spjd } 1599168962Spjd 1600168962Spjd if (vp == cwd) { 1601168962Spjd error = EINVAL; 1602168962Spjd goto out; 1603168962Spjd } 1604168962Spjd 1605168962Spjd vnevent_rmdir(vp); 1606168962Spjd 1607168404Spjd /* 1608168404Spjd * Grab a lock on the directory to make sure that noone is 1609168404Spjd * trying to add (or lookup) entries while we are removing it. 1610168404Spjd */ 1611168404Spjd rw_enter(&zp->z_name_lock, RW_WRITER); 1612168404Spjd 1613168404Spjd /* 1614168404Spjd * Grab a lock on the parent pointer to make sure we play well 1615168404Spjd * with the treewalk and directory rename code. 1616168404Spjd */ 1617168404Spjd rw_enter(&zp->z_parent_lock, RW_WRITER); 1618168404Spjd 1619168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1620168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1621168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1622168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1623168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1624168404Spjd if (error) { 1625168404Spjd rw_exit(&zp->z_parent_lock); 1626168404Spjd rw_exit(&zp->z_name_lock); 1627168404Spjd zfs_dirent_unlock(dl); 1628168962Spjd VN_RELE(vp); 1629168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1630168404Spjd dmu_tx_wait(tx); 1631168404Spjd dmu_tx_abort(tx); 1632168404Spjd goto top; 1633168404Spjd } 1634168404Spjd dmu_tx_abort(tx); 1635168404Spjd ZFS_EXIT(zfsvfs); 1636168404Spjd return (error); 1637168404Spjd } 1638168404Spjd 1639168404Spjd#ifdef FREEBSD_NAMECACHE 1640168404Spjd cache_purge(dvp); 1641168404Spjd#endif 1642168404Spjd 1643168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, NULL); 1644168404Spjd 1645168404Spjd if (error == 0) 1646168404Spjd zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name); 1647168404Spjd 1648168404Spjd dmu_tx_commit(tx); 1649168404Spjd 1650168404Spjd rw_exit(&zp->z_parent_lock); 1651168404Spjd rw_exit(&zp->z_name_lock); 1652168404Spjd#ifdef FREEBSD_NAMECACHE 1653168404Spjd cache_purge(vp); 1654168404Spjd#endif 1655168404Spjdout: 1656168404Spjd zfs_dirent_unlock(dl); 1657168404Spjd 1658168962Spjd VN_RELE(vp); 1659168962Spjd 1660168404Spjd ZFS_EXIT(zfsvfs); 1661168404Spjd return (error); 1662168404Spjd} 1663168404Spjd 1664168404Spjd/* 1665168404Spjd * Read as many directory entries as will fit into the provided 1666168404Spjd * buffer from the given directory cursor position (specified in 1667168404Spjd * the uio structure. 1668168404Spjd * 1669168404Spjd * IN: vp - vnode of directory to read. 1670168404Spjd * uio - structure supplying read location, range info, 1671168404Spjd * and return buffer. 1672168404Spjd * cr - credentials of caller. 1673168404Spjd * 1674168404Spjd * OUT: uio - updated offset and range, buffer filled. 1675168404Spjd * eofp - set to true if end-of-file detected. 1676168404Spjd * 1677168404Spjd * RETURN: 0 if success 1678168404Spjd * error code if failure 1679168404Spjd * 1680168404Spjd * Timestamps: 1681168404Spjd * vp - atime updated 1682168404Spjd * 1683168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero. 1684168404Spjd * This allows us to use the low range for "special" directory entries: 1685168404Spjd * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, 1686168404Spjd * we use the offset 2 for the '.zfs' directory. 1687168404Spjd */ 1688168404Spjd/* ARGSUSED */ 1689168404Spjdstatic int 1690168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies) 1691168404Spjd{ 1692168404Spjd znode_t *zp = VTOZ(vp); 1693168404Spjd iovec_t *iovp; 1694168404Spjd dirent64_t *odp; 1695168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1696168404Spjd objset_t *os; 1697168404Spjd caddr_t outbuf; 1698168404Spjd size_t bufsize; 1699168404Spjd zap_cursor_t zc; 1700168404Spjd zap_attribute_t zap; 1701168404Spjd uint_t bytes_wanted; 1702168404Spjd uint64_t offset; /* must be unsigned; checks for < 1 */ 1703168404Spjd int local_eof; 1704168404Spjd int outcount; 1705168404Spjd int error; 1706168404Spjd uint8_t prefetch; 1707168404Spjd uint8_t type; 1708168962Spjd int ncooks; 1709168962Spjd u_long *cooks = NULL; 1710168404Spjd 1711168404Spjd ZFS_ENTER(zfsvfs); 1712168404Spjd 1713168404Spjd /* 1714168404Spjd * If we are not given an eof variable, 1715168404Spjd * use a local one. 1716168404Spjd */ 1717168404Spjd if (eofp == NULL) 1718168404Spjd eofp = &local_eof; 1719168404Spjd 1720168404Spjd /* 1721168404Spjd * Check for valid iov_len. 1722168404Spjd */ 1723168404Spjd if (uio->uio_iov->iov_len <= 0) { 1724168404Spjd ZFS_EXIT(zfsvfs); 1725168404Spjd return (EINVAL); 1726168404Spjd } 1727168404Spjd 1728168404Spjd /* 1729168404Spjd * Quit if directory has been removed (posix) 1730168404Spjd */ 1731168404Spjd if ((*eofp = zp->z_unlinked) != 0) { 1732168404Spjd ZFS_EXIT(zfsvfs); 1733168404Spjd return (0); 1734168404Spjd } 1735168404Spjd 1736168404Spjd error = 0; 1737168404Spjd os = zfsvfs->z_os; 1738168404Spjd offset = uio->uio_loffset; 1739168404Spjd prefetch = zp->z_zn_prefetch; 1740168404Spjd 1741168404Spjd /* 1742168404Spjd * Initialize the iterator cursor. 1743168404Spjd */ 1744168404Spjd if (offset <= 3) { 1745168404Spjd /* 1746168404Spjd * Start iteration from the beginning of the directory. 1747168404Spjd */ 1748168404Spjd zap_cursor_init(&zc, os, zp->z_id); 1749168404Spjd } else { 1750168404Spjd /* 1751168404Spjd * The offset is a serialized cursor. 1752168404Spjd */ 1753168404Spjd zap_cursor_init_serialized(&zc, os, zp->z_id, offset); 1754168404Spjd } 1755168404Spjd 1756168404Spjd /* 1757168404Spjd * Get space to change directory entries into fs independent format. 1758168404Spjd */ 1759168404Spjd iovp = uio->uio_iov; 1760168404Spjd bytes_wanted = iovp->iov_len; 1761168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { 1762168404Spjd bufsize = bytes_wanted; 1763168404Spjd outbuf = kmem_alloc(bufsize, KM_SLEEP); 1764168404Spjd odp = (struct dirent64 *)outbuf; 1765168404Spjd } else { 1766168404Spjd bufsize = bytes_wanted; 1767168404Spjd odp = (struct dirent64 *)iovp->iov_base; 1768168404Spjd } 1769168404Spjd 1770168962Spjd if (ncookies != NULL) { 1771168404Spjd /* 1772168404Spjd * Minimum entry size is dirent size and 1 byte for a file name. 1773168404Spjd */ 1774168962Spjd ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1); 1775168962Spjd cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK); 1776168962Spjd *cookies = cooks; 1777168962Spjd *ncookies = ncooks; 1778168404Spjd } 1779168404Spjd 1780168404Spjd /* 1781168404Spjd * Transform to file-system independent format 1782168404Spjd */ 1783168404Spjd outcount = 0; 1784168404Spjd while (outcount < bytes_wanted) { 1785168404Spjd ino64_t objnum; 1786168404Spjd ushort_t reclen; 1787168404Spjd 1788168404Spjd /* 1789168404Spjd * Special case `.', `..', and `.zfs'. 1790168404Spjd */ 1791168404Spjd if (offset == 0) { 1792168404Spjd (void) strcpy(zap.za_name, "."); 1793168404Spjd objnum = zp->z_id; 1794168404Spjd } else if (offset == 1) { 1795168404Spjd (void) strcpy(zap.za_name, ".."); 1796168404Spjd objnum = zp->z_phys->zp_parent; 1797168404Spjd } else if (offset == 2 && zfs_show_ctldir(zp)) { 1798168404Spjd (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME); 1799168404Spjd objnum = ZFSCTL_INO_ROOT; 1800168404Spjd } else { 1801168404Spjd /* 1802168404Spjd * Grab next entry. 1803168404Spjd */ 1804168404Spjd if (error = zap_cursor_retrieve(&zc, &zap)) { 1805168404Spjd if ((*eofp = (error == ENOENT)) != 0) 1806168404Spjd break; 1807168404Spjd else 1808168404Spjd goto update; 1809168404Spjd } 1810168404Spjd 1811168404Spjd if (zap.za_integer_length != 8 || 1812168404Spjd zap.za_num_integers != 1) { 1813168404Spjd cmn_err(CE_WARN, "zap_readdir: bad directory " 1814168404Spjd "entry, obj = %lld, offset = %lld\n", 1815168404Spjd (u_longlong_t)zp->z_id, 1816168404Spjd (u_longlong_t)offset); 1817168404Spjd error = ENXIO; 1818168404Spjd goto update; 1819168404Spjd } 1820168404Spjd 1821168404Spjd objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); 1822168404Spjd /* 1823168404Spjd * MacOS X can extract the object type here such as: 1824168404Spjd * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1825168404Spjd */ 1826168404Spjd type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1827168404Spjd } 1828168404Spjd reclen = DIRENT64_RECLEN(strlen(zap.za_name)); 1829168404Spjd 1830168404Spjd /* 1831168404Spjd * Will this entry fit in the buffer? 1832168404Spjd */ 1833168404Spjd if (outcount + reclen > bufsize) { 1834168404Spjd /* 1835168404Spjd * Did we manage to fit anything in the buffer? 1836168404Spjd */ 1837168404Spjd if (!outcount) { 1838168404Spjd error = EINVAL; 1839168404Spjd goto update; 1840168404Spjd } 1841168404Spjd break; 1842168404Spjd } 1843168404Spjd /* 1844168404Spjd * Add this entry: 1845168404Spjd */ 1846168404Spjd odp->d_ino = objnum; 1847168404Spjd odp->d_reclen = reclen; 1848168404Spjd odp->d_namlen = strlen(zap.za_name); 1849168404Spjd (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); 1850168404Spjd odp->d_type = type; 1851168404Spjd outcount += reclen; 1852168404Spjd odp = (dirent64_t *)((intptr_t)odp + reclen); 1853168404Spjd 1854168404Spjd ASSERT(outcount <= bufsize); 1855168404Spjd 1856168404Spjd /* Prefetch znode */ 1857168404Spjd if (prefetch) 1858168404Spjd dmu_prefetch(os, objnum, 0, 0); 1859168404Spjd 1860168404Spjd /* 1861168404Spjd * Move to the next entry, fill in the previous offset. 1862168404Spjd */ 1863168404Spjd if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) { 1864168404Spjd zap_cursor_advance(&zc); 1865168404Spjd offset = zap_cursor_serialize(&zc); 1866168404Spjd } else { 1867168404Spjd offset += 1; 1868168404Spjd } 1869168404Spjd 1870168962Spjd if (cooks != NULL) { 1871168962Spjd *cooks++ = offset; 1872168962Spjd ncooks--; 1873168962Spjd KASSERT(ncooks >= 0, ("ncookies=%d", ncooks)); 1874168404Spjd } 1875168404Spjd } 1876168404Spjd zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ 1877168404Spjd 1878168404Spjd /* Subtract unused cookies */ 1879168962Spjd if (ncookies != NULL) 1880168962Spjd *ncookies -= ncooks; 1881168404Spjd 1882168404Spjd if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { 1883168404Spjd iovp->iov_base += outcount; 1884168404Spjd iovp->iov_len -= outcount; 1885168404Spjd uio->uio_resid -= outcount; 1886168404Spjd } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) { 1887168404Spjd /* 1888168404Spjd * Reset the pointer. 1889168404Spjd */ 1890168404Spjd offset = uio->uio_loffset; 1891168404Spjd } 1892168404Spjd 1893168404Spjdupdate: 1894168404Spjd zap_cursor_fini(&zc); 1895168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1896168404Spjd kmem_free(outbuf, bufsize); 1897168404Spjd 1898168404Spjd if (error == ENOENT) 1899168404Spjd error = 0; 1900168404Spjd 1901168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 1902168404Spjd 1903168404Spjd uio->uio_loffset = offset; 1904168404Spjd ZFS_EXIT(zfsvfs); 1905168404Spjd if (error != 0) { 1906168962Spjd free(*cookies, M_TEMP); 1907168962Spjd *cookies = NULL; 1908168962Spjd *ncookies = 0; 1909168404Spjd } 1910168404Spjd return (error); 1911168404Spjd} 1912168404Spjd 1913168404Spjdstatic int 1914168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr) 1915168404Spjd{ 1916168962Spjd znode_t *zp = VTOZ(vp); 1917168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1918168404Spjd 1919168404Spjd ZFS_ENTER(zfsvfs); 1920168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 1921168404Spjd ZFS_EXIT(zfsvfs); 1922168404Spjd return (0); 1923168404Spjd} 1924168404Spjd 1925168404Spjd/* 1926168404Spjd * Get the requested file attributes and place them in the provided 1927168404Spjd * vattr structure. 1928168404Spjd * 1929168404Spjd * IN: vp - vnode of file. 1930168404Spjd * vap - va_mask identifies requested attributes. 1931168404Spjd * flags - [UNUSED] 1932168404Spjd * cr - credentials of caller. 1933168404Spjd * 1934168404Spjd * OUT: vap - attribute values. 1935168404Spjd * 1936168404Spjd * RETURN: 0 (always succeeds) 1937168404Spjd */ 1938168404Spjd/* ARGSUSED */ 1939168404Spjdstatic int 1940168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 1941168404Spjd{ 1942168962Spjd znode_t *zp = VTOZ(vp); 1943168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1944168962Spjd znode_phys_t *pzp = zp->z_phys; 1945168962Spjd uint32_t blksize; 1946168962Spjd u_longlong_t nblocks; 1947168962Spjd int error; 1948168404Spjd 1949168404Spjd ZFS_ENTER(zfsvfs); 1950168404Spjd 1951168404Spjd /* 1952168404Spjd * Return all attributes. It's cheaper to provide the answer 1953168404Spjd * than to determine whether we were asked the question. 1954168404Spjd */ 1955168404Spjd mutex_enter(&zp->z_lock); 1956168404Spjd 1957168404Spjd vap->va_type = IFTOVT(pzp->zp_mode); 1958168404Spjd vap->va_mode = pzp->zp_mode & ~S_IFMT; 1959168404Spjd vap->va_uid = zp->z_phys->zp_uid; 1960168404Spjd vap->va_gid = zp->z_phys->zp_gid; 1961168404Spjd vap->va_nodeid = zp->z_id; 1962168404Spjd vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX); /* nlink_t limit! */ 1963168404Spjd vap->va_size = pzp->zp_size; 1964168404Spjd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 1965168958Spjd vap->va_rdev = zfs_cmpldev(pzp->zp_rdev); 1966168404Spjd vap->va_seq = zp->z_seq; 1967168404Spjd vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */ 1968168404Spjd 1969168404Spjd ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime); 1970168404Spjd ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime); 1971168404Spjd ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime); 1972168404Spjd ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime); 1973168404Spjd 1974168404Spjd /* 1975168404Spjd * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES. 1976168404Spjd * Also, if we are the owner don't bother, since owner should 1977168404Spjd * always be allowed to read basic attributes of file. 1978168404Spjd */ 1979168404Spjd if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) && 1980168404Spjd (zp->z_phys->zp_uid != crgetuid(cr))) { 1981168404Spjd if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) { 1982168404Spjd mutex_exit(&zp->z_lock); 1983168404Spjd ZFS_EXIT(zfsvfs); 1984168404Spjd return (error); 1985168404Spjd } 1986168404Spjd } 1987168404Spjd 1988168404Spjd mutex_exit(&zp->z_lock); 1989168404Spjd 1990168404Spjd dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks); 1991168404Spjd vap->va_blksize = blksize; 1992168404Spjd vap->va_bytes = nblocks << 9; /* nblocks * 512 */ 1993168404Spjd 1994168404Spjd if (zp->z_blksz == 0) { 1995168404Spjd /* 1996168404Spjd * Block size hasn't been set; suggest maximal I/O transfers. 1997168404Spjd */ 1998168404Spjd vap->va_blksize = zfsvfs->z_max_blksz; 1999168404Spjd } 2000168404Spjd 2001168404Spjd ZFS_EXIT(zfsvfs); 2002168404Spjd return (0); 2003168404Spjd} 2004168404Spjd 2005168404Spjd/* 2006168404Spjd * Set the file attributes to the values contained in the 2007168404Spjd * vattr structure. 2008168404Spjd * 2009168404Spjd * IN: vp - vnode of file to be modified. 2010168404Spjd * vap - new attribute values. 2011168404Spjd * flags - ATTR_UTIME set if non-default time values provided. 2012168404Spjd * cr - credentials of caller. 2013168404Spjd * 2014168404Spjd * RETURN: 0 if success 2015168404Spjd * error code if failure 2016168404Spjd * 2017168404Spjd * Timestamps: 2018168404Spjd * vp - ctime updated, mtime updated if size changed. 2019168404Spjd */ 2020168404Spjd/* ARGSUSED */ 2021168404Spjdstatic int 2022168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 2023168962Spjd caller_context_t *ct) 2024168404Spjd{ 2025168962Spjd struct znode *zp = VTOZ(vp); 2026168404Spjd znode_phys_t *pzp = zp->z_phys; 2027168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2028168404Spjd zilog_t *zilog = zfsvfs->z_log; 2029168404Spjd dmu_tx_t *tx; 2030168404Spjd vattr_t oldva; 2031168962Spjd uint_t mask = vap->va_mask; 2032168404Spjd uint_t saved_mask; 2033168404Spjd int trim_mask = 0; 2034168404Spjd uint64_t new_mode; 2035168404Spjd znode_t *attrzp; 2036168404Spjd int need_policy = FALSE; 2037168404Spjd int err; 2038168404Spjd 2039168404Spjd if (mask == 0) 2040168404Spjd return (0); 2041168404Spjd 2042168962Spjd if (mask & AT_NOSET) 2043168962Spjd return (EINVAL); 2044168962Spjd 2045168404Spjd if (mask & AT_SIZE && vp->v_type == VDIR) 2046168404Spjd return (EISDIR); 2047168404Spjd 2048168404Spjd if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) 2049168404Spjd return (EINVAL); 2050168404Spjd 2051168404Spjd ZFS_ENTER(zfsvfs); 2052168404Spjd 2053168404Spjdtop: 2054168404Spjd attrzp = NULL; 2055168404Spjd 2056168404Spjd if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { 2057168404Spjd ZFS_EXIT(zfsvfs); 2058168404Spjd return (EROFS); 2059168404Spjd } 2060168404Spjd 2061168404Spjd /* 2062168404Spjd * First validate permissions 2063168404Spjd */ 2064168404Spjd 2065168404Spjd if (mask & AT_SIZE) { 2066168404Spjd err = zfs_zaccess(zp, ACE_WRITE_DATA, cr); 2067168404Spjd if (err) { 2068168404Spjd ZFS_EXIT(zfsvfs); 2069168404Spjd return (err); 2070168404Spjd } 2071168404Spjd /* 2072168404Spjd * XXX - Note, we are not providing any open 2073168404Spjd * mode flags here (like FNDELAY), so we may 2074168404Spjd * block if there are locks present... this 2075168404Spjd * should be addressed in openat(). 2076168404Spjd */ 2077168404Spjd do { 2078168404Spjd err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); 2079168404Spjd /* NB: we already did dmu_tx_wait() if necessary */ 2080168404Spjd } while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT); 2081168404Spjd if (err) { 2082168404Spjd ZFS_EXIT(zfsvfs); 2083168404Spjd return (err); 2084168404Spjd } 2085168404Spjd } 2086168404Spjd 2087168404Spjd if (mask & (AT_ATIME|AT_MTIME)) 2088168404Spjd need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr); 2089168404Spjd 2090168404Spjd if (mask & (AT_UID|AT_GID)) { 2091168404Spjd int idmask = (mask & (AT_UID|AT_GID)); 2092168404Spjd int take_owner; 2093168404Spjd int take_group; 2094168404Spjd 2095168404Spjd /* 2096168404Spjd * NOTE: even if a new mode is being set, 2097168404Spjd * we may clear S_ISUID/S_ISGID bits. 2098168404Spjd */ 2099168404Spjd 2100168404Spjd if (!(mask & AT_MODE)) 2101168404Spjd vap->va_mode = pzp->zp_mode; 2102168404Spjd 2103168404Spjd /* 2104168404Spjd * Take ownership or chgrp to group we are a member of 2105168404Spjd */ 2106168404Spjd 2107168404Spjd take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr)); 2108168404Spjd take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr); 2109168404Spjd 2110168404Spjd /* 2111168404Spjd * If both AT_UID and AT_GID are set then take_owner and 2112168404Spjd * take_group must both be set in order to allow taking 2113168404Spjd * ownership. 2114168404Spjd * 2115168404Spjd * Otherwise, send the check through secpolicy_vnode_setattr() 2116168404Spjd * 2117168404Spjd */ 2118168404Spjd 2119168404Spjd if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) || 2120168404Spjd ((idmask == AT_UID) && take_owner) || 2121168404Spjd ((idmask == AT_GID) && take_group)) { 2122168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) { 2123168404Spjd /* 2124168404Spjd * Remove setuid/setgid for non-privileged users 2125168404Spjd */ 2126168404Spjd secpolicy_setid_clear(vap, cr); 2127168404Spjd trim_mask = (mask & (AT_UID|AT_GID)); 2128168404Spjd } else { 2129168404Spjd need_policy = TRUE; 2130168404Spjd } 2131168404Spjd } else { 2132168404Spjd need_policy = TRUE; 2133168404Spjd } 2134168404Spjd } 2135168404Spjd 2136168404Spjd mutex_enter(&zp->z_lock); 2137168404Spjd oldva.va_mode = pzp->zp_mode; 2138168404Spjd oldva.va_uid = zp->z_phys->zp_uid; 2139168404Spjd oldva.va_gid = zp->z_phys->zp_gid; 2140168404Spjd mutex_exit(&zp->z_lock); 2141168404Spjd 2142168404Spjd if (mask & AT_MODE) { 2143168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) { 2144168962Spjd err = secpolicy_setid_setsticky_clear(vp, vap, 2145168962Spjd &oldva, cr); 2146168962Spjd if (err) { 2147168962Spjd ZFS_EXIT(zfsvfs); 2148168962Spjd return (err); 2149168962Spjd } 2150168404Spjd trim_mask |= AT_MODE; 2151168404Spjd } else { 2152168404Spjd need_policy = TRUE; 2153168404Spjd } 2154168404Spjd } 2155168404Spjd 2156168404Spjd if (need_policy) { 2157168404Spjd /* 2158168404Spjd * If trim_mask is set then take ownership 2159168404Spjd * has been granted or write_acl is present and user 2160168404Spjd * has the ability to modify mode. In that case remove 2161168404Spjd * UID|GID and or MODE from mask so that 2162168404Spjd * secpolicy_vnode_setattr() doesn't revoke it. 2163168404Spjd */ 2164168404Spjd 2165168404Spjd if (trim_mask) { 2166168404Spjd saved_mask = vap->va_mask; 2167168404Spjd vap->va_mask &= ~trim_mask; 2168168404Spjd 2169168404Spjd } 2170168404Spjd err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 2171168404Spjd (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp); 2172168404Spjd if (err) { 2173168404Spjd ZFS_EXIT(zfsvfs); 2174168404Spjd return (err); 2175168404Spjd } 2176168404Spjd 2177168404Spjd if (trim_mask) 2178168404Spjd vap->va_mask |= saved_mask; 2179168404Spjd } 2180168404Spjd 2181168404Spjd /* 2182168404Spjd * secpolicy_vnode_setattr, or take ownership may have 2183168404Spjd * changed va_mask 2184168404Spjd */ 2185168404Spjd mask = vap->va_mask; 2186168404Spjd 2187168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2188168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2189168404Spjd 2190168404Spjd if (mask & AT_MODE) { 2191168404Spjd uint64_t pmode = pzp->zp_mode; 2192168404Spjd 2193168404Spjd new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); 2194168404Spjd 2195168404Spjd if (zp->z_phys->zp_acl.z_acl_extern_obj) 2196168404Spjd dmu_tx_hold_write(tx, 2197168404Spjd pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE); 2198168404Spjd else 2199168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2200168404Spjd 0, ZFS_ACL_SIZE(MAX_ACL_SIZE)); 2201168404Spjd } 2202168404Spjd 2203168404Spjd if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) { 2204168404Spjd err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp); 2205168404Spjd if (err) { 2206168404Spjd dmu_tx_abort(tx); 2207168404Spjd ZFS_EXIT(zfsvfs); 2208168404Spjd return (err); 2209168404Spjd } 2210168404Spjd dmu_tx_hold_bonus(tx, attrzp->z_id); 2211168404Spjd } 2212168404Spjd 2213168404Spjd err = dmu_tx_assign(tx, zfsvfs->z_assign); 2214168404Spjd if (err) { 2215168404Spjd if (attrzp) 2216168404Spjd VN_RELE(ZTOV(attrzp)); 2217168404Spjd if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2218168404Spjd dmu_tx_wait(tx); 2219168404Spjd dmu_tx_abort(tx); 2220168404Spjd goto top; 2221168404Spjd } 2222168404Spjd dmu_tx_abort(tx); 2223168404Spjd ZFS_EXIT(zfsvfs); 2224168404Spjd return (err); 2225168404Spjd } 2226168404Spjd 2227168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2228168404Spjd 2229168404Spjd /* 2230168404Spjd * Set each attribute requested. 2231168404Spjd * We group settings according to the locks they need to acquire. 2232168404Spjd * 2233168404Spjd * Note: you cannot set ctime directly, although it will be 2234168404Spjd * updated as a side-effect of calling this function. 2235168404Spjd */ 2236168404Spjd 2237168404Spjd mutex_enter(&zp->z_lock); 2238168404Spjd 2239168404Spjd if (mask & AT_MODE) { 2240168404Spjd err = zfs_acl_chmod_setattr(zp, new_mode, tx); 2241168404Spjd ASSERT3U(err, ==, 0); 2242168404Spjd } 2243168404Spjd 2244168404Spjd if (attrzp) 2245168404Spjd mutex_enter(&attrzp->z_lock); 2246168404Spjd 2247168404Spjd if (mask & AT_UID) { 2248168404Spjd zp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2249168404Spjd if (attrzp) { 2250168404Spjd attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2251168404Spjd } 2252168404Spjd } 2253168404Spjd 2254168404Spjd if (mask & AT_GID) { 2255168404Spjd zp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2256168404Spjd if (attrzp) 2257168404Spjd attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2258168404Spjd } 2259168404Spjd 2260168404Spjd if (attrzp) 2261168404Spjd mutex_exit(&attrzp->z_lock); 2262168404Spjd 2263168404Spjd if (mask & AT_ATIME) 2264168404Spjd ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); 2265168404Spjd 2266168404Spjd if (mask & AT_MTIME) 2267168404Spjd ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime); 2268168404Spjd 2269168404Spjd if (mask & AT_SIZE) 2270168404Spjd zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx); 2271168404Spjd else if (mask != 0) 2272168404Spjd zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 2273168404Spjd 2274168404Spjd if (mask != 0) 2275168404Spjd zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask); 2276168404Spjd 2277168404Spjd mutex_exit(&zp->z_lock); 2278168404Spjd 2279168404Spjd if (attrzp) 2280168404Spjd VN_RELE(ZTOV(attrzp)); 2281168404Spjd 2282168404Spjd dmu_tx_commit(tx); 2283168404Spjd 2284168404Spjd ZFS_EXIT(zfsvfs); 2285168404Spjd return (err); 2286168404Spjd} 2287168404Spjd 2288168404Spjdtypedef struct zfs_zlock { 2289168404Spjd krwlock_t *zl_rwlock; /* lock we acquired */ 2290168404Spjd znode_t *zl_znode; /* znode we held */ 2291168404Spjd struct zfs_zlock *zl_next; /* next in list */ 2292168404Spjd} zfs_zlock_t; 2293168404Spjd 2294168404Spjd/* 2295168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock(). 2296168404Spjd */ 2297168404Spjdstatic void 2298168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp) 2299168404Spjd{ 2300168404Spjd zfs_zlock_t *zl; 2301168404Spjd 2302168404Spjd while ((zl = *zlpp) != NULL) { 2303168404Spjd if (zl->zl_znode != NULL) 2304168404Spjd VN_RELE(ZTOV(zl->zl_znode)); 2305168404Spjd rw_exit(zl->zl_rwlock); 2306168404Spjd *zlpp = zl->zl_next; 2307168404Spjd kmem_free(zl, sizeof (*zl)); 2308168404Spjd } 2309168404Spjd} 2310168404Spjd 2311168404Spjd/* 2312168404Spjd * Search back through the directory tree, using the ".." entries. 2313168404Spjd * Lock each directory in the chain to prevent concurrent renames. 2314168404Spjd * Fail any attempt to move a directory into one of its own descendants. 2315168404Spjd * XXX - z_parent_lock can overlap with map or grow locks 2316168404Spjd */ 2317168404Spjdstatic int 2318168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) 2319168404Spjd{ 2320168404Spjd zfs_zlock_t *zl; 2321168404Spjd znode_t *zp = tdzp; 2322168404Spjd uint64_t rootid = zp->z_zfsvfs->z_root; 2323168404Spjd uint64_t *oidp = &zp->z_id; 2324168404Spjd krwlock_t *rwlp = &szp->z_parent_lock; 2325168404Spjd krw_t rw = RW_WRITER; 2326168404Spjd 2327168404Spjd /* 2328168404Spjd * First pass write-locks szp and compares to zp->z_id. 2329168404Spjd * Later passes read-lock zp and compare to zp->z_parent. 2330168404Spjd */ 2331168404Spjd do { 2332168404Spjd if (!rw_tryenter(rwlp, rw)) { 2333168404Spjd /* 2334168404Spjd * Another thread is renaming in this path. 2335168404Spjd * Note that if we are a WRITER, we don't have any 2336168404Spjd * parent_locks held yet. 2337168404Spjd */ 2338168404Spjd if (rw == RW_READER && zp->z_id > szp->z_id) { 2339168404Spjd /* 2340168404Spjd * Drop our locks and restart 2341168404Spjd */ 2342168404Spjd zfs_rename_unlock(&zl); 2343168404Spjd *zlpp = NULL; 2344168404Spjd zp = tdzp; 2345168404Spjd oidp = &zp->z_id; 2346168404Spjd rwlp = &szp->z_parent_lock; 2347168404Spjd rw = RW_WRITER; 2348168404Spjd continue; 2349168404Spjd } else { 2350168404Spjd /* 2351168404Spjd * Wait for other thread to drop its locks 2352168404Spjd */ 2353168404Spjd rw_enter(rwlp, rw); 2354168404Spjd } 2355168404Spjd } 2356168404Spjd 2357168404Spjd zl = kmem_alloc(sizeof (*zl), KM_SLEEP); 2358168404Spjd zl->zl_rwlock = rwlp; 2359168404Spjd zl->zl_znode = NULL; 2360168404Spjd zl->zl_next = *zlpp; 2361168404Spjd *zlpp = zl; 2362168404Spjd 2363168404Spjd if (*oidp == szp->z_id) /* We're a descendant of szp */ 2364168404Spjd return (EINVAL); 2365168404Spjd 2366168404Spjd if (*oidp == rootid) /* We've hit the top */ 2367168404Spjd return (0); 2368168404Spjd 2369168404Spjd if (rw == RW_READER) { /* i.e. not the first pass */ 2370168404Spjd int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp); 2371168404Spjd if (error) 2372168404Spjd return (error); 2373168404Spjd zl->zl_znode = zp; 2374168404Spjd } 2375168404Spjd oidp = &zp->z_phys->zp_parent; 2376168404Spjd rwlp = &zp->z_parent_lock; 2377168404Spjd rw = RW_READER; 2378168404Spjd 2379168404Spjd } while (zp->z_id != sdzp->z_id); 2380168404Spjd 2381168404Spjd return (0); 2382168404Spjd} 2383168404Spjd 2384168404Spjd/* 2385168404Spjd * Move an entry from the provided source directory to the target 2386168404Spjd * directory. Change the entry name as indicated. 2387168404Spjd * 2388168404Spjd * IN: sdvp - Source directory containing the "old entry". 2389168404Spjd * snm - Old entry name. 2390168404Spjd * tdvp - Target directory to contain the "new entry". 2391168404Spjd * tnm - New entry name. 2392168404Spjd * cr - credentials of caller. 2393168404Spjd * 2394168404Spjd * RETURN: 0 if success 2395168404Spjd * error code if failure 2396168404Spjd * 2397168404Spjd * Timestamps: 2398168404Spjd * sdvp,tdvp - ctime|mtime updated 2399168404Spjd */ 2400168404Spjdstatic int 2401168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr) 2402168404Spjd{ 2403168404Spjd znode_t *tdzp, *szp, *tzp; 2404168404Spjd znode_t *sdzp = VTOZ(sdvp); 2405168404Spjd zfsvfs_t *zfsvfs = sdzp->z_zfsvfs; 2406168404Spjd zilog_t *zilog = zfsvfs->z_log; 2407168962Spjd vnode_t *realvp; 2408168404Spjd zfs_dirlock_t *sdl, *tdl; 2409168404Spjd dmu_tx_t *tx; 2410168404Spjd zfs_zlock_t *zl; 2411168962Spjd int cmp, serr, terr, error; 2412168404Spjd 2413168404Spjd ZFS_ENTER(zfsvfs); 2414168404Spjd 2415168962Spjd /* 2416168962Spjd * Make sure we have the real vp for the target directory. 2417168962Spjd */ 2418168962Spjd if (VOP_REALVP(tdvp, &realvp) == 0) 2419168962Spjd tdvp = realvp; 2420168962Spjd 2421168404Spjd if (tdvp->v_vfsp != sdvp->v_vfsp) { 2422168404Spjd ZFS_EXIT(zfsvfs); 2423168962Spjd return (EXDEV); 2424168404Spjd } 2425168404Spjd 2426168404Spjd tdzp = VTOZ(tdvp); 2427168404Spjdtop: 2428168404Spjd szp = NULL; 2429168404Spjd tzp = NULL; 2430168404Spjd zl = NULL; 2431168404Spjd 2432168404Spjd /* 2433168404Spjd * This is to prevent the creation of links into attribute space 2434168404Spjd * by renaming a linked file into/outof an attribute directory. 2435168404Spjd * See the comment in zfs_link() for why this is considered bad. 2436168404Spjd */ 2437168404Spjd if ((tdzp->z_phys->zp_flags & ZFS_XATTR) != 2438168404Spjd (sdzp->z_phys->zp_flags & ZFS_XATTR)) { 2439168962Spjd ZFS_EXIT(zfsvfs); 2440168962Spjd return (EINVAL); 2441168404Spjd } 2442168404Spjd 2443168404Spjd /* 2444168404Spjd * Lock source and target directory entries. To prevent deadlock, 2445168404Spjd * a lock ordering must be defined. We lock the directory with 2446168404Spjd * the smallest object id first, or if it's a tie, the one with 2447168404Spjd * the lexically first name. 2448168404Spjd */ 2449168404Spjd if (sdzp->z_id < tdzp->z_id) { 2450168962Spjd cmp = -1; 2451168962Spjd } else if (sdzp->z_id > tdzp->z_id) { 2452168962Spjd cmp = 1; 2453168962Spjd } else { 2454168962Spjd cmp = strcmp(snm, tnm); 2455168962Spjd if (cmp == 0) { 2456168962Spjd /* 2457168962Spjd * POSIX: "If the old argument and the new argument 2458168962Spjd * both refer to links to the same existing file, 2459168962Spjd * the rename() function shall return successfully 2460168962Spjd * and perform no other action." 2461168962Spjd */ 2462168962Spjd ZFS_EXIT(zfsvfs); 2463168962Spjd return (0); 2464168962Spjd } 2465168962Spjd } 2466168962Spjd if (cmp < 0) { 2467168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2468168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2469168962Spjd } else { 2470168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2471168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2472168404Spjd } 2473168404Spjd 2474168962Spjd if (serr) { 2475168404Spjd /* 2476168404Spjd * Source entry invalid or not there. 2477168404Spjd */ 2478168962Spjd if (!terr) { 2479168404Spjd zfs_dirent_unlock(tdl); 2480168962Spjd if (tzp) 2481168962Spjd VN_RELE(ZTOV(tzp)); 2482168962Spjd } 2483168404Spjd if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0) 2484168404Spjd serr = EINVAL; 2485168962Spjd ZFS_EXIT(zfsvfs); 2486168962Spjd return (serr); 2487168404Spjd } 2488168404Spjd if (terr) { 2489168404Spjd zfs_dirent_unlock(sdl); 2490168962Spjd VN_RELE(ZTOV(szp)); 2491168404Spjd if (strcmp(tnm, "..") == 0) 2492168404Spjd terr = EINVAL; 2493168962Spjd ZFS_EXIT(zfsvfs); 2494168962Spjd return (terr); 2495168404Spjd } 2496168404Spjd 2497168404Spjd /* 2498168404Spjd * Must have write access at the source to remove the old entry 2499168404Spjd * and write access at the target to create the new entry. 2500168404Spjd * Note that if target and source are the same, this can be 2501168404Spjd * done in a single check. 2502168404Spjd */ 2503168404Spjd 2504168404Spjd if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) 2505168404Spjd goto out; 2506168404Spjd 2507168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2508168404Spjd /* 2509168404Spjd * Check to make sure rename is valid. 2510168404Spjd * Can't do a move like this: /usr/a/b to /usr/a/b/c/d 2511168404Spjd */ 2512168404Spjd if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl)) 2513168404Spjd goto out; 2514168404Spjd } 2515168404Spjd 2516168404Spjd /* 2517168404Spjd * Does target exist? 2518168404Spjd */ 2519168404Spjd if (tzp) { 2520168404Spjd /* 2521168404Spjd * Source and target must be the same type. 2522168404Spjd */ 2523168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2524168962Spjd if (ZTOV(tzp)->v_type != VDIR) { 2525168404Spjd error = ENOTDIR; 2526168404Spjd goto out; 2527168404Spjd } 2528168404Spjd } else { 2529168962Spjd if (ZTOV(tzp)->v_type == VDIR) { 2530168404Spjd error = EISDIR; 2531168404Spjd goto out; 2532168404Spjd } 2533168404Spjd } 2534168404Spjd /* 2535168404Spjd * POSIX dictates that when the source and target 2536168404Spjd * entries refer to the same file object, rename 2537168404Spjd * must do nothing and exit without error. 2538168404Spjd */ 2539168404Spjd if (szp->z_id == tzp->z_id) { 2540168404Spjd error = 0; 2541168404Spjd goto out; 2542168404Spjd } 2543168404Spjd } 2544168404Spjd 2545168962Spjd vnevent_rename_src(ZTOV(szp)); 2546168962Spjd if (tzp) 2547168962Spjd vnevent_rename_dest(ZTOV(tzp)); 2548168962Spjd 2549168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2550168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); /* nlink changes */ 2551168404Spjd dmu_tx_hold_bonus(tx, sdzp->z_id); /* nlink changes */ 2552168404Spjd dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm); 2553168404Spjd dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm); 2554168404Spjd if (sdzp != tdzp) 2555168404Spjd dmu_tx_hold_bonus(tx, tdzp->z_id); /* nlink changes */ 2556168404Spjd if (tzp) 2557168404Spjd dmu_tx_hold_bonus(tx, tzp->z_id); /* parent changes */ 2558168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 2559168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2560168404Spjd if (error) { 2561168404Spjd if (zl != NULL) 2562168404Spjd zfs_rename_unlock(&zl); 2563168404Spjd zfs_dirent_unlock(sdl); 2564168404Spjd zfs_dirent_unlock(tdl); 2565168962Spjd VN_RELE(ZTOV(szp)); 2566168962Spjd if (tzp) 2567168962Spjd VN_RELE(ZTOV(tzp)); 2568168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2569168404Spjd dmu_tx_wait(tx); 2570168404Spjd dmu_tx_abort(tx); 2571168404Spjd goto top; 2572168404Spjd } 2573168404Spjd dmu_tx_abort(tx); 2574168962Spjd ZFS_EXIT(zfsvfs); 2575168962Spjd return (error); 2576168404Spjd } 2577168404Spjd 2578168404Spjd if (tzp) /* Attempt to remove the existing target */ 2579168404Spjd error = zfs_link_destroy(tdl, tzp, tx, 0, NULL); 2580168404Spjd 2581168404Spjd if (error == 0) { 2582168404Spjd error = zfs_link_create(tdl, szp, tx, ZRENAMING); 2583168404Spjd if (error == 0) { 2584168404Spjd error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL); 2585168404Spjd ASSERT(error == 0); 2586168404Spjd zfs_log_rename(zilog, tx, TX_RENAME, sdzp, 2587168404Spjd sdl->dl_name, tdzp, tdl->dl_name, szp); 2588168404Spjd } 2589168404Spjd#ifdef FREEBSD_NAMECACHE 2590168404Spjd if (error == 0) { 2591168404Spjd cache_purge(sdvp); 2592168404Spjd cache_purge(tdvp); 2593168404Spjd } 2594168404Spjd#endif 2595168404Spjd } 2596168404Spjd 2597168404Spjd dmu_tx_commit(tx); 2598168404Spjdout: 2599168404Spjd if (zl != NULL) 2600168404Spjd zfs_rename_unlock(&zl); 2601168404Spjd 2602168404Spjd zfs_dirent_unlock(sdl); 2603168404Spjd zfs_dirent_unlock(tdl); 2604168404Spjd 2605168962Spjd VN_RELE(ZTOV(szp)); 2606168404Spjd if (tzp) 2607168962Spjd VN_RELE(ZTOV(tzp)); 2608168404Spjd 2609168404Spjd ZFS_EXIT(zfsvfs); 2610168404Spjd 2611168404Spjd return (error); 2612168404Spjd} 2613168404Spjd 2614168404Spjd/* 2615168404Spjd * Insert the indicated symbolic reference entry into the directory. 2616168404Spjd * 2617168404Spjd * IN: dvp - Directory to contain new symbolic link. 2618168404Spjd * link - Name for new symlink entry. 2619168404Spjd * vap - Attributes of new entry. 2620168404Spjd * target - Target path of new symlink. 2621168404Spjd * cr - credentials of caller. 2622168404Spjd * 2623168404Spjd * RETURN: 0 if success 2624168404Spjd * error code if failure 2625168404Spjd * 2626168404Spjd * Timestamps: 2627168404Spjd * dvp - ctime|mtime updated 2628168404Spjd */ 2629168404Spjdstatic int 2630168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td) 2631168404Spjd{ 2632168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 2633168404Spjd zfs_dirlock_t *dl; 2634168404Spjd dmu_tx_t *tx; 2635168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2636168404Spjd zilog_t *zilog = zfsvfs->z_log; 2637168404Spjd uint64_t zoid; 2638168404Spjd int len = strlen(link); 2639168404Spjd int error; 2640168404Spjd 2641168962Spjd ASSERT(vap->va_type == VLNK); 2642168404Spjd 2643168404Spjd ZFS_ENTER(zfsvfs); 2644168404Spjdtop: 2645168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2646168404Spjd ZFS_EXIT(zfsvfs); 2647168404Spjd return (error); 2648168404Spjd } 2649168404Spjd 2650168404Spjd if (len > MAXPATHLEN) { 2651168404Spjd ZFS_EXIT(zfsvfs); 2652168404Spjd return (ENAMETOOLONG); 2653168404Spjd } 2654168404Spjd 2655168404Spjd /* 2656168404Spjd * Attempt to lock directory; fail if entry already exists. 2657168404Spjd */ 2658168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) { 2659168404Spjd ZFS_EXIT(zfsvfs); 2660168404Spjd return (error); 2661168404Spjd } 2662168404Spjd 2663168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2664168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len)); 2665168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 2666168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2667168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 2668168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE); 2669168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2670168404Spjd if (error) { 2671168404Spjd zfs_dirent_unlock(dl); 2672168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2673168404Spjd dmu_tx_wait(tx); 2674168404Spjd dmu_tx_abort(tx); 2675168404Spjd goto top; 2676168404Spjd } 2677168404Spjd dmu_tx_abort(tx); 2678168404Spjd ZFS_EXIT(zfsvfs); 2679168404Spjd return (error); 2680168404Spjd } 2681168404Spjd 2682168404Spjd dmu_buf_will_dirty(dzp->z_dbuf, tx); 2683168404Spjd 2684168404Spjd /* 2685168404Spjd * Create a new object for the symlink. 2686168404Spjd * Put the link content into bonus buffer if it will fit; 2687168404Spjd * otherwise, store it just like any other file data. 2688168404Spjd */ 2689168404Spjd zoid = 0; 2690168404Spjd if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) { 2691168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len); 2692168404Spjd if (len != 0) 2693168404Spjd bcopy(link, zp->z_phys + 1, len); 2694168404Spjd } else { 2695168404Spjd dmu_buf_t *dbp; 2696168404Spjd 2697168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 2698168404Spjd 2699168404Spjd /* 2700168404Spjd * Nothing can access the znode yet so no locking needed 2701168404Spjd * for growing the znode's blocksize. 2702168404Spjd */ 2703168404Spjd zfs_grow_blocksize(zp, len, tx); 2704168404Spjd 2705168404Spjd VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp)); 2706168404Spjd dmu_buf_will_dirty(dbp, tx); 2707168404Spjd 2708168404Spjd ASSERT3U(len, <=, dbp->db_size); 2709168404Spjd bcopy(link, dbp->db_data, len); 2710168404Spjd dmu_buf_rele(dbp, FTAG); 2711168404Spjd } 2712168404Spjd zp->z_phys->zp_size = len; 2713168404Spjd 2714168404Spjd /* 2715168404Spjd * Insert the new object into the directory. 2716168404Spjd */ 2717168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 2718168962Spjdout: 2719168404Spjd if (error == 0) { 2720168404Spjd zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link); 2721168962Spjd *vpp = ZTOV(zp); 2722168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 2723168404Spjd } 2724168404Spjd 2725168404Spjd dmu_tx_commit(tx); 2726168404Spjd 2727168404Spjd zfs_dirent_unlock(dl); 2728168404Spjd 2729168404Spjd ZFS_EXIT(zfsvfs); 2730168404Spjd return (error); 2731168404Spjd} 2732168404Spjd 2733168404Spjd/* 2734168404Spjd * Return, in the buffer contained in the provided uio structure, 2735168404Spjd * the symbolic path referred to by vp. 2736168404Spjd * 2737168404Spjd * IN: vp - vnode of symbolic link. 2738168404Spjd * uoip - structure to contain the link path. 2739168404Spjd * cr - credentials of caller. 2740168404Spjd * 2741168404Spjd * OUT: uio - structure to contain the link path. 2742168404Spjd * 2743168404Spjd * RETURN: 0 if success 2744168404Spjd * error code if failure 2745168404Spjd * 2746168404Spjd * Timestamps: 2747168404Spjd * vp - atime updated 2748168404Spjd */ 2749168404Spjd/* ARGSUSED */ 2750168404Spjdstatic int 2751168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr) 2752168404Spjd{ 2753168404Spjd znode_t *zp = VTOZ(vp); 2754168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2755168404Spjd size_t bufsz; 2756168404Spjd int error; 2757168404Spjd 2758168404Spjd ZFS_ENTER(zfsvfs); 2759168404Spjd 2760168404Spjd bufsz = (size_t)zp->z_phys->zp_size; 2761168404Spjd if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) { 2762168404Spjd error = uiomove(zp->z_phys + 1, 2763168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2764168404Spjd } else { 2765168404Spjd dmu_buf_t *dbp; 2766168404Spjd error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp); 2767168404Spjd if (error) { 2768168404Spjd ZFS_EXIT(zfsvfs); 2769168404Spjd return (error); 2770168404Spjd } 2771168404Spjd error = uiomove(dbp->db_data, 2772168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2773168404Spjd dmu_buf_rele(dbp, FTAG); 2774168404Spjd } 2775168404Spjd 2776168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 2777168404Spjd ZFS_EXIT(zfsvfs); 2778168404Spjd return (error); 2779168404Spjd} 2780168404Spjd 2781168404Spjd/* 2782168404Spjd * Insert a new entry into directory tdvp referencing svp. 2783168404Spjd * 2784168404Spjd * IN: tdvp - Directory to contain new entry. 2785168404Spjd * svp - vnode of new entry. 2786168404Spjd * name - name of new entry. 2787168404Spjd * cr - credentials of caller. 2788168404Spjd * 2789168404Spjd * RETURN: 0 if success 2790168404Spjd * error code if failure 2791168404Spjd * 2792168404Spjd * Timestamps: 2793168404Spjd * tdvp - ctime|mtime updated 2794168404Spjd * svp - ctime updated 2795168404Spjd */ 2796168404Spjd/* ARGSUSED */ 2797168404Spjdstatic int 2798168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr) 2799168404Spjd{ 2800168404Spjd znode_t *dzp = VTOZ(tdvp); 2801168404Spjd znode_t *tzp, *szp; 2802168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2803168404Spjd zilog_t *zilog = zfsvfs->z_log; 2804168404Spjd zfs_dirlock_t *dl; 2805168404Spjd dmu_tx_t *tx; 2806168962Spjd vnode_t *realvp; 2807168404Spjd int error; 2808168404Spjd 2809168404Spjd ASSERT(tdvp->v_type == VDIR); 2810168404Spjd 2811168404Spjd ZFS_ENTER(zfsvfs); 2812168404Spjd 2813168962Spjd if (VOP_REALVP(svp, &realvp) == 0) 2814168962Spjd svp = realvp; 2815168962Spjd 2816168404Spjd if (svp->v_vfsp != tdvp->v_vfsp) { 2817168404Spjd ZFS_EXIT(zfsvfs); 2818168404Spjd return (EXDEV); 2819168404Spjd } 2820168404Spjd 2821168404Spjd szp = VTOZ(svp); 2822168404Spjdtop: 2823168404Spjd /* 2824168404Spjd * We do not support links between attributes and non-attributes 2825168404Spjd * because of the potential security risk of creating links 2826168404Spjd * into "normal" file space in order to circumvent restrictions 2827168404Spjd * imposed in attribute space. 2828168404Spjd */ 2829168404Spjd if ((szp->z_phys->zp_flags & ZFS_XATTR) != 2830168404Spjd (dzp->z_phys->zp_flags & ZFS_XATTR)) { 2831168404Spjd ZFS_EXIT(zfsvfs); 2832168404Spjd return (EINVAL); 2833168404Spjd } 2834168404Spjd 2835168404Spjd /* 2836168404Spjd * POSIX dictates that we return EPERM here. 2837168404Spjd * Better choices include ENOTSUP or EISDIR. 2838168404Spjd */ 2839168404Spjd if (svp->v_type == VDIR) { 2840168404Spjd ZFS_EXIT(zfsvfs); 2841168404Spjd return (EPERM); 2842168404Spjd } 2843168404Spjd 2844168404Spjd if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) && 2845168404Spjd secpolicy_basic_link(cr) != 0) { 2846168404Spjd ZFS_EXIT(zfsvfs); 2847168404Spjd return (EPERM); 2848168404Spjd } 2849168404Spjd 2850168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2851168404Spjd ZFS_EXIT(zfsvfs); 2852168404Spjd return (error); 2853168404Spjd } 2854168404Spjd 2855168404Spjd /* 2856168404Spjd * Attempt to lock directory; fail if entry already exists. 2857168404Spjd */ 2858168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) { 2859168404Spjd ZFS_EXIT(zfsvfs); 2860168404Spjd return (error); 2861168404Spjd } 2862168404Spjd 2863168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2864168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); 2865168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2866168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2867168404Spjd if (error) { 2868168404Spjd zfs_dirent_unlock(dl); 2869168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2870168404Spjd dmu_tx_wait(tx); 2871168404Spjd dmu_tx_abort(tx); 2872168404Spjd goto top; 2873168404Spjd } 2874168404Spjd dmu_tx_abort(tx); 2875168404Spjd ZFS_EXIT(zfsvfs); 2876168404Spjd return (error); 2877168404Spjd } 2878168404Spjd 2879168404Spjd error = zfs_link_create(dl, szp, tx, 0); 2880168404Spjd 2881168404Spjd if (error == 0) 2882168404Spjd zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name); 2883168404Spjd 2884168404Spjd dmu_tx_commit(tx); 2885168404Spjd 2886168404Spjd zfs_dirent_unlock(dl); 2887168404Spjd 2888168404Spjd ZFS_EXIT(zfsvfs); 2889168404Spjd return (error); 2890168404Spjd} 2891168404Spjd 2892168962Spjdvoid 2893168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr) 2894168404Spjd{ 2895168962Spjd znode_t *zp = VTOZ(vp); 2896168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2897168962Spjd int error; 2898168404Spjd 2899168404Spjd rw_enter(&zfsvfs->z_um_lock, RW_READER); 2900168404Spjd if (zfsvfs->z_unmounted2) { 2901168404Spjd ASSERT(zp->z_dbuf_held == 0); 2902168404Spjd 2903168404Spjd mutex_enter(&zp->z_lock); 2904168404Spjd VI_LOCK(vp); 2905168404Spjd vp->v_count = 0; /* count arrives as 1 */ 2906168404Spjd VI_UNLOCK(vp); 2907168404Spjd if (zp->z_dbuf == NULL) { 2908168404Spjd mutex_exit(&zp->z_lock); 2909168404Spjd zfs_znode_free(zp); 2910168404Spjd } else { 2911168404Spjd mutex_exit(&zp->z_lock); 2912168404Spjd } 2913168404Spjd rw_exit(&zfsvfs->z_um_lock); 2914168404Spjd VFS_RELE(zfsvfs->z_vfs); 2915168962Spjd return; 2916168404Spjd } 2917168404Spjd 2918168404Spjd if (zp->z_atime_dirty && zp->z_unlinked == 0) { 2919168404Spjd dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 2920168404Spjd 2921168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2922168404Spjd error = dmu_tx_assign(tx, TXG_WAIT); 2923168404Spjd if (error) { 2924168404Spjd dmu_tx_abort(tx); 2925168404Spjd } else { 2926168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2927168404Spjd mutex_enter(&zp->z_lock); 2928168404Spjd zp->z_atime_dirty = 0; 2929168404Spjd mutex_exit(&zp->z_lock); 2930168404Spjd dmu_tx_commit(tx); 2931168404Spjd } 2932168404Spjd } 2933168404Spjd 2934168404Spjd zfs_zinactive(zp); 2935168404Spjd rw_exit(&zfsvfs->z_um_lock); 2936168404Spjd} 2937168404Spjd 2938168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid)); 2939168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid)); 2940168404Spjd 2941168404Spjdstatic int 2942168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp) 2943168404Spjd{ 2944168404Spjd znode_t *zp = VTOZ(vp); 2945168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2946168404Spjd uint32_t gen = (uint32_t)zp->z_phys->zp_gen; 2947168404Spjd uint64_t object = zp->z_id; 2948168404Spjd zfid_short_t *zfid; 2949168404Spjd int size, i; 2950168404Spjd 2951168404Spjd ZFS_ENTER(zfsvfs); 2952168404Spjd 2953168404Spjd size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN; 2954168404Spjd fidp->fid_len = size; 2955168404Spjd 2956168404Spjd zfid = (zfid_short_t *)fidp; 2957168404Spjd 2958168404Spjd zfid->zf_len = size; 2959168404Spjd 2960168404Spjd for (i = 0; i < sizeof (zfid->zf_object); i++) 2961168404Spjd zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 2962168404Spjd 2963168404Spjd /* Must have a non-zero generation number to distinguish from .zfs */ 2964168404Spjd if (gen == 0) 2965168404Spjd gen = 1; 2966168404Spjd for (i = 0; i < sizeof (zfid->zf_gen); i++) 2967168404Spjd zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i)); 2968168404Spjd 2969168404Spjd if (size == LONG_FID_LEN) { 2970168404Spjd uint64_t objsetid = dmu_objset_id(zfsvfs->z_os); 2971169023Spjd zfid_long_t *zlfid; 2972168404Spjd 2973168404Spjd zlfid = (zfid_long_t *)fidp; 2974168404Spjd 2975168404Spjd for (i = 0; i < sizeof (zlfid->zf_setid); i++) 2976168404Spjd zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i)); 2977168404Spjd 2978168404Spjd /* XXX - this should be the generation number for the objset */ 2979168404Spjd for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 2980168404Spjd zlfid->zf_setgen[i] = 0; 2981168404Spjd } 2982168404Spjd 2983168404Spjd ZFS_EXIT(zfsvfs); 2984168404Spjd return (0); 2985168404Spjd} 2986168404Spjd 2987168404Spjdstatic int 2988168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) 2989168404Spjd{ 2990168404Spjd znode_t *zp, *xzp; 2991168404Spjd zfsvfs_t *zfsvfs; 2992168404Spjd zfs_dirlock_t *dl; 2993168404Spjd int error; 2994168404Spjd 2995168404Spjd switch (cmd) { 2996168404Spjd case _PC_LINK_MAX: 2997168404Spjd *valp = INT_MAX; 2998168404Spjd return (0); 2999168404Spjd 3000168404Spjd case _PC_FILESIZEBITS: 3001168404Spjd *valp = 64; 3002168404Spjd return (0); 3003168404Spjd 3004168404Spjd#if 0 3005168404Spjd case _PC_XATTR_EXISTS: 3006168404Spjd zp = VTOZ(vp); 3007168404Spjd zfsvfs = zp->z_zfsvfs; 3008168404Spjd ZFS_ENTER(zfsvfs); 3009168404Spjd *valp = 0; 3010168404Spjd error = zfs_dirent_lock(&dl, zp, "", &xzp, 3011168404Spjd ZXATTR | ZEXISTS | ZSHARED); 3012168404Spjd if (error == 0) { 3013168404Spjd zfs_dirent_unlock(dl); 3014168404Spjd if (!zfs_dirempty(xzp)) 3015168404Spjd *valp = 1; 3016168404Spjd VN_RELE(ZTOV(xzp)); 3017168404Spjd } else if (error == ENOENT) { 3018168404Spjd /* 3019168404Spjd * If there aren't extended attributes, it's the 3020168404Spjd * same as having zero of them. 3021168404Spjd */ 3022168404Spjd error = 0; 3023168404Spjd } 3024168404Spjd ZFS_EXIT(zfsvfs); 3025168404Spjd return (error); 3026168404Spjd#endif 3027168404Spjd 3028168404Spjd case _PC_ACL_EXTENDED: 3029168404Spjd *valp = 0; /* TODO */ 3030168404Spjd return (0); 3031168404Spjd 3032168404Spjd case _PC_MIN_HOLE_SIZE: 3033168404Spjd *valp = (int)SPA_MINBLOCKSIZE; 3034168404Spjd return (0); 3035168404Spjd 3036168404Spjd default: 3037168962Spjd return (EOPNOTSUPP); 3038168404Spjd } 3039168404Spjd} 3040168404Spjd 3041168404Spjd#ifdef TODO 3042168404Spjd/*ARGSUSED*/ 3043168404Spjdstatic int 3044168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3045168404Spjd{ 3046168404Spjd znode_t *zp = VTOZ(vp); 3047168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3048168404Spjd int error; 3049168404Spjd 3050168404Spjd ZFS_ENTER(zfsvfs); 3051168404Spjd error = zfs_getacl(zp, vsecp, cr); 3052168404Spjd ZFS_EXIT(zfsvfs); 3053168404Spjd 3054168404Spjd return (error); 3055168404Spjd} 3056168404Spjd#endif /* TODO */ 3057168404Spjd 3058168404Spjd#ifdef TODO 3059168404Spjd/*ARGSUSED*/ 3060168404Spjdstatic int 3061168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3062168404Spjd{ 3063168404Spjd znode_t *zp = VTOZ(vp); 3064168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3065168404Spjd int error; 3066168404Spjd 3067168404Spjd ZFS_ENTER(zfsvfs); 3068168404Spjd error = zfs_setacl(zp, vsecp, cr); 3069168404Spjd ZFS_EXIT(zfsvfs); 3070168404Spjd return (error); 3071168404Spjd} 3072168404Spjd#endif /* TODO */ 3073168404Spjd 3074168962Spjdstatic int 3075168962Spjdzfs_freebsd_open(ap) 3076168962Spjd struct vop_open_args /* { 3077168962Spjd struct vnode *a_vp; 3078168962Spjd int a_mode; 3079168962Spjd struct ucred *a_cred; 3080168962Spjd struct thread *a_td; 3081168962Spjd } */ *ap; 3082168962Spjd{ 3083168962Spjd vnode_t *vp = ap->a_vp; 3084168962Spjd znode_t *zp = VTOZ(vp); 3085168962Spjd int error; 3086168962Spjd 3087168962Spjd error = zfs_open(&vp, ap->a_mode, ap->a_cred); 3088168962Spjd if (error == 0) 3089168962Spjd vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); 3090168962Spjd return (error); 3091168962Spjd} 3092168962Spjd 3093168962Spjdstatic int 3094168962Spjdzfs_freebsd_close(ap) 3095168962Spjd struct vop_close_args /* { 3096168962Spjd struct vnode *a_vp; 3097168962Spjd int a_fflag; 3098168962Spjd struct ucred *a_cred; 3099168962Spjd struct thread *a_td; 3100168962Spjd } */ *ap; 3101168962Spjd{ 3102168962Spjd 3103168962Spjd return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred)); 3104168962Spjd} 3105168962Spjd 3106168962Spjdstatic int 3107168962Spjdzfs_freebsd_ioctl(ap) 3108168962Spjd struct vop_ioctl_args /* { 3109168962Spjd struct vnode *a_vp; 3110168962Spjd u_long a_command; 3111168962Spjd caddr_t a_data; 3112168962Spjd int a_fflag; 3113168962Spjd struct ucred *cred; 3114168962Spjd struct thread *td; 3115168962Spjd } */ *ap; 3116168962Spjd{ 3117168962Spjd 3118168978Spjd return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data, 3119168962Spjd ap->a_fflag, ap->a_cred, NULL)); 3120168962Spjd} 3121168962Spjd 3122168962Spjdstatic int 3123168962Spjdzfs_freebsd_read(ap) 3124168962Spjd struct vop_read_args /* { 3125168962Spjd struct vnode *a_vp; 3126168962Spjd struct uio *a_uio; 3127168962Spjd int a_ioflag; 3128168962Spjd struct ucred *a_cred; 3129168962Spjd } */ *ap; 3130168962Spjd{ 3131168962Spjd 3132168962Spjd return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3133168962Spjd} 3134168962Spjd 3135168962Spjdstatic int 3136168962Spjdzfs_freebsd_write(ap) 3137168962Spjd struct vop_write_args /* { 3138168962Spjd struct vnode *a_vp; 3139168962Spjd struct uio *a_uio; 3140168962Spjd int a_ioflag; 3141168962Spjd struct ucred *a_cred; 3142168962Spjd } */ *ap; 3143168962Spjd{ 3144168962Spjd 3145168962Spjd return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3146168962Spjd} 3147168962Spjd 3148168962Spjdstatic int 3149168962Spjdzfs_freebsd_access(ap) 3150168962Spjd struct vop_access_args /* { 3151168962Spjd struct vnode *a_vp; 3152168962Spjd int a_mode; 3153168962Spjd struct ucred *a_cred; 3154168962Spjd struct thread *a_td; 3155168962Spjd } */ *ap; 3156168962Spjd{ 3157168962Spjd 3158168962Spjd return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred)); 3159168962Spjd} 3160168962Spjd 3161168962Spjdstatic int 3162168962Spjdzfs_freebsd_lookup(ap) 3163168962Spjd struct vop_lookup_args /* { 3164168962Spjd struct vnode *a_dvp; 3165168962Spjd struct vnode **a_vpp; 3166168962Spjd struct componentname *a_cnp; 3167168962Spjd } */ *ap; 3168168962Spjd{ 3169168962Spjd struct componentname *cnp = ap->a_cnp; 3170168962Spjd char nm[NAME_MAX + 1]; 3171168962Spjd 3172168962Spjd ASSERT(cnp->cn_namelen < sizeof(nm)); 3173168962Spjd strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm))); 3174168962Spjd 3175168962Spjd return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop, 3176168962Spjd cnp->cn_cred, cnp->cn_thread)); 3177168962Spjd} 3178168962Spjd 3179168962Spjdstatic int 3180168962Spjdzfs_freebsd_create(ap) 3181168962Spjd struct vop_create_args /* { 3182168962Spjd struct vnode *a_dvp; 3183168962Spjd struct vnode **a_vpp; 3184168962Spjd struct componentname *a_cnp; 3185168962Spjd struct vattr *a_vap; 3186168962Spjd } */ *ap; 3187168962Spjd{ 3188168962Spjd struct componentname *cnp = ap->a_cnp; 3189168962Spjd vattr_t *vap = ap->a_vap; 3190168962Spjd int mode; 3191168962Spjd 3192168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3193168962Spjd 3194168962Spjd vattr_init_mask(vap); 3195168962Spjd mode = vap->va_mode & ALLPERMS; 3196168962Spjd 3197168962Spjd return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode, 3198168962Spjd ap->a_vpp, cnp->cn_cred, cnp->cn_thread)); 3199168962Spjd} 3200168962Spjd 3201168962Spjdstatic int 3202168962Spjdzfs_freebsd_remove(ap) 3203168962Spjd struct vop_remove_args /* { 3204168962Spjd struct vnode *a_dvp; 3205168962Spjd struct vnode *a_vp; 3206168962Spjd struct componentname *a_cnp; 3207168962Spjd } */ *ap; 3208168962Spjd{ 3209168962Spjd 3210168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3211168962Spjd 3212168962Spjd return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr, 3213168962Spjd ap->a_cnp->cn_cred)); 3214168962Spjd} 3215168962Spjd 3216168962Spjdstatic int 3217168962Spjdzfs_freebsd_mkdir(ap) 3218168962Spjd struct vop_mkdir_args /* { 3219168962Spjd struct vnode *a_dvp; 3220168962Spjd struct vnode **a_vpp; 3221168962Spjd struct componentname *a_cnp; 3222168962Spjd struct vattr *a_vap; 3223168962Spjd } */ *ap; 3224168962Spjd{ 3225168962Spjd vattr_t *vap = ap->a_vap; 3226168962Spjd 3227168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3228168962Spjd 3229168962Spjd vattr_init_mask(vap); 3230168962Spjd 3231168962Spjd return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp, 3232168962Spjd ap->a_cnp->cn_cred)); 3233168962Spjd} 3234168962Spjd 3235168962Spjdstatic int 3236168962Spjdzfs_freebsd_rmdir(ap) 3237168962Spjd struct vop_rmdir_args /* { 3238168962Spjd struct vnode *a_dvp; 3239168962Spjd struct vnode *a_vp; 3240168962Spjd struct componentname *a_cnp; 3241168962Spjd } */ *ap; 3242168962Spjd{ 3243168962Spjd struct componentname *cnp = ap->a_cnp; 3244168962Spjd 3245168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3246168962Spjd 3247168962Spjd return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred)); 3248168962Spjd} 3249168962Spjd 3250168962Spjdstatic int 3251168962Spjdzfs_freebsd_readdir(ap) 3252168962Spjd struct vop_readdir_args /* { 3253168962Spjd struct vnode *a_vp; 3254168962Spjd struct uio *a_uio; 3255168962Spjd struct ucred *a_cred; 3256168962Spjd int *a_eofflag; 3257168962Spjd int *a_ncookies; 3258168962Spjd u_long **a_cookies; 3259168962Spjd } */ *ap; 3260168962Spjd{ 3261168962Spjd 3262168962Spjd return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, 3263168962Spjd ap->a_ncookies, ap->a_cookies)); 3264168962Spjd} 3265168962Spjd 3266168962Spjdstatic int 3267168962Spjdzfs_freebsd_fsync(ap) 3268168962Spjd struct vop_fsync_args /* { 3269168962Spjd struct vnode *a_vp; 3270168962Spjd int a_waitfor; 3271168962Spjd struct thread *a_td; 3272168962Spjd } */ *ap; 3273168962Spjd{ 3274168962Spjd 3275168962Spjd vop_stdfsync(ap); 3276168962Spjd return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred)); 3277168962Spjd} 3278168962Spjd 3279168962Spjdstatic int 3280168962Spjdzfs_freebsd_getattr(ap) 3281168962Spjd struct vop_getattr_args /* { 3282168962Spjd struct vnode *a_vp; 3283168962Spjd struct vattr *a_vap; 3284168962Spjd struct ucred *a_cred; 3285168962Spjd struct thread *a_td; 3286168962Spjd } */ *ap; 3287168962Spjd{ 3288168962Spjd 3289168962Spjd return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred)); 3290168962Spjd} 3291168962Spjd 3292168962Spjdstatic int 3293168962Spjdzfs_freebsd_setattr(ap) 3294168962Spjd struct vop_setattr_args /* { 3295168962Spjd struct vnode *a_vp; 3296168962Spjd struct vattr *a_vap; 3297168962Spjd struct ucred *a_cred; 3298168962Spjd struct thread *a_td; 3299168962Spjd } */ *ap; 3300168962Spjd{ 3301168962Spjd vattr_t *vap = ap->a_vap; 3302168962Spjd 3303168962Spjd /* No support for FreeBSD's chflags(2). */ 3304168962Spjd if (vap->va_flags != VNOVAL) 3305168962Spjd return (EOPNOTSUPP); 3306168962Spjd 3307168962Spjd vattr_init_mask(vap); 3308168962Spjd 3309168962Spjd return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL)); 3310168962Spjd} 3311168962Spjd 3312168962Spjdstatic int 3313168962Spjdzfs_freebsd_rename(ap) 3314168962Spjd struct vop_rename_args /* { 3315168962Spjd struct vnode *a_fdvp; 3316168962Spjd struct vnode *a_fvp; 3317168962Spjd struct componentname *a_fcnp; 3318168962Spjd struct vnode *a_tdvp; 3319168962Spjd struct vnode *a_tvp; 3320168962Spjd struct componentname *a_tcnp; 3321168962Spjd } */ *ap; 3322168962Spjd{ 3323168962Spjd vnode_t *fdvp = ap->a_fdvp; 3324168962Spjd vnode_t *fvp = ap->a_fvp; 3325168962Spjd vnode_t *tdvp = ap->a_tdvp; 3326168962Spjd vnode_t *tvp = ap->a_tvp; 3327168962Spjd int error; 3328168962Spjd 3329168962Spjd ASSERT(ap->a_fcnp->cn_flags & SAVENAME); 3330168962Spjd ASSERT(ap->a_tcnp->cn_flags & SAVENAME); 3331168962Spjd 3332168962Spjd error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp, 3333168962Spjd ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred); 3334168962Spjd 3335168962Spjd if (tdvp == tvp) 3336168962Spjd VN_RELE(tdvp); 3337168962Spjd else 3338168962Spjd VN_URELE(tdvp); 3339168962Spjd if (tvp) 3340168962Spjd VN_URELE(tvp); 3341168962Spjd VN_RELE(fdvp); 3342168962Spjd VN_RELE(fvp); 3343168962Spjd 3344168962Spjd return (error); 3345168962Spjd} 3346168962Spjd 3347168962Spjdstatic int 3348168962Spjdzfs_freebsd_symlink(ap) 3349168962Spjd struct vop_symlink_args /* { 3350168962Spjd struct vnode *a_dvp; 3351168962Spjd struct vnode **a_vpp; 3352168962Spjd struct componentname *a_cnp; 3353168962Spjd struct vattr *a_vap; 3354168962Spjd char *a_target; 3355168962Spjd } */ *ap; 3356168962Spjd{ 3357168962Spjd struct componentname *cnp = ap->a_cnp; 3358168962Spjd vattr_t *vap = ap->a_vap; 3359168962Spjd 3360168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3361168962Spjd 3362168962Spjd vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ 3363168962Spjd vattr_init_mask(vap); 3364168962Spjd 3365168962Spjd return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap, 3366168962Spjd ap->a_target, cnp->cn_cred, cnp->cn_thread)); 3367168962Spjd} 3368168962Spjd 3369168962Spjdstatic int 3370168962Spjdzfs_freebsd_readlink(ap) 3371168962Spjd struct vop_readlink_args /* { 3372168962Spjd struct vnode *a_vp; 3373168962Spjd struct uio *a_uio; 3374168962Spjd struct ucred *a_cred; 3375168962Spjd } */ *ap; 3376168962Spjd{ 3377168962Spjd 3378168962Spjd return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred)); 3379168962Spjd} 3380168962Spjd 3381168962Spjdstatic int 3382168962Spjdzfs_freebsd_link(ap) 3383168962Spjd struct vop_link_args /* { 3384168962Spjd struct vnode *a_tdvp; 3385168962Spjd struct vnode *a_vp; 3386168962Spjd struct componentname *a_cnp; 3387168962Spjd } */ *ap; 3388168962Spjd{ 3389168962Spjd struct componentname *cnp = ap->a_cnp; 3390168962Spjd 3391168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3392168962Spjd 3393168962Spjd return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred)); 3394168962Spjd} 3395168962Spjd 3396168962Spjdstatic int 3397168962Spjdzfs_freebsd_inactive(ap) 3398168962Spjd struct vop_inactive_args /* { 3399168962Spjd struct vnode *a_vp; 3400168962Spjd struct thread *a_td; 3401168962Spjd } */ *ap; 3402168962Spjd{ 3403168962Spjd vnode_t *vp = ap->a_vp; 3404168962Spjd 3405168962Spjd zfs_inactive(vp, ap->a_td->td_ucred); 3406168962Spjd return (0); 3407168962Spjd} 3408168962Spjd 3409168962Spjdstatic int 3410168962Spjdzfs_freebsd_reclaim(ap) 3411168962Spjd struct vop_reclaim_args /* { 3412168962Spjd struct vnode *a_vp; 3413168962Spjd struct thread *a_td; 3414168962Spjd } */ *ap; 3415168962Spjd{ 3416169025Spjd vnode_t *vp = ap->a_vp; 3417168962Spjd znode_t *zp = VTOZ(vp); 3418169025Spjd zfsvfs_t *zfsvfs; 3419169025Spjd int rele = 1; 3420168962Spjd 3421169025Spjd ASSERT(zp != NULL); 3422169025Spjd 3423168962Spjd /* 3424168962Spjd * Destroy the vm object and flush associated pages. 3425168962Spjd */ 3426168962Spjd vnode_destroy_vobject(vp); 3427169025Spjd 3428169025Spjd mutex_enter(&zp->z_lock); 3429169025Spjd ASSERT(zp->z_phys); 3430169025Spjd ASSERT(zp->z_dbuf_held); 3431169025Spjd zfsvfs = zp->z_zfsvfs; 3432169025Spjd if (!zp->z_unlinked) { 3433169025Spjd zp->z_dbuf_held = 0; 3434169025Spjd ZTOV(zp) = NULL; 3435169025Spjd mutex_exit(&zp->z_lock); 3436169025Spjd dmu_buf_rele(zp->z_dbuf, NULL); 3437169025Spjd } else { 3438169025Spjd mutex_exit(&zp->z_lock); 3439169025Spjd } 3440168962Spjd VI_LOCK(vp); 3441169025Spjd if (vp->v_count > 0) 3442169025Spjd rele = 0; 3443168962Spjd vp->v_data = NULL; 3444168962Spjd ASSERT(vp->v_holdcnt > 1); 3445168962Spjd vdropl(vp); 3446169025Spjd if (!zp->z_unlinked && rele) 3447169025Spjd VFS_RELE(zfsvfs->z_vfs); 3448168962Spjd return (0); 3449168962Spjd} 3450168962Spjd 3451168962Spjdstatic int 3452168962Spjdzfs_freebsd_fid(ap) 3453168962Spjd struct vop_fid_args /* { 3454168962Spjd struct vnode *a_vp; 3455168962Spjd struct fid *a_fid; 3456168962Spjd } */ *ap; 3457168962Spjd{ 3458168962Spjd 3459168962Spjd return (zfs_fid(ap->a_vp, (void *)ap->a_fid)); 3460168962Spjd} 3461168962Spjd 3462168962Spjdstatic int 3463168962Spjdzfs_freebsd_pathconf(ap) 3464168962Spjd struct vop_pathconf_args /* { 3465168962Spjd struct vnode *a_vp; 3466168962Spjd int a_name; 3467168962Spjd register_t *a_retval; 3468168962Spjd } */ *ap; 3469168962Spjd{ 3470168962Spjd ulong_t val; 3471168962Spjd int error; 3472168962Spjd 3473168962Spjd error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred); 3474168962Spjd if (error == 0) 3475168962Spjd *ap->a_retval = val; 3476168962Spjd else if (error == EOPNOTSUPP) 3477168962Spjd error = vop_stdpathconf(ap); 3478168962Spjd return (error); 3479168962Spjd} 3480168962Spjd 3481168404Spjd/* 3482168404Spjd * Advisory record locking support 3483168404Spjd */ 3484168404Spjdstatic int 3485168962Spjdzfs_freebsd_advlock(ap) 3486168404Spjd struct vop_advlock_args /* { 3487168404Spjd struct vnode *a_vp; 3488168404Spjd caddr_t a_id; 3489168404Spjd int a_op; 3490168404Spjd struct flock *a_fl; 3491168404Spjd int a_flags; 3492168404Spjd } */ *ap; 3493168404Spjd{ 3494168404Spjd znode_t *zp = VTOZ(ap->a_vp); 3495168404Spjd 3496168404Spjd return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size)); 3497168404Spjd} 3498168404Spjd 3499168404Spjdstruct vop_vector zfs_vnodeops; 3500168404Spjdstruct vop_vector zfs_fifoops; 3501168404Spjd 3502168404Spjdstruct vop_vector zfs_vnodeops = { 3503168404Spjd .vop_default = &default_vnodeops, 3504168962Spjd .vop_inactive = zfs_freebsd_inactive, 3505168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3506168962Spjd .vop_access = zfs_freebsd_access, 3507168404Spjd#ifdef FREEBSD_NAMECACHE 3508168404Spjd .vop_lookup = vfs_cache_lookup, 3509168962Spjd .vop_cachedlookup = zfs_freebsd_lookup, 3510168404Spjd#else 3511168962Spjd .vop_lookup = zfs_freebsd_lookup, 3512168404Spjd#endif 3513168962Spjd .vop_getattr = zfs_freebsd_getattr, 3514168962Spjd .vop_setattr = zfs_freebsd_setattr, 3515168962Spjd .vop_create = zfs_freebsd_create, 3516168962Spjd .vop_mknod = zfs_freebsd_create, 3517168962Spjd .vop_mkdir = zfs_freebsd_mkdir, 3518168962Spjd .vop_readdir = zfs_freebsd_readdir, 3519168962Spjd .vop_fsync = zfs_freebsd_fsync, 3520168962Spjd .vop_open = zfs_freebsd_open, 3521168962Spjd .vop_close = zfs_freebsd_close, 3522168962Spjd .vop_rmdir = zfs_freebsd_rmdir, 3523168962Spjd .vop_ioctl = zfs_freebsd_ioctl, 3524168962Spjd .vop_link = zfs_freebsd_link, 3525168962Spjd .vop_symlink = zfs_freebsd_symlink, 3526168962Spjd .vop_readlink = zfs_freebsd_readlink, 3527168962Spjd .vop_read = zfs_freebsd_read, 3528168962Spjd .vop_write = zfs_freebsd_write, 3529168962Spjd .vop_remove = zfs_freebsd_remove, 3530168962Spjd .vop_rename = zfs_freebsd_rename, 3531168962Spjd .vop_advlock = zfs_freebsd_advlock, 3532168962Spjd .vop_pathconf = zfs_freebsd_pathconf, 3533168404Spjd .vop_bmap = VOP_EOPNOTSUPP, 3534168962Spjd .vop_fid = zfs_freebsd_fid, 3535168404Spjd}; 3536168404Spjd 3537168404Spjdstruct vop_vector zfs_fifoops = { 3538168404Spjd .vop_default = &fifo_specops, 3539168404Spjd .vop_fsync = VOP_PANIC, 3540168962Spjd .vop_access = zfs_freebsd_access, 3541168962Spjd .vop_getattr = zfs_freebsd_getattr, 3542168962Spjd .vop_inactive = zfs_freebsd_inactive, 3543168404Spjd .vop_read = VOP_PANIC, 3544168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3545168962Spjd .vop_setattr = zfs_freebsd_setattr, 3546168404Spjd .vop_write = VOP_PANIC, 3547168962Spjd .vop_fid = zfs_freebsd_fid, 3548168404Spjd}; 3549