zfs_vnops.c revision 176559
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 26169195Spjd/* Portions Copyright 2007 Jeremy Teo */ 27169195Spjd 28168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 29168404Spjd 30168404Spjd#include <sys/types.h> 31168404Spjd#include <sys/param.h> 32168404Spjd#include <sys/time.h> 33168404Spjd#include <sys/systm.h> 34168404Spjd#include <sys/sysmacros.h> 35168404Spjd#include <sys/resource.h> 36168404Spjd#include <sys/vfs.h> 37168404Spjd#include <sys/vnode.h> 38168404Spjd#include <sys/file.h> 39168404Spjd#include <sys/stat.h> 40168404Spjd#include <sys/kmem.h> 41168404Spjd#include <sys/taskq.h> 42168404Spjd#include <sys/uio.h> 43168404Spjd#include <sys/atomic.h> 44168404Spjd#include <sys/namei.h> 45168404Spjd#include <sys/mman.h> 46168404Spjd#include <sys/cmn_err.h> 47168404Spjd#include <sys/errno.h> 48168404Spjd#include <sys/unistd.h> 49168404Spjd#include <sys/zfs_vfsops.h> 50168404Spjd#include <sys/zfs_dir.h> 51168404Spjd#include <sys/zfs_acl.h> 52168404Spjd#include <sys/zfs_ioctl.h> 53168404Spjd#include <sys/fs/zfs.h> 54168404Spjd#include <sys/dmu.h> 55168404Spjd#include <sys/spa.h> 56168404Spjd#include <sys/txg.h> 57168404Spjd#include <sys/dbuf.h> 58168404Spjd#include <sys/zap.h> 59168404Spjd#include <sys/dirent.h> 60168962Spjd#include <sys/policy.h> 61168962Spjd#include <sys/sunddi.h> 62168404Spjd#include <sys/filio.h> 63168404Spjd#include <sys/zfs_ctldir.h> 64168404Spjd#include <sys/dnlc.h> 65168404Spjd#include <sys/zfs_rlock.h> 66168404Spjd#include <sys/bio.h> 67168404Spjd#include <sys/buf.h> 68168404Spjd#include <sys/sf_buf.h> 69168404Spjd#include <sys/sched.h> 70168404Spjd 71168404Spjd/* 72168404Spjd * Programming rules. 73168404Spjd * 74168404Spjd * Each vnode op performs some logical unit of work. To do this, the ZPL must 75168404Spjd * properly lock its in-core state, create a DMU transaction, do the work, 76168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction, 77168404Spjd * and wait the the intent log to commit if it's is a synchronous operation. 78168404Spjd * Morover, the vnode ops must work in both normal and log replay context. 79168404Spjd * The ordering of events is important to avoid deadlocks and references 80168404Spjd * to freed memory. The example below illustrates the following Big Rules: 81168404Spjd * 82168404Spjd * (1) A check must be made in each zfs thread for a mounted file system. 83168404Spjd * This is done avoiding races using ZFS_ENTER(zfsvfs). 84168404Spjd * A ZFS_EXIT(zfsvfs) is needed before all returns. 85168404Spjd * 86168404Spjd * (2) VN_RELE() should always be the last thing except for zil_commit() 87168404Spjd * (if necessary) and ZFS_EXIT(). This is for 3 reasons: 88168404Spjd * First, if it's the last reference, the vnode/znode 89168404Spjd * can be freed, so the zp may point to freed memory. Second, the last 90168404Spjd * reference will call zfs_zinactive(), which may induce a lot of work -- 91168404Spjd * pushing cached pages (which acquires range locks) and syncing out 92168404Spjd * cached atime changes. Third, zfs_zinactive() may require a new tx, 93168404Spjd * which could deadlock the system if you were already holding one. 94168404Spjd * 95168404Spjd * (3) All range locks must be grabbed before calling dmu_tx_assign(), 96168404Spjd * as they can span dmu_tx_assign() calls. 97168404Spjd * 98168404Spjd * (4) Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign(). 99168404Spjd * In normal operation, this will be TXG_NOWAIT. During ZIL replay, 100168404Spjd * it will be a specific txg. Either way, dmu_tx_assign() never blocks. 101168404Spjd * This is critical because we don't want to block while holding locks. 102168404Spjd * Note, in particular, that if a lock is sometimes acquired before 103168404Spjd * the tx assigns, and sometimes after (e.g. z_lock), then failing to 104168404Spjd * use a non-blocking assign can deadlock the system. The scenario: 105168404Spjd * 106168404Spjd * Thread A has grabbed a lock before calling dmu_tx_assign(). 107168404Spjd * Thread B is in an already-assigned tx, and blocks for this lock. 108168404Spjd * Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open() 109168404Spjd * forever, because the previous txg can't quiesce until B's tx commits. 110168404Spjd * 111168404Spjd * If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT, 112168404Spjd * then drop all locks, call dmu_tx_wait(), and try again. 113168404Spjd * 114168404Spjd * (5) If the operation succeeded, generate the intent log entry for it 115168404Spjd * before dropping locks. This ensures that the ordering of events 116168404Spjd * in the intent log matches the order in which they actually occurred. 117168404Spjd * 118168404Spjd * (6) At the end of each vnode op, the DMU tx must always commit, 119168404Spjd * regardless of whether there were any errors. 120168404Spjd * 121168404Spjd * (7) After dropping all locks, invoke zil_commit(zilog, seq, foid) 122168404Spjd * to ensure that synchronous semantics are provided when necessary. 123168404Spjd * 124168404Spjd * In general, this is how things should be ordered in each vnode op: 125168404Spjd * 126168404Spjd * ZFS_ENTER(zfsvfs); // exit if unmounted 127168404Spjd * top: 128168404Spjd * zfs_dirent_lock(&dl, ...) // lock directory entry (may VN_HOLD()) 129168404Spjd * rw_enter(...); // grab any other locks you need 130168404Spjd * tx = dmu_tx_create(...); // get DMU tx 131168404Spjd * dmu_tx_hold_*(); // hold each object you might modify 132168404Spjd * error = dmu_tx_assign(tx, zfsvfs->z_assign); // try to assign 133168404Spjd * if (error) { 134168404Spjd * rw_exit(...); // drop locks 135168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 136168404Spjd * VN_RELE(...); // release held vnodes 137168404Spjd * if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 138168404Spjd * dmu_tx_wait(tx); 139168404Spjd * dmu_tx_abort(tx); 140168404Spjd * goto top; 141168404Spjd * } 142168404Spjd * dmu_tx_abort(tx); // abort DMU tx 143168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 144168404Spjd * return (error); // really out of space 145168404Spjd * } 146168404Spjd * error = do_real_work(); // do whatever this VOP does 147168404Spjd * if (error == 0) 148168404Spjd * zfs_log_*(...); // on success, make ZIL entry 149168404Spjd * dmu_tx_commit(tx); // commit DMU tx -- error or not 150168404Spjd * rw_exit(...); // drop locks 151168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 152168404Spjd * VN_RELE(...); // release held vnodes 153168404Spjd * zil_commit(zilog, seq, foid); // synchronous when necessary 154168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 155168404Spjd * return (error); // done, report error 156168404Spjd */ 157168404Spjd/* ARGSUSED */ 158168404Spjdstatic int 159168962Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr) 160168404Spjd{ 161168962Spjd znode_t *zp = VTOZ(*vpp); 162168404Spjd 163168404Spjd /* Keep a count of the synchronous opens in the znode */ 164168962Spjd if (flag & (FSYNC | FDSYNC)) 165168404Spjd atomic_inc_32(&zp->z_sync_cnt); 166168404Spjd return (0); 167168404Spjd} 168168404Spjd 169168404Spjd/* ARGSUSED */ 170168404Spjdstatic int 171168962Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) 172168404Spjd{ 173168962Spjd znode_t *zp = VTOZ(vp); 174168404Spjd 175168404Spjd /* Decrement the synchronous opens in the znode */ 176168962Spjd if (flag & (FSYNC | FDSYNC)) 177168404Spjd atomic_dec_32(&zp->z_sync_cnt); 178168404Spjd 179168962Spjd /* 180168962Spjd * Clean up any locks held by this process on the vp. 181168962Spjd */ 182168962Spjd cleanlocks(vp, ddi_get_pid(), 0); 183168962Spjd cleanshares(vp, ddi_get_pid()); 184168962Spjd 185168404Spjd return (0); 186168404Spjd} 187168404Spjd 188168404Spjd/* 189168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and 190168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. 191168404Spjd */ 192168404Spjdstatic int 193168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off) 194168404Spjd{ 195168404Spjd znode_t *zp = VTOZ(vp); 196168404Spjd uint64_t noff = (uint64_t)*off; /* new offset */ 197168404Spjd uint64_t file_sz; 198168404Spjd int error; 199168404Spjd boolean_t hole; 200168404Spjd 201168404Spjd file_sz = zp->z_phys->zp_size; 202168404Spjd if (noff >= file_sz) { 203168404Spjd return (ENXIO); 204168404Spjd } 205168404Spjd 206168962Spjd if (cmd == _FIO_SEEK_HOLE) 207168404Spjd hole = B_TRUE; 208168404Spjd else 209168404Spjd hole = B_FALSE; 210168404Spjd 211168404Spjd error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); 212168404Spjd 213168404Spjd /* end of file? */ 214168404Spjd if ((error == ESRCH) || (noff > file_sz)) { 215168404Spjd /* 216168404Spjd * Handle the virtual hole at the end of file. 217168404Spjd */ 218168404Spjd if (hole) { 219168404Spjd *off = file_sz; 220168404Spjd return (0); 221168404Spjd } 222168404Spjd return (ENXIO); 223168404Spjd } 224168404Spjd 225168404Spjd if (noff < *off) 226168404Spjd return (error); 227168404Spjd *off = noff; 228168404Spjd return (error); 229168404Spjd} 230168404Spjd 231168404Spjd/* ARGSUSED */ 232168404Spjdstatic int 233168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred, 234168962Spjd int *rvalp) 235168404Spjd{ 236168962Spjd offset_t off; 237168962Spjd int error; 238168962Spjd zfsvfs_t *zfsvfs; 239168404Spjd 240168404Spjd switch (com) { 241168962Spjd case _FIOFFS: 242168962Spjd return (0); 243168404Spjd 244168962Spjd /* 245168962Spjd * The following two ioctls are used by bfu. Faking out, 246168962Spjd * necessary to avoid bfu errors. 247168962Spjd */ 248168962Spjd case _FIOGDIO: 249168962Spjd case _FIOSDIO: 250168962Spjd return (0); 251168962Spjd 252168962Spjd case _FIO_SEEK_DATA: 253168962Spjd case _FIO_SEEK_HOLE: 254168962Spjd if (ddi_copyin((void *)data, &off, sizeof (off), flag)) 255168962Spjd return (EFAULT); 256168962Spjd 257168404Spjd zfsvfs = VTOZ(vp)->z_zfsvfs; 258168404Spjd ZFS_ENTER(zfsvfs); 259168404Spjd 260168404Spjd /* offset parameter is in/out */ 261168404Spjd error = zfs_holey(vp, com, &off); 262168404Spjd ZFS_EXIT(zfsvfs); 263168404Spjd if (error) 264168404Spjd return (error); 265168962Spjd if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) 266168962Spjd return (EFAULT); 267168404Spjd return (0); 268168404Spjd } 269168404Spjd return (ENOTTY); 270168404Spjd} 271168404Spjd 272168404Spjd/* 273168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 274168404Spjd * between the DMU cache and the memory mapped pages. What this means: 275168404Spjd * 276168404Spjd * On Write: If we find a memory mapped page, we write to *both* 277168404Spjd * the page and the dmu buffer. 278168404Spjd * 279168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 280168404Spjd * the file is memory mapped. 281168404Spjd */ 282168404Spjdstatic int 283168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) 284168404Spjd{ 285168404Spjd znode_t *zp = VTOZ(vp); 286168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 287168404Spjd vm_object_t obj; 288168404Spjd vm_page_t m; 289168404Spjd struct sf_buf *sf; 290168404Spjd int64_t start, off; 291168404Spjd int len = nbytes; 292168404Spjd int error = 0; 293169059Spjd uint64_t dirbytes; 294168404Spjd 295168404Spjd ASSERT(vp->v_mount != NULL); 296168404Spjd obj = vp->v_object; 297168404Spjd ASSERT(obj != NULL); 298168404Spjd 299168404Spjd start = uio->uio_loffset; 300168404Spjd off = start & PAGEOFFSET; 301169059Spjd dirbytes = 0; 302168404Spjd VM_OBJECT_LOCK(obj); 303168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 304168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 305169059Spjd uint64_t fsize; 306168404Spjd 307168404Spjdagain: 308168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 309168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 310169059Spjd uint64_t woff; 311168404Spjd caddr_t va; 312168404Spjd 313168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) 314168404Spjd goto again; 315169059Spjd fsize = obj->un_pager.vnp.vnp_size; 316168404Spjd vm_page_busy(m); 317169057Spjd vm_page_lock_queues(); 318169057Spjd vm_page_undirty(m); 319169057Spjd vm_page_unlock_queues(); 320168404Spjd VM_OBJECT_UNLOCK(obj); 321169059Spjd if (dirbytes > 0) { 322169059Spjd error = dmu_write_uio(os, zp->z_id, uio, 323169059Spjd dirbytes, tx); 324169059Spjd dirbytes = 0; 325169059Spjd } 326169059Spjd if (error == 0) { 327169059Spjd sched_pin(); 328169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 329169059Spjd va = (caddr_t)sf_buf_kva(sf); 330169059Spjd woff = uio->uio_loffset - off; 331169059Spjd error = uiomove(va + off, bytes, UIO_WRITE, uio); 332169167Spjd /* 333169167Spjd * The uiomove() above could have been partially 334169167Spjd * successful, that's why we call dmu_write() 335169167Spjd * below unconditionally. The page was marked 336169167Spjd * non-dirty above and we would lose the changes 337169167Spjd * without doing so. If the uiomove() failed 338169167Spjd * entirely, well, we just write what we got 339169167Spjd * before one more time. 340169167Spjd */ 341169059Spjd dmu_write(os, zp->z_id, woff, 342169059Spjd MIN(PAGESIZE, fsize - woff), va, tx); 343169059Spjd sf_buf_free(sf); 344169059Spjd sched_unpin(); 345169059Spjd } 346168404Spjd VM_OBJECT_LOCK(obj); 347168404Spjd vm_page_wakeup(m); 348168404Spjd } else { 349169059Spjd dirbytes += bytes; 350168404Spjd } 351168404Spjd len -= bytes; 352168404Spjd off = 0; 353168404Spjd if (error) 354168404Spjd break; 355168404Spjd } 356168404Spjd VM_OBJECT_UNLOCK(obj); 357169059Spjd if (error == 0 && dirbytes > 0) 358169059Spjd error = dmu_write_uio(os, zp->z_id, uio, dirbytes, tx); 359168404Spjd return (error); 360168404Spjd} 361168404Spjd 362168404Spjd/* 363168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 364168404Spjd * between the DMU cache and the memory mapped pages. What this means: 365168404Spjd * 366168404Spjd * On Read: We "read" preferentially from memory mapped pages, 367168404Spjd * else we default from the dmu buffer. 368168404Spjd * 369168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 370168404Spjd * the file is memory mapped. 371168404Spjd */ 372168404Spjdstatic int 373168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio) 374168404Spjd{ 375168404Spjd znode_t *zp = VTOZ(vp); 376168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 377168404Spjd vm_object_t obj; 378168404Spjd vm_page_t m; 379168404Spjd struct sf_buf *sf; 380168404Spjd int64_t start, off; 381168926Spjd caddr_t va; 382168404Spjd int len = nbytes; 383168404Spjd int error = 0; 384169059Spjd uint64_t dirbytes; 385168404Spjd 386168404Spjd ASSERT(vp->v_mount != NULL); 387168404Spjd obj = vp->v_object; 388168404Spjd ASSERT(obj != NULL); 389168404Spjd 390168404Spjd start = uio->uio_loffset; 391168404Spjd off = start & PAGEOFFSET; 392169059Spjd dirbytes = 0; 393168404Spjd VM_OBJECT_LOCK(obj); 394168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 395168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 396168404Spjd 397168404Spjdagain: 398168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 399168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 400168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 401168404Spjd goto again; 402168404Spjd vm_page_busy(m); 403168404Spjd VM_OBJECT_UNLOCK(obj); 404169059Spjd if (dirbytes > 0) { 405169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 406169059Spjd dirbytes); 407169059Spjd dirbytes = 0; 408169059Spjd } 409169059Spjd if (error == 0) { 410169059Spjd sched_pin(); 411169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 412169059Spjd va = (caddr_t)sf_buf_kva(sf); 413169059Spjd error = uiomove(va + off, bytes, UIO_READ, uio); 414169059Spjd sf_buf_free(sf); 415169059Spjd sched_unpin(); 416169059Spjd } 417168404Spjd VM_OBJECT_LOCK(obj); 418168404Spjd vm_page_wakeup(m); 419168926Spjd } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { 420168962Spjd /* 421168962Spjd * The code below is here to make sendfile(2) work 422168962Spjd * correctly with ZFS. As pointed out by ups@ 423168962Spjd * sendfile(2) should be changed to use VOP_GETPAGES(), 424168962Spjd * but it pessimize performance of sendfile/UFS, that's 425168962Spjd * why I handle this special case in ZFS code. 426168962Spjd */ 427168926Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 428168926Spjd goto again; 429168926Spjd vm_page_busy(m); 430168926Spjd VM_OBJECT_UNLOCK(obj); 431169059Spjd if (dirbytes > 0) { 432169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 433169059Spjd dirbytes); 434169059Spjd dirbytes = 0; 435169059Spjd } 436169059Spjd if (error == 0) { 437169059Spjd sched_pin(); 438169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 439169059Spjd va = (caddr_t)sf_buf_kva(sf); 440169059Spjd error = dmu_read(os, zp->z_id, start + off, 441169059Spjd bytes, (void *)(va + off)); 442169059Spjd sf_buf_free(sf); 443169059Spjd sched_unpin(); 444169059Spjd } 445168926Spjd VM_OBJECT_LOCK(obj); 446168926Spjd vm_page_wakeup(m); 447169059Spjd if (error == 0) 448169059Spjd uio->uio_resid -= bytes; 449168404Spjd } else { 450169059Spjd dirbytes += bytes; 451168404Spjd } 452168404Spjd len -= bytes; 453168404Spjd off = 0; 454168404Spjd if (error) 455168404Spjd break; 456168404Spjd } 457168404Spjd VM_OBJECT_UNLOCK(obj); 458169059Spjd if (error == 0 && dirbytes > 0) 459169059Spjd error = dmu_read_uio(os, zp->z_id, uio, dirbytes); 460168404Spjd return (error); 461168404Spjd} 462168404Spjd 463168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */ 464168404Spjd 465168404Spjd/* 466168404Spjd * Read bytes from specified file into supplied buffer. 467168404Spjd * 468168404Spjd * IN: vp - vnode of file to be read from. 469168404Spjd * uio - structure supplying read location, range info, 470168404Spjd * and return buffer. 471168404Spjd * ioflag - SYNC flags; used to provide FRSYNC semantics. 472168404Spjd * cr - credentials of caller. 473168404Spjd * 474168404Spjd * OUT: uio - updated offset and range, buffer filled. 475168404Spjd * 476168404Spjd * RETURN: 0 if success 477168404Spjd * error code if failure 478168404Spjd * 479168404Spjd * Side Effects: 480168404Spjd * vp - atime updated if byte count > 0 481168404Spjd */ 482168404Spjd/* ARGSUSED */ 483168404Spjdstatic int 484168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 485168404Spjd{ 486168404Spjd znode_t *zp = VTOZ(vp); 487168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 488168404Spjd objset_t *os = zfsvfs->z_os; 489168404Spjd ssize_t n, nbytes; 490168404Spjd int error; 491168404Spjd rl_t *rl; 492168404Spjd 493168404Spjd ZFS_ENTER(zfsvfs); 494168404Spjd 495168404Spjd /* 496168404Spjd * Validate file offset 497168404Spjd */ 498168404Spjd if (uio->uio_loffset < (offset_t)0) { 499168404Spjd ZFS_EXIT(zfsvfs); 500168404Spjd return (EINVAL); 501168404Spjd } 502168404Spjd 503168404Spjd /* 504168404Spjd * Fasttrack empty reads 505168404Spjd */ 506168404Spjd if (uio->uio_resid == 0) { 507168404Spjd ZFS_EXIT(zfsvfs); 508168404Spjd return (0); 509168404Spjd } 510168404Spjd 511168404Spjd /* 512168962Spjd * Check for mandatory locks 513168962Spjd */ 514168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode)) { 515168962Spjd if (error = chklock(vp, FREAD, 516168962Spjd uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { 517168962Spjd ZFS_EXIT(zfsvfs); 518168962Spjd return (error); 519168962Spjd } 520168962Spjd } 521168962Spjd 522168962Spjd /* 523168404Spjd * If we're in FRSYNC mode, sync out this znode before reading it. 524168404Spjd */ 525168962Spjd if (ioflag & FRSYNC) 526168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 527168404Spjd 528168404Spjd /* 529168404Spjd * Lock the range against changes. 530168404Spjd */ 531168404Spjd rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER); 532168404Spjd 533168404Spjd /* 534168404Spjd * If we are reading past end-of-file we can skip 535168404Spjd * to the end; but we might still need to set atime. 536168404Spjd */ 537168404Spjd if (uio->uio_loffset >= zp->z_phys->zp_size) { 538168404Spjd error = 0; 539168404Spjd goto out; 540168404Spjd } 541168404Spjd 542168404Spjd ASSERT(uio->uio_loffset < zp->z_phys->zp_size); 543168404Spjd n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset); 544168404Spjd 545168404Spjd while (n > 0) { 546168404Spjd nbytes = MIN(n, zfs_read_chunk_size - 547168404Spjd P2PHASE(uio->uio_loffset, zfs_read_chunk_size)); 548168404Spjd 549168404Spjd if (vn_has_cached_data(vp)) 550168404Spjd error = mappedread(vp, nbytes, uio); 551168404Spjd else 552168404Spjd error = dmu_read_uio(os, zp->z_id, uio, nbytes); 553168404Spjd if (error) 554168404Spjd break; 555168962Spjd 556168404Spjd n -= nbytes; 557168404Spjd } 558168404Spjd 559168404Spjdout: 560168404Spjd zfs_range_unlock(rl); 561168404Spjd 562168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 563168404Spjd ZFS_EXIT(zfsvfs); 564168404Spjd return (error); 565168404Spjd} 566168404Spjd 567168404Spjd/* 568168404Spjd * Fault in the pages of the first n bytes specified by the uio structure. 569168404Spjd * 1 byte in each page is touched and the uio struct is unmodified. 570168404Spjd * Any error will exit this routine as this is only a best 571168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch(). 572168404Spjd */ 573168404Spjdstatic void 574168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio) 575168404Spjd{ 576168404Spjd struct iovec *iov; 577168404Spjd ulong_t cnt, incr; 578168404Spjd caddr_t p; 579168404Spjd 580168404Spjd if (uio->uio_segflg != UIO_USERSPACE) 581168404Spjd return; 582168404Spjd 583168404Spjd iov = uio->uio_iov; 584168404Spjd 585168404Spjd while (n) { 586168404Spjd cnt = MIN(iov->iov_len, n); 587168404Spjd if (cnt == 0) { 588168404Spjd /* empty iov entry */ 589168404Spjd iov++; 590168404Spjd continue; 591168404Spjd } 592168404Spjd n -= cnt; 593168404Spjd /* 594168404Spjd * touch each page in this segment. 595168404Spjd */ 596168404Spjd p = iov->iov_base; 597168404Spjd while (cnt) { 598168404Spjd if (fubyte(p) == -1) 599168404Spjd return; 600168404Spjd incr = MIN(cnt, PAGESIZE); 601168404Spjd p += incr; 602168404Spjd cnt -= incr; 603168404Spjd } 604168404Spjd /* 605168404Spjd * touch the last byte in case it straddles a page. 606168404Spjd */ 607168404Spjd p--; 608168404Spjd if (fubyte(p) == -1) 609168404Spjd return; 610168404Spjd iov++; 611168404Spjd } 612168404Spjd} 613168404Spjd 614168404Spjd/* 615168404Spjd * Write the bytes to a file. 616168404Spjd * 617168404Spjd * IN: vp - vnode of file to be written to. 618168404Spjd * uio - structure supplying write location, range info, 619168404Spjd * and data buffer. 620168404Spjd * ioflag - IO_APPEND flag set if in append mode. 621168404Spjd * cr - credentials of caller. 622168404Spjd * 623168404Spjd * OUT: uio - updated offset and range. 624168404Spjd * 625168404Spjd * RETURN: 0 if success 626168404Spjd * error code if failure 627168404Spjd * 628168404Spjd * Timestamps: 629168404Spjd * vp - ctime|mtime updated if byte count > 0 630168404Spjd */ 631168404Spjd/* ARGSUSED */ 632168404Spjdstatic int 633168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 634168404Spjd{ 635168404Spjd znode_t *zp = VTOZ(vp); 636168962Spjd rlim64_t limit = MAXOFFSET_T; 637168404Spjd ssize_t start_resid = uio->uio_resid; 638168404Spjd ssize_t tx_bytes; 639168404Spjd uint64_t end_size; 640168404Spjd dmu_tx_t *tx; 641168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 642168404Spjd zilog_t *zilog = zfsvfs->z_log; 643168404Spjd offset_t woff; 644168404Spjd ssize_t n, nbytes; 645168404Spjd rl_t *rl; 646168404Spjd int max_blksz = zfsvfs->z_max_blksz; 647168404Spjd int error; 648168404Spjd 649168404Spjd /* 650168404Spjd * Fasttrack empty write 651168404Spjd */ 652168404Spjd n = start_resid; 653168404Spjd if (n == 0) 654168404Spjd return (0); 655168404Spjd 656168962Spjd if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 657168962Spjd limit = MAXOFFSET_T; 658168962Spjd 659168404Spjd ZFS_ENTER(zfsvfs); 660168404Spjd 661168404Spjd /* 662168404Spjd * Pre-fault the pages to ensure slow (eg NFS) pages 663168404Spjd * don't hold up txg. 664168404Spjd */ 665168404Spjd zfs_prefault_write(n, uio); 666168404Spjd 667168404Spjd /* 668168404Spjd * If in append mode, set the io offset pointer to eof. 669168404Spjd */ 670168404Spjd if (ioflag & IO_APPEND) { 671168404Spjd /* 672168404Spjd * Range lock for a file append: 673168404Spjd * The value for the start of range will be determined by 674168404Spjd * zfs_range_lock() (to guarantee append semantics). 675168404Spjd * If this write will cause the block size to increase, 676168404Spjd * zfs_range_lock() will lock the entire file, so we must 677168404Spjd * later reduce the range after we grow the block size. 678168404Spjd */ 679168404Spjd rl = zfs_range_lock(zp, 0, n, RL_APPEND); 680168404Spjd if (rl->r_len == UINT64_MAX) { 681168404Spjd /* overlocked, zp_size can't change */ 682168404Spjd woff = uio->uio_loffset = zp->z_phys->zp_size; 683168404Spjd } else { 684168404Spjd woff = uio->uio_loffset = rl->r_off; 685168404Spjd } 686168404Spjd } else { 687168404Spjd woff = uio->uio_loffset; 688168404Spjd /* 689168404Spjd * Validate file offset 690168404Spjd */ 691168404Spjd if (woff < 0) { 692168404Spjd ZFS_EXIT(zfsvfs); 693168404Spjd return (EINVAL); 694168404Spjd } 695168404Spjd 696168404Spjd /* 697168404Spjd * If we need to grow the block size then zfs_range_lock() 698168404Spjd * will lock a wider range than we request here. 699168404Spjd * Later after growing the block size we reduce the range. 700168404Spjd */ 701168404Spjd rl = zfs_range_lock(zp, woff, n, RL_WRITER); 702168404Spjd } 703168404Spjd 704168962Spjd if (woff >= limit) { 705168962Spjd zfs_range_unlock(rl); 706168962Spjd ZFS_EXIT(zfsvfs); 707168962Spjd return (EFBIG); 708168962Spjd } 709168962Spjd 710168962Spjd if ((woff + n) > limit || woff > (limit - n)) 711168962Spjd n = limit - woff; 712168962Spjd 713168962Spjd /* 714168962Spjd * Check for mandatory locks 715168962Spjd */ 716168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode) && 717168962Spjd (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { 718168962Spjd zfs_range_unlock(rl); 719168962Spjd ZFS_EXIT(zfsvfs); 720168962Spjd return (error); 721168962Spjd } 722168404Spjd end_size = MAX(zp->z_phys->zp_size, woff + n); 723168404Spjd 724168404Spjd /* 725168404Spjd * Write the file in reasonable size chunks. Each chunk is written 726168404Spjd * in a separate transaction; this keeps the intent log records small 727168404Spjd * and allows us to do more fine-grained space accounting. 728168404Spjd */ 729168404Spjd while (n > 0) { 730168404Spjd /* 731168404Spjd * Start a transaction. 732168404Spjd */ 733168404Spjd woff = uio->uio_loffset; 734168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 735168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 736168404Spjd dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); 737168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 738168404Spjd if (error) { 739168404Spjd if (error == ERESTART && 740168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 741168404Spjd dmu_tx_wait(tx); 742168404Spjd dmu_tx_abort(tx); 743168404Spjd continue; 744168404Spjd } 745168404Spjd dmu_tx_abort(tx); 746168404Spjd break; 747168404Spjd } 748168404Spjd 749168404Spjd /* 750168404Spjd * If zfs_range_lock() over-locked we grow the blocksize 751168404Spjd * and then reduce the lock range. This will only happen 752168404Spjd * on the first iteration since zfs_range_reduce() will 753168404Spjd * shrink down r_len to the appropriate size. 754168404Spjd */ 755168404Spjd if (rl->r_len == UINT64_MAX) { 756168404Spjd uint64_t new_blksz; 757168404Spjd 758168404Spjd if (zp->z_blksz > max_blksz) { 759168404Spjd ASSERT(!ISP2(zp->z_blksz)); 760168404Spjd new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE); 761168404Spjd } else { 762168404Spjd new_blksz = MIN(end_size, max_blksz); 763168404Spjd } 764168404Spjd zfs_grow_blocksize(zp, new_blksz, tx); 765168404Spjd zfs_range_reduce(rl, woff, n); 766168404Spjd } 767168404Spjd 768168404Spjd /* 769168404Spjd * XXX - should we really limit each write to z_max_blksz? 770168404Spjd * Perhaps we should use SPA_MAXBLOCKSIZE chunks? 771168404Spjd */ 772168404Spjd nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz)); 773168404Spjd 774168404Spjd if (woff + nbytes > zp->z_phys->zp_size) 775168404Spjd vnode_pager_setsize(vp, woff + nbytes); 776168404Spjd 777169302Spjd rw_enter(&zp->z_map_lock, RW_READER); 778169302Spjd 779168962Spjd tx_bytes = uio->uio_resid; 780168404Spjd if (vn_has_cached_data(vp)) { 781168404Spjd rw_exit(&zp->z_map_lock); 782168404Spjd error = mappedwrite(vp, nbytes, uio, tx); 783168404Spjd } else { 784168404Spjd error = dmu_write_uio(zfsvfs->z_os, zp->z_id, 785168404Spjd uio, nbytes, tx); 786168404Spjd rw_exit(&zp->z_map_lock); 787168404Spjd } 788168404Spjd tx_bytes -= uio->uio_resid; 789168404Spjd 790168404Spjd /* 791168404Spjd * If we made no progress, we're done. If we made even 792168404Spjd * partial progress, update the znode and ZIL accordingly. 793168404Spjd */ 794168404Spjd if (tx_bytes == 0) { 795168404Spjd dmu_tx_commit(tx); 796168404Spjd ASSERT(error != 0); 797168404Spjd break; 798168404Spjd } 799168404Spjd 800168404Spjd /* 801168404Spjd * Clear Set-UID/Set-GID bits on successful write if not 802168404Spjd * privileged and at least one of the excute bits is set. 803168404Spjd * 804168404Spjd * It would be nice to to this after all writes have 805168404Spjd * been done, but that would still expose the ISUID/ISGID 806168404Spjd * to another app after the partial write is committed. 807168404Spjd */ 808168404Spjd mutex_enter(&zp->z_acl_lock); 809168404Spjd if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) | 810168404Spjd (S_IXUSR >> 6))) != 0 && 811168404Spjd (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 && 812168404Spjd secpolicy_vnode_setid_retain(cr, 813168404Spjd (zp->z_phys->zp_mode & S_ISUID) != 0 && 814168404Spjd zp->z_phys->zp_uid == 0) != 0) { 815168404Spjd zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID); 816168404Spjd } 817168404Spjd mutex_exit(&zp->z_acl_lock); 818168404Spjd 819168404Spjd /* 820168404Spjd * Update time stamp. NOTE: This marks the bonus buffer as 821168404Spjd * dirty, so we don't have to do it again for zp_size. 822168404Spjd */ 823168404Spjd zfs_time_stamper(zp, CONTENT_MODIFIED, tx); 824168404Spjd 825168404Spjd /* 826168404Spjd * Update the file size (zp_size) if it has changed; 827168404Spjd * account for possible concurrent updates. 828168404Spjd */ 829168404Spjd while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset) 830168404Spjd (void) atomic_cas_64(&zp->z_phys->zp_size, end_size, 831168404Spjd uio->uio_loffset); 832168404Spjd zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); 833168404Spjd dmu_tx_commit(tx); 834168404Spjd 835168404Spjd if (error != 0) 836168404Spjd break; 837168404Spjd ASSERT(tx_bytes == nbytes); 838168404Spjd n -= nbytes; 839168404Spjd } 840168404Spjd 841168404Spjd zfs_range_unlock(rl); 842168404Spjd 843168404Spjd /* 844168404Spjd * If we're in replay mode, or we made no progress, return error. 845168404Spjd * Otherwise, it's at least a partial write, so it's successful. 846168404Spjd */ 847168404Spjd if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) { 848168404Spjd ZFS_EXIT(zfsvfs); 849168404Spjd return (error); 850168404Spjd } 851168404Spjd 852168962Spjd if (ioflag & (FSYNC | FDSYNC)) 853168404Spjd zil_commit(zilog, zp->z_last_itx, zp->z_id); 854168404Spjd 855168404Spjd ZFS_EXIT(zfsvfs); 856168404Spjd return (0); 857168404Spjd} 858168404Spjd 859168404Spjdvoid 860168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd) 861168404Spjd{ 862168404Spjd zgd_t *zgd = (zgd_t *)vzgd; 863168404Spjd rl_t *rl = zgd->zgd_rl; 864168404Spjd vnode_t *vp = ZTOV(rl->r_zp); 865168404Spjd int vfslocked; 866168404Spjd 867168404Spjd vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); 868168404Spjd dmu_buf_rele(db, vzgd); 869168404Spjd zfs_range_unlock(rl); 870168404Spjd VN_RELE(vp); 871168404Spjd zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp))); 872168404Spjd kmem_free(zgd, sizeof (zgd_t)); 873168404Spjd VFS_UNLOCK_GIANT(vfslocked); 874168404Spjd} 875168404Spjd 876168404Spjd/* 877168404Spjd * Get data to generate a TX_WRITE intent log record. 878168404Spjd */ 879168404Spjdint 880168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) 881168404Spjd{ 882168404Spjd zfsvfs_t *zfsvfs = arg; 883168404Spjd objset_t *os = zfsvfs->z_os; 884168404Spjd znode_t *zp; 885168404Spjd uint64_t off = lr->lr_offset; 886168404Spjd dmu_buf_t *db; 887168404Spjd rl_t *rl; 888168404Spjd zgd_t *zgd; 889168404Spjd int dlen = lr->lr_length; /* length of user data */ 890168404Spjd int error = 0; 891168404Spjd 892168404Spjd ASSERT(zio); 893168404Spjd ASSERT(dlen != 0); 894168404Spjd 895168404Spjd /* 896168404Spjd * Nothing to do if the file has been removed 897168404Spjd */ 898168404Spjd if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0) 899168404Spjd return (ENOENT); 900168404Spjd if (zp->z_unlinked) { 901168404Spjd VN_RELE(ZTOV(zp)); 902168404Spjd return (ENOENT); 903168404Spjd } 904168404Spjd 905168404Spjd /* 906168404Spjd * Write records come in two flavors: immediate and indirect. 907168404Spjd * For small writes it's cheaper to store the data with the 908168404Spjd * log record (immediate); for large writes it's cheaper to 909168404Spjd * sync the data and get a pointer to it (indirect) so that 910168404Spjd * we don't have to write the data twice. 911168404Spjd */ 912168404Spjd if (buf != NULL) { /* immediate write */ 913168404Spjd rl = zfs_range_lock(zp, off, dlen, RL_READER); 914168404Spjd /* test for truncation needs to be done while range locked */ 915168404Spjd if (off >= zp->z_phys->zp_size) { 916168404Spjd error = ENOENT; 917168404Spjd goto out; 918168404Spjd } 919168404Spjd VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf)); 920168404Spjd } else { /* indirect write */ 921168404Spjd uint64_t boff; /* block starting offset */ 922168404Spjd 923168404Spjd /* 924168404Spjd * Have to lock the whole block to ensure when it's 925168404Spjd * written out and it's checksum is being calculated 926168404Spjd * that no one can change the data. We need to re-check 927168404Spjd * blocksize after we get the lock in case it's changed! 928168404Spjd */ 929168404Spjd for (;;) { 930168404Spjd if (ISP2(zp->z_blksz)) { 931168404Spjd boff = P2ALIGN_TYPED(off, zp->z_blksz, 932168404Spjd uint64_t); 933168404Spjd } else { 934168404Spjd boff = 0; 935168404Spjd } 936168404Spjd dlen = zp->z_blksz; 937168404Spjd rl = zfs_range_lock(zp, boff, dlen, RL_READER); 938168404Spjd if (zp->z_blksz == dlen) 939168404Spjd break; 940168404Spjd zfs_range_unlock(rl); 941168404Spjd } 942168404Spjd /* test for truncation needs to be done while range locked */ 943168404Spjd if (off >= zp->z_phys->zp_size) { 944168404Spjd error = ENOENT; 945168404Spjd goto out; 946168404Spjd } 947168404Spjd zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP); 948168404Spjd zgd->zgd_rl = rl; 949168404Spjd zgd->zgd_zilog = zfsvfs->z_log; 950168404Spjd zgd->zgd_bp = &lr->lr_blkptr; 951168404Spjd VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db)); 952168404Spjd ASSERT(boff == db->db_offset); 953168404Spjd lr->lr_blkoff = off - boff; 954168404Spjd error = dmu_sync(zio, db, &lr->lr_blkptr, 955168404Spjd lr->lr_common.lrc_txg, zfs_get_done, zgd); 956168404Spjd ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz); 957168404Spjd if (error == 0) { 958168404Spjd zil_add_vdev(zfsvfs->z_log, 959168404Spjd DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr))); 960168404Spjd } 961168404Spjd /* 962168404Spjd * If we get EINPROGRESS, then we need to wait for a 963168404Spjd * write IO initiated by dmu_sync() to complete before 964168404Spjd * we can release this dbuf. We will finish everything 965168404Spjd * up in the zfs_get_done() callback. 966168404Spjd */ 967168404Spjd if (error == EINPROGRESS) 968168404Spjd return (0); 969168404Spjd dmu_buf_rele(db, zgd); 970168404Spjd kmem_free(zgd, sizeof (zgd_t)); 971168404Spjd } 972168404Spjdout: 973168404Spjd zfs_range_unlock(rl); 974168404Spjd VN_RELE(ZTOV(zp)); 975168404Spjd return (error); 976168404Spjd} 977168404Spjd 978168404Spjd/*ARGSUSED*/ 979168404Spjdstatic int 980168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr) 981168404Spjd{ 982168404Spjd znode_t *zp = VTOZ(vp); 983168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 984168404Spjd int error; 985168404Spjd 986168404Spjd ZFS_ENTER(zfsvfs); 987168962Spjd error = zfs_zaccess_rwx(zp, mode, cr); 988168404Spjd ZFS_EXIT(zfsvfs); 989168404Spjd return (error); 990168404Spjd} 991168404Spjd 992168404Spjd/* 993168404Spjd * Lookup an entry in a directory, or an extended attribute directory. 994168404Spjd * If it exists, return a held vnode reference for it. 995168404Spjd * 996168404Spjd * IN: dvp - vnode of directory to search. 997168404Spjd * nm - name of entry to lookup. 998168404Spjd * pnp - full pathname to lookup [UNUSED]. 999168404Spjd * flags - LOOKUP_XATTR set if looking for an attribute. 1000168404Spjd * rdir - root directory vnode [UNUSED]. 1001168404Spjd * cr - credentials of caller. 1002168404Spjd * 1003168404Spjd * OUT: vpp - vnode of located entry, NULL if not found. 1004168404Spjd * 1005168404Spjd * RETURN: 0 if success 1006168404Spjd * error code if failure 1007168404Spjd * 1008168404Spjd * Timestamps: 1009168404Spjd * NA 1010168404Spjd */ 1011168404Spjd/* ARGSUSED */ 1012168962Spjdstatic int 1013168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, 1014169170Spjd int nameiop, cred_t *cr, kthread_t *td) 1015168404Spjd{ 1016168404Spjd 1017168962Spjd znode_t *zdp = VTOZ(dvp); 1018168962Spjd zfsvfs_t *zfsvfs = zdp->z_zfsvfs; 1019168962Spjd int error; 1020168404Spjd 1021168404Spjd ZFS_ENTER(zfsvfs); 1022168404Spjd 1023168404Spjd *vpp = NULL; 1024168404Spjd 1025168404Spjd#ifdef TODO 1026168404Spjd if (flags & LOOKUP_XATTR) { 1027168404Spjd /* 1028168404Spjd * If the xattr property is off, refuse the lookup request. 1029168404Spjd */ 1030168404Spjd if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) { 1031168404Spjd ZFS_EXIT(zfsvfs); 1032168404Spjd return (EINVAL); 1033168404Spjd } 1034168404Spjd 1035168404Spjd /* 1036168404Spjd * We don't allow recursive attributes.. 1037168404Spjd * Maybe someday we will. 1038168404Spjd */ 1039168404Spjd if (zdp->z_phys->zp_flags & ZFS_XATTR) { 1040168404Spjd ZFS_EXIT(zfsvfs); 1041168404Spjd return (EINVAL); 1042168404Spjd } 1043168404Spjd 1044168404Spjd if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) { 1045168404Spjd ZFS_EXIT(zfsvfs); 1046168404Spjd return (error); 1047168404Spjd } 1048168404Spjd 1049168404Spjd /* 1050168404Spjd * Do we have permission to get into attribute directory? 1051168404Spjd */ 1052168404Spjd 1053168404Spjd if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) { 1054168404Spjd VN_RELE(*vpp); 1055168404Spjd } 1056168404Spjd 1057168404Spjd ZFS_EXIT(zfsvfs); 1058168404Spjd return (error); 1059168404Spjd } 1060168404Spjd#endif /* TODO */ 1061168404Spjd 1062168404Spjd if (dvp->v_type != VDIR) { 1063168404Spjd ZFS_EXIT(zfsvfs); 1064168404Spjd return (ENOTDIR); 1065168404Spjd } 1066168404Spjd 1067168404Spjd /* 1068168404Spjd * Check accessibility of directory. 1069168404Spjd */ 1070168404Spjd 1071168404Spjd if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) { 1072168404Spjd ZFS_EXIT(zfsvfs); 1073168404Spjd return (error); 1074168404Spjd } 1075168404Spjd 1076168962Spjd if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) { 1077168404Spjd 1078168962Spjd /* 1079168962Spjd * Convert device special files 1080168962Spjd */ 1081168962Spjd if (IS_DEVVP(*vpp)) { 1082168962Spjd vnode_t *svp; 1083168962Spjd 1084168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1085168962Spjd VN_RELE(*vpp); 1086168962Spjd if (svp == NULL) 1087168962Spjd error = ENOSYS; 1088168962Spjd else 1089168962Spjd *vpp = svp; 1090168962Spjd } 1091168962Spjd } 1092168962Spjd 1093168404Spjd ZFS_EXIT(zfsvfs); 1094168404Spjd 1095168404Spjd /* Translate errors and add SAVENAME when needed. */ 1096168404Spjd if (cnp->cn_flags & ISLASTCN) { 1097168404Spjd switch (nameiop) { 1098168404Spjd case CREATE: 1099168404Spjd case RENAME: 1100168404Spjd if (error == ENOENT) { 1101168404Spjd error = EJUSTRETURN; 1102168404Spjd cnp->cn_flags |= SAVENAME; 1103168404Spjd break; 1104168404Spjd } 1105168404Spjd /* FALLTHROUGH */ 1106168404Spjd case DELETE: 1107168404Spjd if (error == 0) 1108168404Spjd cnp->cn_flags |= SAVENAME; 1109168404Spjd break; 1110168404Spjd } 1111168404Spjd } 1112168404Spjd if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) { 1113169198Spjd int ltype = 0; 1114169198Spjd 1115169198Spjd if (cnp->cn_flags & ISDOTDOT) { 1116176559Sattilio ltype = VOP_ISLOCKED(dvp); 1117175294Sattilio VOP_UNLOCK(dvp, 0); 1118169198Spjd } 1119175202Sattilio error = vn_lock(*vpp, cnp->cn_lkflags); 1120168962Spjd if (cnp->cn_flags & ISDOTDOT) 1121175202Sattilio vn_lock(dvp, ltype | LK_RETRY); 1122169172Spjd if (error != 0) { 1123169172Spjd VN_RELE(*vpp); 1124169172Spjd *vpp = NULL; 1125169172Spjd return (error); 1126169172Spjd } 1127168404Spjd } 1128168404Spjd 1129168404Spjd#ifdef FREEBSD_NAMECACHE 1130168404Spjd /* 1131168404Spjd * Insert name into cache (as non-existent) if appropriate. 1132168404Spjd */ 1133168404Spjd if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 1134168404Spjd cache_enter(dvp, *vpp, cnp); 1135169170Spjd /* 1136169170Spjd * Insert name into cache if appropriate. 1137169170Spjd */ 1138168404Spjd if (error == 0 && (cnp->cn_flags & MAKEENTRY)) { 1139168404Spjd if (!(cnp->cn_flags & ISLASTCN) || 1140168404Spjd (nameiop != DELETE && nameiop != RENAME)) { 1141168404Spjd cache_enter(dvp, *vpp, cnp); 1142168404Spjd } 1143168404Spjd } 1144168404Spjd#endif 1145168404Spjd 1146168404Spjd return (error); 1147168404Spjd} 1148168404Spjd 1149168404Spjd/* 1150168404Spjd * Attempt to create a new entry in a directory. If the entry 1151168404Spjd * already exists, truncate the file if permissible, else return 1152168404Spjd * an error. Return the vp of the created or trunc'd file. 1153168404Spjd * 1154168404Spjd * IN: dvp - vnode of directory to put new file entry in. 1155168404Spjd * name - name of new file entry. 1156168404Spjd * vap - attributes of new file. 1157168404Spjd * excl - flag indicating exclusive or non-exclusive mode. 1158168404Spjd * mode - mode to open file with. 1159168404Spjd * cr - credentials of caller. 1160168404Spjd * flag - large file flag [UNUSED]. 1161168404Spjd * 1162168404Spjd * OUT: vpp - vnode of created or trunc'd entry. 1163168404Spjd * 1164168404Spjd * RETURN: 0 if success 1165168404Spjd * error code if failure 1166168404Spjd * 1167168404Spjd * Timestamps: 1168168404Spjd * dvp - ctime|mtime updated if new entry created 1169168404Spjd * vp - ctime|mtime always, atime if new 1170168404Spjd */ 1171168404Spjd/* ARGSUSED */ 1172168404Spjdstatic int 1173168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode, 1174176559Sattilio vnode_t **vpp, cred_t *cr) 1175168404Spjd{ 1176168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1177168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1178168404Spjd zilog_t *zilog = zfsvfs->z_log; 1179168404Spjd objset_t *os = zfsvfs->z_os; 1180168404Spjd zfs_dirlock_t *dl; 1181168404Spjd dmu_tx_t *tx; 1182168404Spjd int error; 1183168404Spjd uint64_t zoid; 1184168404Spjd 1185168404Spjd ZFS_ENTER(zfsvfs); 1186168404Spjd 1187168404Spjdtop: 1188168404Spjd *vpp = NULL; 1189168404Spjd 1190168404Spjd if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr)) 1191168404Spjd vap->va_mode &= ~VSVTX; 1192168404Spjd 1193168404Spjd if (*name == '\0') { 1194168404Spjd /* 1195168404Spjd * Null component name refers to the directory itself. 1196168404Spjd */ 1197168404Spjd VN_HOLD(dvp); 1198168404Spjd zp = dzp; 1199168404Spjd dl = NULL; 1200168404Spjd error = 0; 1201168404Spjd } else { 1202168404Spjd /* possible VN_HOLD(zp) */ 1203168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) { 1204168404Spjd if (strcmp(name, "..") == 0) 1205168404Spjd error = EISDIR; 1206168404Spjd ZFS_EXIT(zfsvfs); 1207168404Spjd return (error); 1208168404Spjd } 1209168404Spjd } 1210168404Spjd 1211168404Spjd zoid = zp ? zp->z_id : -1ULL; 1212168404Spjd 1213168404Spjd if (zp == NULL) { 1214168404Spjd /* 1215168404Spjd * Create a new file object and update the directory 1216168404Spjd * to reference it. 1217168404Spjd */ 1218168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 1219168404Spjd goto out; 1220168404Spjd } 1221168404Spjd 1222168404Spjd /* 1223168404Spjd * We only support the creation of regular files in 1224168404Spjd * extended attribute directories. 1225168404Spjd */ 1226168404Spjd if ((dzp->z_phys->zp_flags & ZFS_XATTR) && 1227168404Spjd (vap->va_type != VREG)) { 1228168404Spjd error = EINVAL; 1229168404Spjd goto out; 1230168404Spjd } 1231168404Spjd 1232168404Spjd tx = dmu_tx_create(os); 1233168404Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1234168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 1235168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 1236168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1237168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1238168404Spjd 0, SPA_MAXBLOCKSIZE); 1239168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1240168404Spjd if (error) { 1241168404Spjd zfs_dirent_unlock(dl); 1242168404Spjd if (error == ERESTART && 1243168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1244168404Spjd dmu_tx_wait(tx); 1245168404Spjd dmu_tx_abort(tx); 1246168404Spjd goto top; 1247168404Spjd } 1248168404Spjd dmu_tx_abort(tx); 1249168404Spjd ZFS_EXIT(zfsvfs); 1250168404Spjd return (error); 1251168404Spjd } 1252168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1253168404Spjd ASSERT(zp->z_id == zoid); 1254168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1255168404Spjd zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name); 1256168404Spjd dmu_tx_commit(tx); 1257168404Spjd } else { 1258168404Spjd /* 1259168404Spjd * A directory entry already exists for this name. 1260168404Spjd */ 1261168404Spjd /* 1262168962Spjd * Can't truncate an existing file if in exclusive mode. 1263168962Spjd */ 1264168962Spjd if (excl == EXCL) { 1265168962Spjd error = EEXIST; 1266168962Spjd goto out; 1267168962Spjd } 1268168962Spjd /* 1269168404Spjd * Can't open a directory for writing. 1270168404Spjd */ 1271168404Spjd if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) { 1272168404Spjd error = EISDIR; 1273168404Spjd goto out; 1274168404Spjd } 1275168404Spjd /* 1276168404Spjd * Verify requested access to file. 1277168404Spjd */ 1278168404Spjd if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) { 1279168404Spjd goto out; 1280168404Spjd } 1281168404Spjd 1282168404Spjd mutex_enter(&dzp->z_lock); 1283168404Spjd dzp->z_seq++; 1284168404Spjd mutex_exit(&dzp->z_lock); 1285168404Spjd 1286168404Spjd /* 1287168404Spjd * Truncate regular files if requested. 1288168404Spjd */ 1289168404Spjd if ((ZTOV(zp)->v_type == VREG) && 1290168404Spjd (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) { 1291168404Spjd error = zfs_freesp(zp, 0, 0, mode, TRUE); 1292168404Spjd if (error == ERESTART && 1293168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1294168404Spjd /* NB: we already did dmu_tx_wait() */ 1295168404Spjd zfs_dirent_unlock(dl); 1296168404Spjd VN_RELE(ZTOV(zp)); 1297168404Spjd goto top; 1298168404Spjd } 1299168404Spjd } 1300168404Spjd } 1301168404Spjdout: 1302168404Spjd 1303168404Spjd if (error == 0) { 1304168404Spjd *vpp = ZTOV(zp); 1305175202Sattilio vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 1306168404Spjd } 1307168404Spjd 1308168404Spjd if (dl) 1309168404Spjd zfs_dirent_unlock(dl); 1310168404Spjd 1311168404Spjd if (error) { 1312168404Spjd if (zp) 1313168404Spjd VN_RELE(ZTOV(zp)); 1314168962Spjd } else { 1315168962Spjd *vpp = ZTOV(zp); 1316168962Spjd /* 1317168962Spjd * If vnode is for a device return a specfs vnode instead. 1318168962Spjd */ 1319168962Spjd if (IS_DEVVP(*vpp)) { 1320168962Spjd struct vnode *svp; 1321168962Spjd 1322168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1323168962Spjd VN_RELE(*vpp); 1324168962Spjd if (svp == NULL) { 1325168962Spjd error = ENOSYS; 1326168962Spjd } 1327168962Spjd *vpp = svp; 1328168962Spjd } 1329168404Spjd } 1330168404Spjd 1331168404Spjd ZFS_EXIT(zfsvfs); 1332168404Spjd return (error); 1333168404Spjd} 1334168404Spjd 1335168404Spjd/* 1336168404Spjd * Remove an entry from a directory. 1337168404Spjd * 1338168404Spjd * IN: dvp - vnode of directory to remove entry from. 1339168404Spjd * name - name of entry to remove. 1340168404Spjd * cr - credentials of caller. 1341168404Spjd * 1342168404Spjd * RETURN: 0 if success 1343168404Spjd * error code if failure 1344168404Spjd * 1345168404Spjd * Timestamps: 1346168404Spjd * dvp - ctime|mtime 1347168404Spjd * vp - ctime (if nlink > 0) 1348168404Spjd */ 1349168404Spjdstatic int 1350168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr) 1351168404Spjd{ 1352168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1353168404Spjd znode_t *xzp = NULL; 1354168404Spjd vnode_t *vp; 1355168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1356168404Spjd zilog_t *zilog = zfsvfs->z_log; 1357168962Spjd uint64_t acl_obj, xattr_obj; 1358168404Spjd zfs_dirlock_t *dl; 1359168404Spjd dmu_tx_t *tx; 1360168962Spjd boolean_t may_delete_now, delete_now = FALSE; 1361168404Spjd boolean_t unlinked; 1362168404Spjd int error; 1363168404Spjd 1364168404Spjd ZFS_ENTER(zfsvfs); 1365168404Spjd 1366168404Spjdtop: 1367168404Spjd /* 1368168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1369168404Spjd */ 1370168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1371168404Spjd ZFS_EXIT(zfsvfs); 1372168404Spjd return (error); 1373168404Spjd } 1374168404Spjd 1375168404Spjd vp = ZTOV(zp); 1376168404Spjd 1377168962Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1378168404Spjd goto out; 1379168962Spjd } 1380168404Spjd 1381168962Spjd /* 1382168962Spjd * Need to use rmdir for removing directories. 1383168962Spjd */ 1384168962Spjd if (vp->v_type == VDIR) { 1385168962Spjd error = EPERM; 1386168962Spjd goto out; 1387168962Spjd } 1388168962Spjd 1389168962Spjd vnevent_remove(vp); 1390168962Spjd 1391168404Spjd dnlc_remove(dvp, name); 1392168404Spjd 1393168962Spjd may_delete_now = FALSE; 1394168962Spjd 1395168404Spjd /* 1396168404Spjd * We may delete the znode now, or we may put it in the unlinked set; 1397168404Spjd * it depends on whether we're the last link, and on whether there are 1398168404Spjd * other holds on the vnode. So we dmu_tx_hold() the right things to 1399168404Spjd * allow for either case. 1400168404Spjd */ 1401168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1402168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1403168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1404168962Spjd if (may_delete_now) 1405168962Spjd dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END); 1406168404Spjd 1407168404Spjd /* are there any extended attributes? */ 1408168404Spjd if ((xattr_obj = zp->z_phys->zp_xattr) != 0) { 1409168404Spjd /* XXX - do we need this if we are deleting? */ 1410168404Spjd dmu_tx_hold_bonus(tx, xattr_obj); 1411168404Spjd } 1412168404Spjd 1413168962Spjd /* are there any additional acls */ 1414168962Spjd if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 && 1415168962Spjd may_delete_now) 1416168962Spjd dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); 1417168962Spjd 1418168404Spjd /* charge as an update -- would be nice not to charge at all */ 1419168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1420168404Spjd 1421168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1422168404Spjd if (error) { 1423168404Spjd zfs_dirent_unlock(dl); 1424168962Spjd VN_RELE(vp); 1425168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1426168404Spjd dmu_tx_wait(tx); 1427168404Spjd dmu_tx_abort(tx); 1428168404Spjd goto top; 1429168404Spjd } 1430168404Spjd dmu_tx_abort(tx); 1431168404Spjd ZFS_EXIT(zfsvfs); 1432168404Spjd return (error); 1433168404Spjd } 1434168404Spjd 1435168404Spjd /* 1436168404Spjd * Remove the directory entry. 1437168404Spjd */ 1438168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, &unlinked); 1439168404Spjd 1440168404Spjd if (error) { 1441168404Spjd dmu_tx_commit(tx); 1442168404Spjd goto out; 1443168404Spjd } 1444168404Spjd 1445168962Spjd if (0 && unlinked) { 1446168962Spjd VI_LOCK(vp); 1447168962Spjd delete_now = may_delete_now && 1448168962Spjd vp->v_count == 1 && !vn_has_cached_data(vp) && 1449168962Spjd zp->z_phys->zp_xattr == xattr_obj && 1450168962Spjd zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj; 1451168962Spjd VI_UNLOCK(vp); 1452168962Spjd } 1453168962Spjd 1454168962Spjd if (delete_now) { 1455168962Spjd if (zp->z_phys->zp_xattr) { 1456168962Spjd error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp); 1457168962Spjd ASSERT3U(error, ==, 0); 1458168962Spjd ASSERT3U(xzp->z_phys->zp_links, ==, 2); 1459168962Spjd dmu_buf_will_dirty(xzp->z_dbuf, tx); 1460168962Spjd mutex_enter(&xzp->z_lock); 1461168962Spjd xzp->z_unlinked = 1; 1462168962Spjd xzp->z_phys->zp_links = 0; 1463168962Spjd mutex_exit(&xzp->z_lock); 1464168962Spjd zfs_unlinked_add(xzp, tx); 1465168962Spjd zp->z_phys->zp_xattr = 0; /* probably unnecessary */ 1466168962Spjd } 1467168962Spjd mutex_enter(&zp->z_lock); 1468168962Spjd VI_LOCK(vp); 1469168962Spjd vp->v_count--; 1470168962Spjd ASSERT3U(vp->v_count, ==, 0); 1471168962Spjd VI_UNLOCK(vp); 1472168962Spjd mutex_exit(&zp->z_lock); 1473168962Spjd zfs_znode_delete(zp, tx); 1474168962Spjd VFS_RELE(zfsvfs->z_vfs); 1475168962Spjd } else if (unlinked) { 1476168404Spjd zfs_unlinked_add(zp, tx); 1477168962Spjd } 1478168404Spjd 1479168404Spjd zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name); 1480168404Spjd 1481168404Spjd dmu_tx_commit(tx); 1482168404Spjdout: 1483168404Spjd zfs_dirent_unlock(dl); 1484168404Spjd 1485168962Spjd if (!delete_now) { 1486168962Spjd VN_RELE(vp); 1487168962Spjd } else if (xzp) { 1488168962Spjd /* this rele delayed to prevent nesting transactions */ 1489168962Spjd VN_RELE(ZTOV(xzp)); 1490168962Spjd } 1491168962Spjd 1492168404Spjd ZFS_EXIT(zfsvfs); 1493168404Spjd return (error); 1494168404Spjd} 1495168404Spjd 1496168404Spjd/* 1497168404Spjd * Create a new directory and insert it into dvp using the name 1498168404Spjd * provided. Return a pointer to the inserted directory. 1499168404Spjd * 1500168404Spjd * IN: dvp - vnode of directory to add subdir to. 1501168404Spjd * dirname - name of new directory. 1502168404Spjd * vap - attributes of new directory. 1503168404Spjd * cr - credentials of caller. 1504168404Spjd * 1505168404Spjd * OUT: vpp - vnode of created directory. 1506168404Spjd * 1507168404Spjd * RETURN: 0 if success 1508168404Spjd * error code if failure 1509168404Spjd * 1510168404Spjd * Timestamps: 1511168404Spjd * dvp - ctime|mtime updated 1512168404Spjd * vp - ctime|mtime|atime updated 1513168404Spjd */ 1514168404Spjdstatic int 1515168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr) 1516168404Spjd{ 1517168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1518168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1519168404Spjd zilog_t *zilog = zfsvfs->z_log; 1520168404Spjd zfs_dirlock_t *dl; 1521168404Spjd uint64_t zoid = 0; 1522168404Spjd dmu_tx_t *tx; 1523168404Spjd int error; 1524168404Spjd 1525168404Spjd ASSERT(vap->va_type == VDIR); 1526168404Spjd 1527168404Spjd ZFS_ENTER(zfsvfs); 1528168404Spjd 1529168404Spjd if (dzp->z_phys->zp_flags & ZFS_XATTR) { 1530168404Spjd ZFS_EXIT(zfsvfs); 1531168404Spjd return (EINVAL); 1532168404Spjd } 1533168404Spjdtop: 1534168404Spjd *vpp = NULL; 1535168404Spjd 1536168404Spjd /* 1537168404Spjd * First make sure the new directory doesn't exist. 1538168404Spjd */ 1539168404Spjd if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) { 1540168404Spjd ZFS_EXIT(zfsvfs); 1541168404Spjd return (error); 1542168404Spjd } 1543168404Spjd 1544168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) { 1545168404Spjd zfs_dirent_unlock(dl); 1546168404Spjd ZFS_EXIT(zfsvfs); 1547168404Spjd return (error); 1548168404Spjd } 1549168404Spjd 1550168404Spjd /* 1551168404Spjd * Add a new entry to the directory. 1552168404Spjd */ 1553168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1554168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname); 1555168404Spjd dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 1556168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1557168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1558168404Spjd 0, SPA_MAXBLOCKSIZE); 1559168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1560168404Spjd if (error) { 1561168404Spjd zfs_dirent_unlock(dl); 1562168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1563168404Spjd dmu_tx_wait(tx); 1564168404Spjd dmu_tx_abort(tx); 1565168404Spjd goto top; 1566168404Spjd } 1567168404Spjd dmu_tx_abort(tx); 1568168404Spjd ZFS_EXIT(zfsvfs); 1569168404Spjd return (error); 1570168404Spjd } 1571168404Spjd 1572168404Spjd /* 1573168404Spjd * Create new node. 1574168404Spjd */ 1575168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1576168404Spjd 1577168404Spjd /* 1578168404Spjd * Now put new name in parent dir. 1579168404Spjd */ 1580168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1581168404Spjd 1582168404Spjd *vpp = ZTOV(zp); 1583168404Spjd 1584168404Spjd zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname); 1585168404Spjd dmu_tx_commit(tx); 1586168404Spjd 1587175202Sattilio vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 1588168404Spjd 1589168404Spjd zfs_dirent_unlock(dl); 1590168404Spjd 1591168404Spjd ZFS_EXIT(zfsvfs); 1592168404Spjd return (0); 1593168404Spjd} 1594168404Spjd 1595168404Spjd/* 1596168404Spjd * Remove a directory subdir entry. If the current working 1597168404Spjd * directory is the same as the subdir to be removed, the 1598168404Spjd * remove will fail. 1599168404Spjd * 1600168404Spjd * IN: dvp - vnode of directory to remove from. 1601168404Spjd * name - name of directory to be removed. 1602168404Spjd * cwd - vnode of current working directory. 1603168404Spjd * cr - credentials of caller. 1604168404Spjd * 1605168404Spjd * RETURN: 0 if success 1606168404Spjd * error code if failure 1607168404Spjd * 1608168404Spjd * Timestamps: 1609168404Spjd * dvp - ctime|mtime updated 1610168404Spjd */ 1611168404Spjdstatic int 1612168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr) 1613168404Spjd{ 1614168404Spjd znode_t *dzp = VTOZ(dvp); 1615168404Spjd znode_t *zp; 1616168404Spjd vnode_t *vp; 1617168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1618168404Spjd zilog_t *zilog = zfsvfs->z_log; 1619168404Spjd zfs_dirlock_t *dl; 1620168404Spjd dmu_tx_t *tx; 1621168404Spjd int error; 1622168404Spjd 1623168962Spjd ZFS_ENTER(zfsvfs); 1624168404Spjd 1625168404Spjdtop: 1626168404Spjd zp = NULL; 1627168404Spjd 1628168404Spjd /* 1629168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1630168404Spjd */ 1631168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1632168404Spjd ZFS_EXIT(zfsvfs); 1633168404Spjd return (error); 1634168404Spjd } 1635168404Spjd 1636168404Spjd vp = ZTOV(zp); 1637168404Spjd 1638168404Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1639168404Spjd goto out; 1640168404Spjd } 1641168404Spjd 1642168962Spjd if (vp->v_type != VDIR) { 1643168962Spjd error = ENOTDIR; 1644168962Spjd goto out; 1645168962Spjd } 1646168962Spjd 1647168962Spjd if (vp == cwd) { 1648168962Spjd error = EINVAL; 1649168962Spjd goto out; 1650168962Spjd } 1651168962Spjd 1652168962Spjd vnevent_rmdir(vp); 1653168962Spjd 1654168404Spjd /* 1655168404Spjd * Grab a lock on the directory to make sure that noone is 1656168404Spjd * trying to add (or lookup) entries while we are removing it. 1657168404Spjd */ 1658168404Spjd rw_enter(&zp->z_name_lock, RW_WRITER); 1659168404Spjd 1660168404Spjd /* 1661168404Spjd * Grab a lock on the parent pointer to make sure we play well 1662168404Spjd * with the treewalk and directory rename code. 1663168404Spjd */ 1664168404Spjd rw_enter(&zp->z_parent_lock, RW_WRITER); 1665168404Spjd 1666168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1667168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1668168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1669168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1670168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1671168404Spjd if (error) { 1672168404Spjd rw_exit(&zp->z_parent_lock); 1673168404Spjd rw_exit(&zp->z_name_lock); 1674168404Spjd zfs_dirent_unlock(dl); 1675168962Spjd VN_RELE(vp); 1676168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1677168404Spjd dmu_tx_wait(tx); 1678168404Spjd dmu_tx_abort(tx); 1679168404Spjd goto top; 1680168404Spjd } 1681168404Spjd dmu_tx_abort(tx); 1682168404Spjd ZFS_EXIT(zfsvfs); 1683168404Spjd return (error); 1684168404Spjd } 1685168404Spjd 1686168404Spjd#ifdef FREEBSD_NAMECACHE 1687168404Spjd cache_purge(dvp); 1688168404Spjd#endif 1689168404Spjd 1690168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, NULL); 1691168404Spjd 1692168404Spjd if (error == 0) 1693168404Spjd zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name); 1694168404Spjd 1695168404Spjd dmu_tx_commit(tx); 1696168404Spjd 1697168404Spjd rw_exit(&zp->z_parent_lock); 1698168404Spjd rw_exit(&zp->z_name_lock); 1699168404Spjd#ifdef FREEBSD_NAMECACHE 1700168404Spjd cache_purge(vp); 1701168404Spjd#endif 1702168404Spjdout: 1703168404Spjd zfs_dirent_unlock(dl); 1704168404Spjd 1705168962Spjd VN_RELE(vp); 1706168962Spjd 1707168404Spjd ZFS_EXIT(zfsvfs); 1708168404Spjd return (error); 1709168404Spjd} 1710168404Spjd 1711168404Spjd/* 1712168404Spjd * Read as many directory entries as will fit into the provided 1713168404Spjd * buffer from the given directory cursor position (specified in 1714168404Spjd * the uio structure. 1715168404Spjd * 1716168404Spjd * IN: vp - vnode of directory to read. 1717168404Spjd * uio - structure supplying read location, range info, 1718168404Spjd * and return buffer. 1719168404Spjd * cr - credentials of caller. 1720168404Spjd * 1721168404Spjd * OUT: uio - updated offset and range, buffer filled. 1722168404Spjd * eofp - set to true if end-of-file detected. 1723168404Spjd * 1724168404Spjd * RETURN: 0 if success 1725168404Spjd * error code if failure 1726168404Spjd * 1727168404Spjd * Timestamps: 1728168404Spjd * vp - atime updated 1729168404Spjd * 1730168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero. 1731168404Spjd * This allows us to use the low range for "special" directory entries: 1732168404Spjd * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, 1733168404Spjd * we use the offset 2 for the '.zfs' directory. 1734168404Spjd */ 1735168404Spjd/* ARGSUSED */ 1736168404Spjdstatic int 1737168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies) 1738168404Spjd{ 1739168404Spjd znode_t *zp = VTOZ(vp); 1740168404Spjd iovec_t *iovp; 1741168404Spjd dirent64_t *odp; 1742168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1743168404Spjd objset_t *os; 1744168404Spjd caddr_t outbuf; 1745168404Spjd size_t bufsize; 1746168404Spjd zap_cursor_t zc; 1747168404Spjd zap_attribute_t zap; 1748168404Spjd uint_t bytes_wanted; 1749168404Spjd uint64_t offset; /* must be unsigned; checks for < 1 */ 1750168404Spjd int local_eof; 1751168404Spjd int outcount; 1752168404Spjd int error; 1753168404Spjd uint8_t prefetch; 1754168404Spjd uint8_t type; 1755168962Spjd int ncooks; 1756168962Spjd u_long *cooks = NULL; 1757168404Spjd 1758168404Spjd ZFS_ENTER(zfsvfs); 1759168404Spjd 1760168404Spjd /* 1761168404Spjd * If we are not given an eof variable, 1762168404Spjd * use a local one. 1763168404Spjd */ 1764168404Spjd if (eofp == NULL) 1765168404Spjd eofp = &local_eof; 1766168404Spjd 1767168404Spjd /* 1768168404Spjd * Check for valid iov_len. 1769168404Spjd */ 1770168404Spjd if (uio->uio_iov->iov_len <= 0) { 1771168404Spjd ZFS_EXIT(zfsvfs); 1772168404Spjd return (EINVAL); 1773168404Spjd } 1774168404Spjd 1775168404Spjd /* 1776168404Spjd * Quit if directory has been removed (posix) 1777168404Spjd */ 1778168404Spjd if ((*eofp = zp->z_unlinked) != 0) { 1779168404Spjd ZFS_EXIT(zfsvfs); 1780168404Spjd return (0); 1781168404Spjd } 1782168404Spjd 1783168404Spjd error = 0; 1784168404Spjd os = zfsvfs->z_os; 1785168404Spjd offset = uio->uio_loffset; 1786168404Spjd prefetch = zp->z_zn_prefetch; 1787168404Spjd 1788168404Spjd /* 1789168404Spjd * Initialize the iterator cursor. 1790168404Spjd */ 1791168404Spjd if (offset <= 3) { 1792168404Spjd /* 1793168404Spjd * Start iteration from the beginning of the directory. 1794168404Spjd */ 1795168404Spjd zap_cursor_init(&zc, os, zp->z_id); 1796168404Spjd } else { 1797168404Spjd /* 1798168404Spjd * The offset is a serialized cursor. 1799168404Spjd */ 1800168404Spjd zap_cursor_init_serialized(&zc, os, zp->z_id, offset); 1801168404Spjd } 1802168404Spjd 1803168404Spjd /* 1804168404Spjd * Get space to change directory entries into fs independent format. 1805168404Spjd */ 1806168404Spjd iovp = uio->uio_iov; 1807168404Spjd bytes_wanted = iovp->iov_len; 1808168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { 1809168404Spjd bufsize = bytes_wanted; 1810168404Spjd outbuf = kmem_alloc(bufsize, KM_SLEEP); 1811168404Spjd odp = (struct dirent64 *)outbuf; 1812168404Spjd } else { 1813168404Spjd bufsize = bytes_wanted; 1814168404Spjd odp = (struct dirent64 *)iovp->iov_base; 1815168404Spjd } 1816168404Spjd 1817169170Spjd if (ncookies != NULL) { 1818168404Spjd /* 1819168404Spjd * Minimum entry size is dirent size and 1 byte for a file name. 1820168404Spjd */ 1821168962Spjd ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1); 1822168962Spjd cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK); 1823169170Spjd *cookies = cooks; 1824168962Spjd *ncookies = ncooks; 1825168404Spjd } 1826168404Spjd 1827168404Spjd /* 1828168404Spjd * Transform to file-system independent format 1829168404Spjd */ 1830168404Spjd outcount = 0; 1831168404Spjd while (outcount < bytes_wanted) { 1832168404Spjd ino64_t objnum; 1833168404Spjd ushort_t reclen; 1834168404Spjd 1835168404Spjd /* 1836168404Spjd * Special case `.', `..', and `.zfs'. 1837168404Spjd */ 1838168404Spjd if (offset == 0) { 1839168404Spjd (void) strcpy(zap.za_name, "."); 1840168404Spjd objnum = zp->z_id; 1841169108Spjd type = DT_DIR; 1842168404Spjd } else if (offset == 1) { 1843168404Spjd (void) strcpy(zap.za_name, ".."); 1844168404Spjd objnum = zp->z_phys->zp_parent; 1845169108Spjd type = DT_DIR; 1846168404Spjd } else if (offset == 2 && zfs_show_ctldir(zp)) { 1847168404Spjd (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME); 1848168404Spjd objnum = ZFSCTL_INO_ROOT; 1849169108Spjd type = DT_DIR; 1850168404Spjd } else { 1851168404Spjd /* 1852168404Spjd * Grab next entry. 1853168404Spjd */ 1854168404Spjd if (error = zap_cursor_retrieve(&zc, &zap)) { 1855168404Spjd if ((*eofp = (error == ENOENT)) != 0) 1856168404Spjd break; 1857168404Spjd else 1858168404Spjd goto update; 1859168404Spjd } 1860168404Spjd 1861168404Spjd if (zap.za_integer_length != 8 || 1862168404Spjd zap.za_num_integers != 1) { 1863168404Spjd cmn_err(CE_WARN, "zap_readdir: bad directory " 1864168404Spjd "entry, obj = %lld, offset = %lld\n", 1865168404Spjd (u_longlong_t)zp->z_id, 1866168404Spjd (u_longlong_t)offset); 1867168404Spjd error = ENXIO; 1868168404Spjd goto update; 1869168404Spjd } 1870168404Spjd 1871168404Spjd objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); 1872168404Spjd /* 1873168404Spjd * MacOS X can extract the object type here such as: 1874168404Spjd * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1875168404Spjd */ 1876168404Spjd type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1877168404Spjd } 1878168404Spjd reclen = DIRENT64_RECLEN(strlen(zap.za_name)); 1879168404Spjd 1880168404Spjd /* 1881168404Spjd * Will this entry fit in the buffer? 1882168404Spjd */ 1883168404Spjd if (outcount + reclen > bufsize) { 1884168404Spjd /* 1885168404Spjd * Did we manage to fit anything in the buffer? 1886168404Spjd */ 1887168404Spjd if (!outcount) { 1888168404Spjd error = EINVAL; 1889168404Spjd goto update; 1890168404Spjd } 1891168404Spjd break; 1892168404Spjd } 1893168404Spjd /* 1894168404Spjd * Add this entry: 1895168404Spjd */ 1896168404Spjd odp->d_ino = objnum; 1897168404Spjd odp->d_reclen = reclen; 1898168404Spjd odp->d_namlen = strlen(zap.za_name); 1899168404Spjd (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); 1900168404Spjd odp->d_type = type; 1901168404Spjd outcount += reclen; 1902168404Spjd odp = (dirent64_t *)((intptr_t)odp + reclen); 1903168404Spjd 1904168404Spjd ASSERT(outcount <= bufsize); 1905168404Spjd 1906168404Spjd /* Prefetch znode */ 1907168404Spjd if (prefetch) 1908168404Spjd dmu_prefetch(os, objnum, 0, 0); 1909168404Spjd 1910168404Spjd /* 1911168404Spjd * Move to the next entry, fill in the previous offset. 1912168404Spjd */ 1913168404Spjd if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) { 1914168404Spjd zap_cursor_advance(&zc); 1915168404Spjd offset = zap_cursor_serialize(&zc); 1916168404Spjd } else { 1917168404Spjd offset += 1; 1918168404Spjd } 1919168404Spjd 1920168962Spjd if (cooks != NULL) { 1921168962Spjd *cooks++ = offset; 1922168962Spjd ncooks--; 1923168962Spjd KASSERT(ncooks >= 0, ("ncookies=%d", ncooks)); 1924168404Spjd } 1925168404Spjd } 1926168404Spjd zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ 1927168404Spjd 1928168404Spjd /* Subtract unused cookies */ 1929168962Spjd if (ncookies != NULL) 1930168962Spjd *ncookies -= ncooks; 1931168404Spjd 1932168404Spjd if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { 1933168404Spjd iovp->iov_base += outcount; 1934168404Spjd iovp->iov_len -= outcount; 1935168404Spjd uio->uio_resid -= outcount; 1936168404Spjd } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) { 1937168404Spjd /* 1938168404Spjd * Reset the pointer. 1939168404Spjd */ 1940168404Spjd offset = uio->uio_loffset; 1941168404Spjd } 1942168404Spjd 1943168404Spjdupdate: 1944168404Spjd zap_cursor_fini(&zc); 1945168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1946168404Spjd kmem_free(outbuf, bufsize); 1947168404Spjd 1948168404Spjd if (error == ENOENT) 1949168404Spjd error = 0; 1950168404Spjd 1951168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 1952168404Spjd 1953168404Spjd uio->uio_loffset = offset; 1954168404Spjd ZFS_EXIT(zfsvfs); 1955169107Spjd if (error != 0 && cookies != NULL) { 1956168962Spjd free(*cookies, M_TEMP); 1957168962Spjd *cookies = NULL; 1958168962Spjd *ncookies = 0; 1959168404Spjd } 1960168404Spjd return (error); 1961168404Spjd} 1962168404Spjd 1963168404Spjdstatic int 1964168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr) 1965168404Spjd{ 1966168962Spjd znode_t *zp = VTOZ(vp); 1967168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1968168404Spjd 1969168404Spjd ZFS_ENTER(zfsvfs); 1970168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 1971168404Spjd ZFS_EXIT(zfsvfs); 1972168404Spjd return (0); 1973168404Spjd} 1974168404Spjd 1975168404Spjd/* 1976168404Spjd * Get the requested file attributes and place them in the provided 1977168404Spjd * vattr structure. 1978168404Spjd * 1979168404Spjd * IN: vp - vnode of file. 1980168404Spjd * vap - va_mask identifies requested attributes. 1981168404Spjd * flags - [UNUSED] 1982168404Spjd * cr - credentials of caller. 1983168404Spjd * 1984168404Spjd * OUT: vap - attribute values. 1985168404Spjd * 1986168404Spjd * RETURN: 0 (always succeeds) 1987168404Spjd */ 1988168404Spjd/* ARGSUSED */ 1989168404Spjdstatic int 1990168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 1991168404Spjd{ 1992168962Spjd znode_t *zp = VTOZ(vp); 1993168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1994168962Spjd znode_phys_t *pzp = zp->z_phys; 1995168962Spjd uint32_t blksize; 1996168962Spjd u_longlong_t nblocks; 1997168962Spjd int error; 1998168404Spjd 1999168404Spjd ZFS_ENTER(zfsvfs); 2000168404Spjd 2001168404Spjd /* 2002168404Spjd * Return all attributes. It's cheaper to provide the answer 2003168404Spjd * than to determine whether we were asked the question. 2004168404Spjd */ 2005168404Spjd mutex_enter(&zp->z_lock); 2006168404Spjd 2007168404Spjd vap->va_type = IFTOVT(pzp->zp_mode); 2008168404Spjd vap->va_mode = pzp->zp_mode & ~S_IFMT; 2009168404Spjd vap->va_uid = zp->z_phys->zp_uid; 2010168404Spjd vap->va_gid = zp->z_phys->zp_gid; 2011168404Spjd vap->va_nodeid = zp->z_id; 2012168404Spjd vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX); /* nlink_t limit! */ 2013168404Spjd vap->va_size = pzp->zp_size; 2014168404Spjd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 2015168958Spjd vap->va_rdev = zfs_cmpldev(pzp->zp_rdev); 2016168404Spjd vap->va_seq = zp->z_seq; 2017168404Spjd vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */ 2018168404Spjd 2019168404Spjd ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime); 2020168404Spjd ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime); 2021168404Spjd ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime); 2022168404Spjd ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime); 2023168404Spjd 2024168404Spjd /* 2025168404Spjd * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES. 2026168404Spjd * Also, if we are the owner don't bother, since owner should 2027168404Spjd * always be allowed to read basic attributes of file. 2028168404Spjd */ 2029168404Spjd if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) && 2030168404Spjd (zp->z_phys->zp_uid != crgetuid(cr))) { 2031168404Spjd if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) { 2032168404Spjd mutex_exit(&zp->z_lock); 2033168404Spjd ZFS_EXIT(zfsvfs); 2034168404Spjd return (error); 2035168404Spjd } 2036168404Spjd } 2037168404Spjd 2038168404Spjd mutex_exit(&zp->z_lock); 2039168404Spjd 2040168404Spjd dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks); 2041168404Spjd vap->va_blksize = blksize; 2042168404Spjd vap->va_bytes = nblocks << 9; /* nblocks * 512 */ 2043168404Spjd 2044168404Spjd if (zp->z_blksz == 0) { 2045168404Spjd /* 2046168404Spjd * Block size hasn't been set; suggest maximal I/O transfers. 2047168404Spjd */ 2048168404Spjd vap->va_blksize = zfsvfs->z_max_blksz; 2049168404Spjd } 2050168404Spjd 2051168404Spjd ZFS_EXIT(zfsvfs); 2052168404Spjd return (0); 2053168404Spjd} 2054168404Spjd 2055168404Spjd/* 2056168404Spjd * Set the file attributes to the values contained in the 2057168404Spjd * vattr structure. 2058168404Spjd * 2059168404Spjd * IN: vp - vnode of file to be modified. 2060168404Spjd * vap - new attribute values. 2061168404Spjd * flags - ATTR_UTIME set if non-default time values provided. 2062168404Spjd * cr - credentials of caller. 2063168404Spjd * 2064168404Spjd * RETURN: 0 if success 2065168404Spjd * error code if failure 2066168404Spjd * 2067168404Spjd * Timestamps: 2068168404Spjd * vp - ctime updated, mtime updated if size changed. 2069168404Spjd */ 2070168404Spjd/* ARGSUSED */ 2071168404Spjdstatic int 2072168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 2073168962Spjd caller_context_t *ct) 2074168404Spjd{ 2075168962Spjd struct znode *zp = VTOZ(vp); 2076168404Spjd znode_phys_t *pzp = zp->z_phys; 2077168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2078168404Spjd zilog_t *zilog = zfsvfs->z_log; 2079168404Spjd dmu_tx_t *tx; 2080168404Spjd vattr_t oldva; 2081168962Spjd uint_t mask = vap->va_mask; 2082168404Spjd uint_t saved_mask; 2083168404Spjd int trim_mask = 0; 2084168404Spjd uint64_t new_mode; 2085168404Spjd znode_t *attrzp; 2086168404Spjd int need_policy = FALSE; 2087168404Spjd int err; 2088168404Spjd 2089168404Spjd if (mask == 0) 2090168404Spjd return (0); 2091168404Spjd 2092168962Spjd if (mask & AT_NOSET) 2093168962Spjd return (EINVAL); 2094168962Spjd 2095168404Spjd if (mask & AT_SIZE && vp->v_type == VDIR) 2096168404Spjd return (EISDIR); 2097168404Spjd 2098168404Spjd if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) 2099168404Spjd return (EINVAL); 2100168404Spjd 2101168404Spjd ZFS_ENTER(zfsvfs); 2102168404Spjd 2103168404Spjdtop: 2104168404Spjd attrzp = NULL; 2105168404Spjd 2106168404Spjd if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { 2107168404Spjd ZFS_EXIT(zfsvfs); 2108168404Spjd return (EROFS); 2109168404Spjd } 2110168404Spjd 2111168404Spjd /* 2112168404Spjd * First validate permissions 2113168404Spjd */ 2114168404Spjd 2115168404Spjd if (mask & AT_SIZE) { 2116168404Spjd err = zfs_zaccess(zp, ACE_WRITE_DATA, cr); 2117168404Spjd if (err) { 2118168404Spjd ZFS_EXIT(zfsvfs); 2119168404Spjd return (err); 2120168404Spjd } 2121168404Spjd /* 2122168404Spjd * XXX - Note, we are not providing any open 2123168404Spjd * mode flags here (like FNDELAY), so we may 2124168404Spjd * block if there are locks present... this 2125168404Spjd * should be addressed in openat(). 2126168404Spjd */ 2127168404Spjd do { 2128168404Spjd err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); 2129168404Spjd /* NB: we already did dmu_tx_wait() if necessary */ 2130168404Spjd } while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT); 2131168404Spjd if (err) { 2132168404Spjd ZFS_EXIT(zfsvfs); 2133168404Spjd return (err); 2134168404Spjd } 2135168404Spjd } 2136168404Spjd 2137168404Spjd if (mask & (AT_ATIME|AT_MTIME)) 2138168404Spjd need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr); 2139168404Spjd 2140168404Spjd if (mask & (AT_UID|AT_GID)) { 2141168404Spjd int idmask = (mask & (AT_UID|AT_GID)); 2142168404Spjd int take_owner; 2143168404Spjd int take_group; 2144168404Spjd 2145168404Spjd /* 2146168404Spjd * NOTE: even if a new mode is being set, 2147168404Spjd * we may clear S_ISUID/S_ISGID bits. 2148168404Spjd */ 2149168404Spjd 2150168404Spjd if (!(mask & AT_MODE)) 2151168404Spjd vap->va_mode = pzp->zp_mode; 2152168404Spjd 2153168404Spjd /* 2154168404Spjd * Take ownership or chgrp to group we are a member of 2155168404Spjd */ 2156168404Spjd 2157168404Spjd take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr)); 2158168404Spjd take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr); 2159168404Spjd 2160168404Spjd /* 2161168404Spjd * If both AT_UID and AT_GID are set then take_owner and 2162168404Spjd * take_group must both be set in order to allow taking 2163168404Spjd * ownership. 2164168404Spjd * 2165168404Spjd * Otherwise, send the check through secpolicy_vnode_setattr() 2166168404Spjd * 2167168404Spjd */ 2168168404Spjd 2169168404Spjd if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) || 2170168404Spjd ((idmask == AT_UID) && take_owner) || 2171168404Spjd ((idmask == AT_GID) && take_group)) { 2172168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) { 2173168404Spjd /* 2174168404Spjd * Remove setuid/setgid for non-privileged users 2175168404Spjd */ 2176168404Spjd secpolicy_setid_clear(vap, cr); 2177168404Spjd trim_mask = (mask & (AT_UID|AT_GID)); 2178168404Spjd } else { 2179168404Spjd need_policy = TRUE; 2180168404Spjd } 2181168404Spjd } else { 2182168404Spjd need_policy = TRUE; 2183168404Spjd } 2184168404Spjd } 2185168404Spjd 2186168404Spjd mutex_enter(&zp->z_lock); 2187168404Spjd oldva.va_mode = pzp->zp_mode; 2188168404Spjd oldva.va_uid = zp->z_phys->zp_uid; 2189168404Spjd oldva.va_gid = zp->z_phys->zp_gid; 2190168404Spjd mutex_exit(&zp->z_lock); 2191168404Spjd 2192168404Spjd if (mask & AT_MODE) { 2193168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) { 2194168962Spjd err = secpolicy_setid_setsticky_clear(vp, vap, 2195168962Spjd &oldva, cr); 2196168962Spjd if (err) { 2197168962Spjd ZFS_EXIT(zfsvfs); 2198168962Spjd return (err); 2199168962Spjd } 2200168404Spjd trim_mask |= AT_MODE; 2201168404Spjd } else { 2202168404Spjd need_policy = TRUE; 2203168404Spjd } 2204168404Spjd } 2205168404Spjd 2206168404Spjd if (need_policy) { 2207168404Spjd /* 2208168404Spjd * If trim_mask is set then take ownership 2209168404Spjd * has been granted or write_acl is present and user 2210168404Spjd * has the ability to modify mode. In that case remove 2211168404Spjd * UID|GID and or MODE from mask so that 2212168404Spjd * secpolicy_vnode_setattr() doesn't revoke it. 2213168404Spjd */ 2214168404Spjd 2215168404Spjd if (trim_mask) { 2216168404Spjd saved_mask = vap->va_mask; 2217168404Spjd vap->va_mask &= ~trim_mask; 2218168404Spjd 2219168404Spjd } 2220168404Spjd err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 2221168404Spjd (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp); 2222168404Spjd if (err) { 2223168404Spjd ZFS_EXIT(zfsvfs); 2224168404Spjd return (err); 2225168404Spjd } 2226168404Spjd 2227168404Spjd if (trim_mask) 2228168404Spjd vap->va_mask |= saved_mask; 2229168404Spjd } 2230168404Spjd 2231168404Spjd /* 2232168404Spjd * secpolicy_vnode_setattr, or take ownership may have 2233168404Spjd * changed va_mask 2234168404Spjd */ 2235168404Spjd mask = vap->va_mask; 2236168404Spjd 2237168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2238168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2239168404Spjd 2240168404Spjd if (mask & AT_MODE) { 2241168404Spjd uint64_t pmode = pzp->zp_mode; 2242168404Spjd 2243168404Spjd new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); 2244168404Spjd 2245168404Spjd if (zp->z_phys->zp_acl.z_acl_extern_obj) 2246168404Spjd dmu_tx_hold_write(tx, 2247168404Spjd pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE); 2248168404Spjd else 2249168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2250168404Spjd 0, ZFS_ACL_SIZE(MAX_ACL_SIZE)); 2251168404Spjd } 2252168404Spjd 2253168404Spjd if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) { 2254168404Spjd err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp); 2255168404Spjd if (err) { 2256168404Spjd dmu_tx_abort(tx); 2257168404Spjd ZFS_EXIT(zfsvfs); 2258168404Spjd return (err); 2259168404Spjd } 2260168404Spjd dmu_tx_hold_bonus(tx, attrzp->z_id); 2261168404Spjd } 2262168404Spjd 2263168404Spjd err = dmu_tx_assign(tx, zfsvfs->z_assign); 2264168404Spjd if (err) { 2265168404Spjd if (attrzp) 2266168404Spjd VN_RELE(ZTOV(attrzp)); 2267168404Spjd if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2268168404Spjd dmu_tx_wait(tx); 2269168404Spjd dmu_tx_abort(tx); 2270168404Spjd goto top; 2271168404Spjd } 2272168404Spjd dmu_tx_abort(tx); 2273168404Spjd ZFS_EXIT(zfsvfs); 2274168404Spjd return (err); 2275168404Spjd } 2276168404Spjd 2277168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2278168404Spjd 2279168404Spjd /* 2280168404Spjd * Set each attribute requested. 2281168404Spjd * We group settings according to the locks they need to acquire. 2282168404Spjd * 2283168404Spjd * Note: you cannot set ctime directly, although it will be 2284168404Spjd * updated as a side-effect of calling this function. 2285168404Spjd */ 2286168404Spjd 2287168404Spjd mutex_enter(&zp->z_lock); 2288168404Spjd 2289168404Spjd if (mask & AT_MODE) { 2290168404Spjd err = zfs_acl_chmod_setattr(zp, new_mode, tx); 2291168404Spjd ASSERT3U(err, ==, 0); 2292168404Spjd } 2293168404Spjd 2294168404Spjd if (attrzp) 2295168404Spjd mutex_enter(&attrzp->z_lock); 2296168404Spjd 2297168404Spjd if (mask & AT_UID) { 2298168404Spjd zp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2299168404Spjd if (attrzp) { 2300168404Spjd attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2301168404Spjd } 2302168404Spjd } 2303168404Spjd 2304168404Spjd if (mask & AT_GID) { 2305168404Spjd zp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2306168404Spjd if (attrzp) 2307168404Spjd attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2308168404Spjd } 2309168404Spjd 2310168404Spjd if (attrzp) 2311168404Spjd mutex_exit(&attrzp->z_lock); 2312168404Spjd 2313168404Spjd if (mask & AT_ATIME) 2314168404Spjd ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); 2315168404Spjd 2316168404Spjd if (mask & AT_MTIME) 2317168404Spjd ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime); 2318168404Spjd 2319168404Spjd if (mask & AT_SIZE) 2320168404Spjd zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx); 2321168404Spjd else if (mask != 0) 2322168404Spjd zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 2323168404Spjd 2324168404Spjd if (mask != 0) 2325168404Spjd zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask); 2326168404Spjd 2327168404Spjd mutex_exit(&zp->z_lock); 2328168404Spjd 2329168404Spjd if (attrzp) 2330168404Spjd VN_RELE(ZTOV(attrzp)); 2331168404Spjd 2332168404Spjd dmu_tx_commit(tx); 2333168404Spjd 2334168404Spjd ZFS_EXIT(zfsvfs); 2335168404Spjd return (err); 2336168404Spjd} 2337168404Spjd 2338168404Spjdtypedef struct zfs_zlock { 2339168404Spjd krwlock_t *zl_rwlock; /* lock we acquired */ 2340168404Spjd znode_t *zl_znode; /* znode we held */ 2341168404Spjd struct zfs_zlock *zl_next; /* next in list */ 2342168404Spjd} zfs_zlock_t; 2343168404Spjd 2344168404Spjd/* 2345168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock(). 2346168404Spjd */ 2347168404Spjdstatic void 2348168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp) 2349168404Spjd{ 2350168404Spjd zfs_zlock_t *zl; 2351168404Spjd 2352168404Spjd while ((zl = *zlpp) != NULL) { 2353168404Spjd if (zl->zl_znode != NULL) 2354168404Spjd VN_RELE(ZTOV(zl->zl_znode)); 2355168404Spjd rw_exit(zl->zl_rwlock); 2356168404Spjd *zlpp = zl->zl_next; 2357168404Spjd kmem_free(zl, sizeof (*zl)); 2358168404Spjd } 2359168404Spjd} 2360168404Spjd 2361168404Spjd/* 2362168404Spjd * Search back through the directory tree, using the ".." entries. 2363168404Spjd * Lock each directory in the chain to prevent concurrent renames. 2364168404Spjd * Fail any attempt to move a directory into one of its own descendants. 2365168404Spjd * XXX - z_parent_lock can overlap with map or grow locks 2366168404Spjd */ 2367168404Spjdstatic int 2368168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) 2369168404Spjd{ 2370168404Spjd zfs_zlock_t *zl; 2371168404Spjd znode_t *zp = tdzp; 2372168404Spjd uint64_t rootid = zp->z_zfsvfs->z_root; 2373168404Spjd uint64_t *oidp = &zp->z_id; 2374168404Spjd krwlock_t *rwlp = &szp->z_parent_lock; 2375168404Spjd krw_t rw = RW_WRITER; 2376168404Spjd 2377168404Spjd /* 2378168404Spjd * First pass write-locks szp and compares to zp->z_id. 2379168404Spjd * Later passes read-lock zp and compare to zp->z_parent. 2380168404Spjd */ 2381168404Spjd do { 2382168404Spjd if (!rw_tryenter(rwlp, rw)) { 2383168404Spjd /* 2384168404Spjd * Another thread is renaming in this path. 2385168404Spjd * Note that if we are a WRITER, we don't have any 2386168404Spjd * parent_locks held yet. 2387168404Spjd */ 2388168404Spjd if (rw == RW_READER && zp->z_id > szp->z_id) { 2389168404Spjd /* 2390168404Spjd * Drop our locks and restart 2391168404Spjd */ 2392168404Spjd zfs_rename_unlock(&zl); 2393168404Spjd *zlpp = NULL; 2394168404Spjd zp = tdzp; 2395168404Spjd oidp = &zp->z_id; 2396168404Spjd rwlp = &szp->z_parent_lock; 2397168404Spjd rw = RW_WRITER; 2398168404Spjd continue; 2399168404Spjd } else { 2400168404Spjd /* 2401168404Spjd * Wait for other thread to drop its locks 2402168404Spjd */ 2403168404Spjd rw_enter(rwlp, rw); 2404168404Spjd } 2405168404Spjd } 2406168404Spjd 2407168404Spjd zl = kmem_alloc(sizeof (*zl), KM_SLEEP); 2408168404Spjd zl->zl_rwlock = rwlp; 2409168404Spjd zl->zl_znode = NULL; 2410168404Spjd zl->zl_next = *zlpp; 2411168404Spjd *zlpp = zl; 2412168404Spjd 2413168404Spjd if (*oidp == szp->z_id) /* We're a descendant of szp */ 2414168404Spjd return (EINVAL); 2415168404Spjd 2416168404Spjd if (*oidp == rootid) /* We've hit the top */ 2417168404Spjd return (0); 2418168404Spjd 2419168404Spjd if (rw == RW_READER) { /* i.e. not the first pass */ 2420168404Spjd int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp); 2421168404Spjd if (error) 2422168404Spjd return (error); 2423168404Spjd zl->zl_znode = zp; 2424168404Spjd } 2425168404Spjd oidp = &zp->z_phys->zp_parent; 2426168404Spjd rwlp = &zp->z_parent_lock; 2427168404Spjd rw = RW_READER; 2428168404Spjd 2429168404Spjd } while (zp->z_id != sdzp->z_id); 2430168404Spjd 2431168404Spjd return (0); 2432168404Spjd} 2433168404Spjd 2434168404Spjd/* 2435168404Spjd * Move an entry from the provided source directory to the target 2436168404Spjd * directory. Change the entry name as indicated. 2437168404Spjd * 2438168404Spjd * IN: sdvp - Source directory containing the "old entry". 2439168404Spjd * snm - Old entry name. 2440168404Spjd * tdvp - Target directory to contain the "new entry". 2441168404Spjd * tnm - New entry name. 2442168404Spjd * cr - credentials of caller. 2443168404Spjd * 2444168404Spjd * RETURN: 0 if success 2445168404Spjd * error code if failure 2446168404Spjd * 2447168404Spjd * Timestamps: 2448168404Spjd * sdvp,tdvp - ctime|mtime updated 2449168404Spjd */ 2450168404Spjdstatic int 2451168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr) 2452168404Spjd{ 2453168404Spjd znode_t *tdzp, *szp, *tzp; 2454168404Spjd znode_t *sdzp = VTOZ(sdvp); 2455168404Spjd zfsvfs_t *zfsvfs = sdzp->z_zfsvfs; 2456168404Spjd zilog_t *zilog = zfsvfs->z_log; 2457168962Spjd vnode_t *realvp; 2458168404Spjd zfs_dirlock_t *sdl, *tdl; 2459168404Spjd dmu_tx_t *tx; 2460168404Spjd zfs_zlock_t *zl; 2461168962Spjd int cmp, serr, terr, error; 2462168404Spjd 2463168404Spjd ZFS_ENTER(zfsvfs); 2464168404Spjd 2465168962Spjd /* 2466168962Spjd * Make sure we have the real vp for the target directory. 2467168962Spjd */ 2468168962Spjd if (VOP_REALVP(tdvp, &realvp) == 0) 2469168962Spjd tdvp = realvp; 2470168962Spjd 2471168404Spjd if (tdvp->v_vfsp != sdvp->v_vfsp) { 2472168404Spjd ZFS_EXIT(zfsvfs); 2473168962Spjd return (EXDEV); 2474168404Spjd } 2475168404Spjd 2476168404Spjd tdzp = VTOZ(tdvp); 2477168404Spjdtop: 2478168404Spjd szp = NULL; 2479168404Spjd tzp = NULL; 2480168404Spjd zl = NULL; 2481168404Spjd 2482168404Spjd /* 2483168404Spjd * This is to prevent the creation of links into attribute space 2484168404Spjd * by renaming a linked file into/outof an attribute directory. 2485168404Spjd * See the comment in zfs_link() for why this is considered bad. 2486168404Spjd */ 2487168404Spjd if ((tdzp->z_phys->zp_flags & ZFS_XATTR) != 2488168404Spjd (sdzp->z_phys->zp_flags & ZFS_XATTR)) { 2489168962Spjd ZFS_EXIT(zfsvfs); 2490168962Spjd return (EINVAL); 2491168404Spjd } 2492168404Spjd 2493168404Spjd /* 2494168404Spjd * Lock source and target directory entries. To prevent deadlock, 2495168404Spjd * a lock ordering must be defined. We lock the directory with 2496168404Spjd * the smallest object id first, or if it's a tie, the one with 2497168404Spjd * the lexically first name. 2498168404Spjd */ 2499168404Spjd if (sdzp->z_id < tdzp->z_id) { 2500168962Spjd cmp = -1; 2501168962Spjd } else if (sdzp->z_id > tdzp->z_id) { 2502168962Spjd cmp = 1; 2503168962Spjd } else { 2504168962Spjd cmp = strcmp(snm, tnm); 2505168962Spjd if (cmp == 0) { 2506168962Spjd /* 2507168962Spjd * POSIX: "If the old argument and the new argument 2508168962Spjd * both refer to links to the same existing file, 2509168962Spjd * the rename() function shall return successfully 2510168962Spjd * and perform no other action." 2511168962Spjd */ 2512168962Spjd ZFS_EXIT(zfsvfs); 2513168962Spjd return (0); 2514168962Spjd } 2515168962Spjd } 2516168962Spjd if (cmp < 0) { 2517168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2518168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2519168962Spjd } else { 2520168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2521168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2522168404Spjd } 2523168404Spjd 2524168962Spjd if (serr) { 2525168404Spjd /* 2526168404Spjd * Source entry invalid or not there. 2527168404Spjd */ 2528168962Spjd if (!terr) { 2529168404Spjd zfs_dirent_unlock(tdl); 2530168962Spjd if (tzp) 2531168962Spjd VN_RELE(ZTOV(tzp)); 2532168962Spjd } 2533168404Spjd if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0) 2534168404Spjd serr = EINVAL; 2535168962Spjd ZFS_EXIT(zfsvfs); 2536168962Spjd return (serr); 2537168404Spjd } 2538168404Spjd if (terr) { 2539168404Spjd zfs_dirent_unlock(sdl); 2540168962Spjd VN_RELE(ZTOV(szp)); 2541168404Spjd if (strcmp(tnm, "..") == 0) 2542168404Spjd terr = EINVAL; 2543168962Spjd ZFS_EXIT(zfsvfs); 2544168962Spjd return (terr); 2545168404Spjd } 2546168404Spjd 2547168404Spjd /* 2548168404Spjd * Must have write access at the source to remove the old entry 2549168404Spjd * and write access at the target to create the new entry. 2550168404Spjd * Note that if target and source are the same, this can be 2551168404Spjd * done in a single check. 2552168404Spjd */ 2553168404Spjd 2554168404Spjd if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) 2555168404Spjd goto out; 2556168404Spjd 2557168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2558168404Spjd /* 2559168404Spjd * Check to make sure rename is valid. 2560168404Spjd * Can't do a move like this: /usr/a/b to /usr/a/b/c/d 2561168404Spjd */ 2562168404Spjd if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl)) 2563168404Spjd goto out; 2564168404Spjd } 2565168404Spjd 2566168404Spjd /* 2567168404Spjd * Does target exist? 2568168404Spjd */ 2569168404Spjd if (tzp) { 2570168404Spjd /* 2571168404Spjd * Source and target must be the same type. 2572168404Spjd */ 2573168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2574168962Spjd if (ZTOV(tzp)->v_type != VDIR) { 2575168404Spjd error = ENOTDIR; 2576168404Spjd goto out; 2577168404Spjd } 2578168404Spjd } else { 2579168962Spjd if (ZTOV(tzp)->v_type == VDIR) { 2580168404Spjd error = EISDIR; 2581168404Spjd goto out; 2582168404Spjd } 2583168404Spjd } 2584168404Spjd /* 2585168404Spjd * POSIX dictates that when the source and target 2586168404Spjd * entries refer to the same file object, rename 2587168404Spjd * must do nothing and exit without error. 2588168404Spjd */ 2589168404Spjd if (szp->z_id == tzp->z_id) { 2590168404Spjd error = 0; 2591168404Spjd goto out; 2592168404Spjd } 2593168404Spjd } 2594168404Spjd 2595168962Spjd vnevent_rename_src(ZTOV(szp)); 2596168962Spjd if (tzp) 2597168962Spjd vnevent_rename_dest(ZTOV(tzp)); 2598168962Spjd 2599168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2600168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); /* nlink changes */ 2601168404Spjd dmu_tx_hold_bonus(tx, sdzp->z_id); /* nlink changes */ 2602168404Spjd dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm); 2603168404Spjd dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm); 2604168404Spjd if (sdzp != tdzp) 2605168404Spjd dmu_tx_hold_bonus(tx, tdzp->z_id); /* nlink changes */ 2606168404Spjd if (tzp) 2607168404Spjd dmu_tx_hold_bonus(tx, tzp->z_id); /* parent changes */ 2608168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 2609168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2610168404Spjd if (error) { 2611168404Spjd if (zl != NULL) 2612168404Spjd zfs_rename_unlock(&zl); 2613168404Spjd zfs_dirent_unlock(sdl); 2614168404Spjd zfs_dirent_unlock(tdl); 2615168962Spjd VN_RELE(ZTOV(szp)); 2616168962Spjd if (tzp) 2617168962Spjd VN_RELE(ZTOV(tzp)); 2618168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2619168404Spjd dmu_tx_wait(tx); 2620168404Spjd dmu_tx_abort(tx); 2621168404Spjd goto top; 2622168404Spjd } 2623168404Spjd dmu_tx_abort(tx); 2624168962Spjd ZFS_EXIT(zfsvfs); 2625168962Spjd return (error); 2626168404Spjd } 2627168404Spjd 2628168404Spjd if (tzp) /* Attempt to remove the existing target */ 2629168404Spjd error = zfs_link_destroy(tdl, tzp, tx, 0, NULL); 2630168404Spjd 2631168404Spjd if (error == 0) { 2632168404Spjd error = zfs_link_create(tdl, szp, tx, ZRENAMING); 2633168404Spjd if (error == 0) { 2634168404Spjd error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL); 2635168404Spjd ASSERT(error == 0); 2636168404Spjd zfs_log_rename(zilog, tx, TX_RENAME, sdzp, 2637168404Spjd sdl->dl_name, tdzp, tdl->dl_name, szp); 2638168404Spjd } 2639168404Spjd#ifdef FREEBSD_NAMECACHE 2640168404Spjd if (error == 0) { 2641168404Spjd cache_purge(sdvp); 2642168404Spjd cache_purge(tdvp); 2643168404Spjd } 2644168404Spjd#endif 2645168404Spjd } 2646168404Spjd 2647168404Spjd dmu_tx_commit(tx); 2648168404Spjdout: 2649168404Spjd if (zl != NULL) 2650168404Spjd zfs_rename_unlock(&zl); 2651168404Spjd 2652168404Spjd zfs_dirent_unlock(sdl); 2653168404Spjd zfs_dirent_unlock(tdl); 2654168404Spjd 2655168962Spjd VN_RELE(ZTOV(szp)); 2656168404Spjd if (tzp) 2657168962Spjd VN_RELE(ZTOV(tzp)); 2658168404Spjd 2659168404Spjd ZFS_EXIT(zfsvfs); 2660168404Spjd 2661168404Spjd return (error); 2662168404Spjd} 2663168404Spjd 2664168404Spjd/* 2665168404Spjd * Insert the indicated symbolic reference entry into the directory. 2666168404Spjd * 2667168404Spjd * IN: dvp - Directory to contain new symbolic link. 2668168404Spjd * link - Name for new symlink entry. 2669168404Spjd * vap - Attributes of new entry. 2670168404Spjd * target - Target path of new symlink. 2671168404Spjd * cr - credentials of caller. 2672168404Spjd * 2673168404Spjd * RETURN: 0 if success 2674168404Spjd * error code if failure 2675168404Spjd * 2676168404Spjd * Timestamps: 2677168404Spjd * dvp - ctime|mtime updated 2678168404Spjd */ 2679168404Spjdstatic int 2680168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td) 2681168404Spjd{ 2682168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 2683168404Spjd zfs_dirlock_t *dl; 2684168404Spjd dmu_tx_t *tx; 2685168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2686168404Spjd zilog_t *zilog = zfsvfs->z_log; 2687168404Spjd uint64_t zoid; 2688168404Spjd int len = strlen(link); 2689168404Spjd int error; 2690168404Spjd 2691168962Spjd ASSERT(vap->va_type == VLNK); 2692168404Spjd 2693168404Spjd ZFS_ENTER(zfsvfs); 2694168404Spjdtop: 2695168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2696168404Spjd ZFS_EXIT(zfsvfs); 2697168404Spjd return (error); 2698168404Spjd } 2699168404Spjd 2700168404Spjd if (len > MAXPATHLEN) { 2701168404Spjd ZFS_EXIT(zfsvfs); 2702168404Spjd return (ENAMETOOLONG); 2703168404Spjd } 2704168404Spjd 2705168404Spjd /* 2706168404Spjd * Attempt to lock directory; fail if entry already exists. 2707168404Spjd */ 2708168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) { 2709168404Spjd ZFS_EXIT(zfsvfs); 2710168404Spjd return (error); 2711168404Spjd } 2712168404Spjd 2713168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2714168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len)); 2715168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 2716168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2717168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 2718168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE); 2719168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2720168404Spjd if (error) { 2721168404Spjd zfs_dirent_unlock(dl); 2722168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2723168404Spjd dmu_tx_wait(tx); 2724168404Spjd dmu_tx_abort(tx); 2725168404Spjd goto top; 2726168404Spjd } 2727168404Spjd dmu_tx_abort(tx); 2728168404Spjd ZFS_EXIT(zfsvfs); 2729168404Spjd return (error); 2730168404Spjd } 2731168404Spjd 2732168404Spjd dmu_buf_will_dirty(dzp->z_dbuf, tx); 2733168404Spjd 2734168404Spjd /* 2735168404Spjd * Create a new object for the symlink. 2736168404Spjd * Put the link content into bonus buffer if it will fit; 2737168404Spjd * otherwise, store it just like any other file data. 2738168404Spjd */ 2739168404Spjd zoid = 0; 2740168404Spjd if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) { 2741168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len); 2742168404Spjd if (len != 0) 2743168404Spjd bcopy(link, zp->z_phys + 1, len); 2744168404Spjd } else { 2745168404Spjd dmu_buf_t *dbp; 2746168404Spjd 2747168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 2748168404Spjd 2749168404Spjd /* 2750168404Spjd * Nothing can access the znode yet so no locking needed 2751168404Spjd * for growing the znode's blocksize. 2752168404Spjd */ 2753168404Spjd zfs_grow_blocksize(zp, len, tx); 2754168404Spjd 2755168404Spjd VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp)); 2756168404Spjd dmu_buf_will_dirty(dbp, tx); 2757168404Spjd 2758168404Spjd ASSERT3U(len, <=, dbp->db_size); 2759168404Spjd bcopy(link, dbp->db_data, len); 2760168404Spjd dmu_buf_rele(dbp, FTAG); 2761168404Spjd } 2762168404Spjd zp->z_phys->zp_size = len; 2763168404Spjd 2764168404Spjd /* 2765168404Spjd * Insert the new object into the directory. 2766168404Spjd */ 2767168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 2768168962Spjdout: 2769168404Spjd if (error == 0) { 2770168404Spjd zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link); 2771168962Spjd *vpp = ZTOV(zp); 2772175202Sattilio vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 2773168404Spjd } 2774168404Spjd 2775168404Spjd dmu_tx_commit(tx); 2776168404Spjd 2777168404Spjd zfs_dirent_unlock(dl); 2778168404Spjd 2779168404Spjd ZFS_EXIT(zfsvfs); 2780168404Spjd return (error); 2781168404Spjd} 2782168404Spjd 2783168404Spjd/* 2784168404Spjd * Return, in the buffer contained in the provided uio structure, 2785168404Spjd * the symbolic path referred to by vp. 2786168404Spjd * 2787168404Spjd * IN: vp - vnode of symbolic link. 2788168404Spjd * uoip - structure to contain the link path. 2789168404Spjd * cr - credentials of caller. 2790168404Spjd * 2791168404Spjd * OUT: uio - structure to contain the link path. 2792168404Spjd * 2793168404Spjd * RETURN: 0 if success 2794168404Spjd * error code if failure 2795168404Spjd * 2796168404Spjd * Timestamps: 2797168404Spjd * vp - atime updated 2798168404Spjd */ 2799168404Spjd/* ARGSUSED */ 2800168404Spjdstatic int 2801168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr) 2802168404Spjd{ 2803168404Spjd znode_t *zp = VTOZ(vp); 2804168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2805168404Spjd size_t bufsz; 2806168404Spjd int error; 2807168404Spjd 2808168404Spjd ZFS_ENTER(zfsvfs); 2809168404Spjd 2810168404Spjd bufsz = (size_t)zp->z_phys->zp_size; 2811168404Spjd if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) { 2812168404Spjd error = uiomove(zp->z_phys + 1, 2813168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2814168404Spjd } else { 2815168404Spjd dmu_buf_t *dbp; 2816168404Spjd error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp); 2817168404Spjd if (error) { 2818168404Spjd ZFS_EXIT(zfsvfs); 2819168404Spjd return (error); 2820168404Spjd } 2821168404Spjd error = uiomove(dbp->db_data, 2822168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2823168404Spjd dmu_buf_rele(dbp, FTAG); 2824168404Spjd } 2825168404Spjd 2826168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 2827168404Spjd ZFS_EXIT(zfsvfs); 2828168404Spjd return (error); 2829168404Spjd} 2830168404Spjd 2831168404Spjd/* 2832168404Spjd * Insert a new entry into directory tdvp referencing svp. 2833168404Spjd * 2834168404Spjd * IN: tdvp - Directory to contain new entry. 2835168404Spjd * svp - vnode of new entry. 2836168404Spjd * name - name of new entry. 2837168404Spjd * cr - credentials of caller. 2838168404Spjd * 2839168404Spjd * RETURN: 0 if success 2840168404Spjd * error code if failure 2841168404Spjd * 2842168404Spjd * Timestamps: 2843168404Spjd * tdvp - ctime|mtime updated 2844168404Spjd * svp - ctime updated 2845168404Spjd */ 2846168404Spjd/* ARGSUSED */ 2847168404Spjdstatic int 2848168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr) 2849168404Spjd{ 2850168404Spjd znode_t *dzp = VTOZ(tdvp); 2851168404Spjd znode_t *tzp, *szp; 2852168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2853168404Spjd zilog_t *zilog = zfsvfs->z_log; 2854168404Spjd zfs_dirlock_t *dl; 2855168404Spjd dmu_tx_t *tx; 2856168962Spjd vnode_t *realvp; 2857168404Spjd int error; 2858168404Spjd 2859168404Spjd ASSERT(tdvp->v_type == VDIR); 2860168404Spjd 2861168404Spjd ZFS_ENTER(zfsvfs); 2862168404Spjd 2863168962Spjd if (VOP_REALVP(svp, &realvp) == 0) 2864168962Spjd svp = realvp; 2865168962Spjd 2866168404Spjd if (svp->v_vfsp != tdvp->v_vfsp) { 2867168404Spjd ZFS_EXIT(zfsvfs); 2868168404Spjd return (EXDEV); 2869168404Spjd } 2870168404Spjd 2871168404Spjd szp = VTOZ(svp); 2872168404Spjdtop: 2873168404Spjd /* 2874168404Spjd * We do not support links between attributes and non-attributes 2875168404Spjd * because of the potential security risk of creating links 2876168404Spjd * into "normal" file space in order to circumvent restrictions 2877168404Spjd * imposed in attribute space. 2878168404Spjd */ 2879168404Spjd if ((szp->z_phys->zp_flags & ZFS_XATTR) != 2880168404Spjd (dzp->z_phys->zp_flags & ZFS_XATTR)) { 2881168404Spjd ZFS_EXIT(zfsvfs); 2882168404Spjd return (EINVAL); 2883168404Spjd } 2884168404Spjd 2885168404Spjd /* 2886168404Spjd * POSIX dictates that we return EPERM here. 2887168404Spjd * Better choices include ENOTSUP or EISDIR. 2888168404Spjd */ 2889168404Spjd if (svp->v_type == VDIR) { 2890168404Spjd ZFS_EXIT(zfsvfs); 2891168404Spjd return (EPERM); 2892168404Spjd } 2893168404Spjd 2894168404Spjd if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) && 2895168404Spjd secpolicy_basic_link(cr) != 0) { 2896168404Spjd ZFS_EXIT(zfsvfs); 2897168404Spjd return (EPERM); 2898168404Spjd } 2899168404Spjd 2900168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2901168404Spjd ZFS_EXIT(zfsvfs); 2902168404Spjd return (error); 2903168404Spjd } 2904168404Spjd 2905168404Spjd /* 2906168404Spjd * Attempt to lock directory; fail if entry already exists. 2907168404Spjd */ 2908168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) { 2909168404Spjd ZFS_EXIT(zfsvfs); 2910168404Spjd return (error); 2911168404Spjd } 2912168404Spjd 2913168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2914168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); 2915168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2916168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2917168404Spjd if (error) { 2918168404Spjd zfs_dirent_unlock(dl); 2919168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2920168404Spjd dmu_tx_wait(tx); 2921168404Spjd dmu_tx_abort(tx); 2922168404Spjd goto top; 2923168404Spjd } 2924168404Spjd dmu_tx_abort(tx); 2925168404Spjd ZFS_EXIT(zfsvfs); 2926168404Spjd return (error); 2927168404Spjd } 2928168404Spjd 2929168404Spjd error = zfs_link_create(dl, szp, tx, 0); 2930168404Spjd 2931168404Spjd if (error == 0) 2932168404Spjd zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name); 2933168404Spjd 2934168404Spjd dmu_tx_commit(tx); 2935168404Spjd 2936168404Spjd zfs_dirent_unlock(dl); 2937168404Spjd 2938168404Spjd ZFS_EXIT(zfsvfs); 2939168404Spjd return (error); 2940168404Spjd} 2941168404Spjd 2942168962Spjdvoid 2943168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr) 2944168404Spjd{ 2945168962Spjd znode_t *zp = VTOZ(vp); 2946168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2947168962Spjd int error; 2948168404Spjd 2949168404Spjd rw_enter(&zfsvfs->z_um_lock, RW_READER); 2950168404Spjd if (zfsvfs->z_unmounted2) { 2951168404Spjd ASSERT(zp->z_dbuf_held == 0); 2952168404Spjd 2953168404Spjd mutex_enter(&zp->z_lock); 2954168404Spjd VI_LOCK(vp); 2955168404Spjd vp->v_count = 0; /* count arrives as 1 */ 2956168404Spjd VI_UNLOCK(vp); 2957168404Spjd if (zp->z_dbuf == NULL) { 2958168404Spjd mutex_exit(&zp->z_lock); 2959168404Spjd zfs_znode_free(zp); 2960168404Spjd } else { 2961168404Spjd mutex_exit(&zp->z_lock); 2962168404Spjd } 2963168404Spjd rw_exit(&zfsvfs->z_um_lock); 2964168404Spjd VFS_RELE(zfsvfs->z_vfs); 2965168962Spjd return; 2966168404Spjd } 2967168404Spjd 2968168404Spjd if (zp->z_atime_dirty && zp->z_unlinked == 0) { 2969168404Spjd dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 2970168404Spjd 2971168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2972168404Spjd error = dmu_tx_assign(tx, TXG_WAIT); 2973168404Spjd if (error) { 2974168404Spjd dmu_tx_abort(tx); 2975168404Spjd } else { 2976168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2977168404Spjd mutex_enter(&zp->z_lock); 2978168404Spjd zp->z_atime_dirty = 0; 2979168404Spjd mutex_exit(&zp->z_lock); 2980168404Spjd dmu_tx_commit(tx); 2981168404Spjd } 2982168404Spjd } 2983168404Spjd 2984168404Spjd zfs_zinactive(zp); 2985168404Spjd rw_exit(&zfsvfs->z_um_lock); 2986168404Spjd} 2987168404Spjd 2988168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid)); 2989168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid)); 2990168404Spjd 2991168404Spjdstatic int 2992168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp) 2993168404Spjd{ 2994168404Spjd znode_t *zp = VTOZ(vp); 2995168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2996168404Spjd uint32_t gen = (uint32_t)zp->z_phys->zp_gen; 2997168404Spjd uint64_t object = zp->z_id; 2998168404Spjd zfid_short_t *zfid; 2999168404Spjd int size, i; 3000168404Spjd 3001168404Spjd ZFS_ENTER(zfsvfs); 3002168404Spjd 3003168404Spjd size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN; 3004168404Spjd fidp->fid_len = size; 3005168404Spjd 3006168404Spjd zfid = (zfid_short_t *)fidp; 3007168404Spjd 3008168404Spjd zfid->zf_len = size; 3009168404Spjd 3010168404Spjd for (i = 0; i < sizeof (zfid->zf_object); i++) 3011168404Spjd zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 3012168404Spjd 3013168404Spjd /* Must have a non-zero generation number to distinguish from .zfs */ 3014168404Spjd if (gen == 0) 3015168404Spjd gen = 1; 3016168404Spjd for (i = 0; i < sizeof (zfid->zf_gen); i++) 3017168404Spjd zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i)); 3018168404Spjd 3019168404Spjd if (size == LONG_FID_LEN) { 3020168404Spjd uint64_t objsetid = dmu_objset_id(zfsvfs->z_os); 3021169023Spjd zfid_long_t *zlfid; 3022168404Spjd 3023168404Spjd zlfid = (zfid_long_t *)fidp; 3024168404Spjd 3025168404Spjd for (i = 0; i < sizeof (zlfid->zf_setid); i++) 3026168404Spjd zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i)); 3027168404Spjd 3028168404Spjd /* XXX - this should be the generation number for the objset */ 3029168404Spjd for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 3030168404Spjd zlfid->zf_setgen[i] = 0; 3031168404Spjd } 3032168404Spjd 3033168404Spjd ZFS_EXIT(zfsvfs); 3034168404Spjd return (0); 3035168404Spjd} 3036168404Spjd 3037168404Spjdstatic int 3038168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) 3039168404Spjd{ 3040168404Spjd znode_t *zp, *xzp; 3041168404Spjd zfsvfs_t *zfsvfs; 3042168404Spjd zfs_dirlock_t *dl; 3043168404Spjd int error; 3044168404Spjd 3045168404Spjd switch (cmd) { 3046168404Spjd case _PC_LINK_MAX: 3047168404Spjd *valp = INT_MAX; 3048168404Spjd return (0); 3049168404Spjd 3050168404Spjd case _PC_FILESIZEBITS: 3051168404Spjd *valp = 64; 3052168404Spjd return (0); 3053168404Spjd 3054168404Spjd#if 0 3055168404Spjd case _PC_XATTR_EXISTS: 3056168404Spjd zp = VTOZ(vp); 3057168404Spjd zfsvfs = zp->z_zfsvfs; 3058168404Spjd ZFS_ENTER(zfsvfs); 3059168404Spjd *valp = 0; 3060168404Spjd error = zfs_dirent_lock(&dl, zp, "", &xzp, 3061168404Spjd ZXATTR | ZEXISTS | ZSHARED); 3062168404Spjd if (error == 0) { 3063168404Spjd zfs_dirent_unlock(dl); 3064168404Spjd if (!zfs_dirempty(xzp)) 3065168404Spjd *valp = 1; 3066168404Spjd VN_RELE(ZTOV(xzp)); 3067168404Spjd } else if (error == ENOENT) { 3068168404Spjd /* 3069168404Spjd * If there aren't extended attributes, it's the 3070168404Spjd * same as having zero of them. 3071168404Spjd */ 3072168404Spjd error = 0; 3073168404Spjd } 3074168404Spjd ZFS_EXIT(zfsvfs); 3075168404Spjd return (error); 3076168404Spjd#endif 3077168404Spjd 3078168404Spjd case _PC_ACL_EXTENDED: 3079168404Spjd *valp = 0; /* TODO */ 3080168404Spjd return (0); 3081168404Spjd 3082168404Spjd case _PC_MIN_HOLE_SIZE: 3083168404Spjd *valp = (int)SPA_MINBLOCKSIZE; 3084168404Spjd return (0); 3085168404Spjd 3086168404Spjd default: 3087168962Spjd return (EOPNOTSUPP); 3088168404Spjd } 3089168404Spjd} 3090168404Spjd 3091168404Spjd#ifdef TODO 3092168404Spjd/*ARGSUSED*/ 3093168404Spjdstatic int 3094168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3095168404Spjd{ 3096168404Spjd znode_t *zp = VTOZ(vp); 3097168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3098168404Spjd int error; 3099168404Spjd 3100168404Spjd ZFS_ENTER(zfsvfs); 3101168404Spjd error = zfs_getacl(zp, vsecp, cr); 3102168404Spjd ZFS_EXIT(zfsvfs); 3103168404Spjd 3104168404Spjd return (error); 3105168404Spjd} 3106168404Spjd#endif /* TODO */ 3107168404Spjd 3108168404Spjd#ifdef TODO 3109168404Spjd/*ARGSUSED*/ 3110168404Spjdstatic int 3111168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3112168404Spjd{ 3113168404Spjd znode_t *zp = VTOZ(vp); 3114168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3115168404Spjd int error; 3116168404Spjd 3117168404Spjd ZFS_ENTER(zfsvfs); 3118168404Spjd error = zfs_setacl(zp, vsecp, cr); 3119168404Spjd ZFS_EXIT(zfsvfs); 3120168404Spjd return (error); 3121168404Spjd} 3122168404Spjd#endif /* TODO */ 3123168404Spjd 3124168962Spjdstatic int 3125168962Spjdzfs_freebsd_open(ap) 3126168962Spjd struct vop_open_args /* { 3127168962Spjd struct vnode *a_vp; 3128168962Spjd int a_mode; 3129168962Spjd struct ucred *a_cred; 3130168962Spjd struct thread *a_td; 3131168962Spjd } */ *ap; 3132168962Spjd{ 3133168962Spjd vnode_t *vp = ap->a_vp; 3134168962Spjd znode_t *zp = VTOZ(vp); 3135168962Spjd int error; 3136168962Spjd 3137168962Spjd error = zfs_open(&vp, ap->a_mode, ap->a_cred); 3138168962Spjd if (error == 0) 3139168962Spjd vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); 3140168962Spjd return (error); 3141168962Spjd} 3142168962Spjd 3143168962Spjdstatic int 3144168962Spjdzfs_freebsd_close(ap) 3145168962Spjd struct vop_close_args /* { 3146168962Spjd struct vnode *a_vp; 3147168962Spjd int a_fflag; 3148168962Spjd struct ucred *a_cred; 3149168962Spjd struct thread *a_td; 3150168962Spjd } */ *ap; 3151168962Spjd{ 3152168962Spjd 3153168962Spjd return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred)); 3154168962Spjd} 3155168962Spjd 3156168962Spjdstatic int 3157168962Spjdzfs_freebsd_ioctl(ap) 3158168962Spjd struct vop_ioctl_args /* { 3159168962Spjd struct vnode *a_vp; 3160168962Spjd u_long a_command; 3161168962Spjd caddr_t a_data; 3162168962Spjd int a_fflag; 3163168962Spjd struct ucred *cred; 3164168962Spjd struct thread *td; 3165168962Spjd } */ *ap; 3166168962Spjd{ 3167168962Spjd 3168168978Spjd return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data, 3169168962Spjd ap->a_fflag, ap->a_cred, NULL)); 3170168962Spjd} 3171168962Spjd 3172168962Spjdstatic int 3173168962Spjdzfs_freebsd_read(ap) 3174168962Spjd struct vop_read_args /* { 3175168962Spjd struct vnode *a_vp; 3176168962Spjd struct uio *a_uio; 3177168962Spjd int a_ioflag; 3178168962Spjd struct ucred *a_cred; 3179168962Spjd } */ *ap; 3180168962Spjd{ 3181168962Spjd 3182168962Spjd return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3183168962Spjd} 3184168962Spjd 3185168962Spjdstatic int 3186168962Spjdzfs_freebsd_write(ap) 3187168962Spjd struct vop_write_args /* { 3188168962Spjd struct vnode *a_vp; 3189168962Spjd struct uio *a_uio; 3190168962Spjd int a_ioflag; 3191168962Spjd struct ucred *a_cred; 3192168962Spjd } */ *ap; 3193168962Spjd{ 3194168962Spjd 3195168962Spjd return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3196168962Spjd} 3197168962Spjd 3198168962Spjdstatic int 3199168962Spjdzfs_freebsd_access(ap) 3200168962Spjd struct vop_access_args /* { 3201168962Spjd struct vnode *a_vp; 3202168962Spjd int a_mode; 3203168962Spjd struct ucred *a_cred; 3204168962Spjd struct thread *a_td; 3205168962Spjd } */ *ap; 3206168962Spjd{ 3207168962Spjd 3208168962Spjd return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred)); 3209168962Spjd} 3210168962Spjd 3211168962Spjdstatic int 3212168962Spjdzfs_freebsd_lookup(ap) 3213168962Spjd struct vop_lookup_args /* { 3214168962Spjd struct vnode *a_dvp; 3215168962Spjd struct vnode **a_vpp; 3216168962Spjd struct componentname *a_cnp; 3217168962Spjd } */ *ap; 3218168962Spjd{ 3219168962Spjd struct componentname *cnp = ap->a_cnp; 3220168962Spjd char nm[NAME_MAX + 1]; 3221168962Spjd 3222168962Spjd ASSERT(cnp->cn_namelen < sizeof(nm)); 3223168962Spjd strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm))); 3224168962Spjd 3225168962Spjd return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop, 3226168962Spjd cnp->cn_cred, cnp->cn_thread)); 3227168962Spjd} 3228168962Spjd 3229168962Spjdstatic int 3230168962Spjdzfs_freebsd_create(ap) 3231168962Spjd struct vop_create_args /* { 3232168962Spjd struct vnode *a_dvp; 3233168962Spjd struct vnode **a_vpp; 3234168962Spjd struct componentname *a_cnp; 3235168962Spjd struct vattr *a_vap; 3236168962Spjd } */ *ap; 3237168962Spjd{ 3238168962Spjd struct componentname *cnp = ap->a_cnp; 3239168962Spjd vattr_t *vap = ap->a_vap; 3240168962Spjd int mode; 3241168962Spjd 3242168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3243168962Spjd 3244168962Spjd vattr_init_mask(vap); 3245168962Spjd mode = vap->va_mode & ALLPERMS; 3246168962Spjd 3247168962Spjd return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode, 3248176559Sattilio ap->a_vpp, cnp->cn_cred)); 3249168962Spjd} 3250168962Spjd 3251168962Spjdstatic int 3252168962Spjdzfs_freebsd_remove(ap) 3253168962Spjd struct vop_remove_args /* { 3254168962Spjd struct vnode *a_dvp; 3255168962Spjd struct vnode *a_vp; 3256168962Spjd struct componentname *a_cnp; 3257168962Spjd } */ *ap; 3258168962Spjd{ 3259168962Spjd 3260168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3261168962Spjd 3262168962Spjd return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr, 3263168962Spjd ap->a_cnp->cn_cred)); 3264168962Spjd} 3265168962Spjd 3266168962Spjdstatic int 3267168962Spjdzfs_freebsd_mkdir(ap) 3268168962Spjd struct vop_mkdir_args /* { 3269168962Spjd struct vnode *a_dvp; 3270168962Spjd struct vnode **a_vpp; 3271168962Spjd struct componentname *a_cnp; 3272168962Spjd struct vattr *a_vap; 3273168962Spjd } */ *ap; 3274168962Spjd{ 3275168962Spjd vattr_t *vap = ap->a_vap; 3276168962Spjd 3277168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3278168962Spjd 3279168962Spjd vattr_init_mask(vap); 3280168962Spjd 3281168962Spjd return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp, 3282168962Spjd ap->a_cnp->cn_cred)); 3283168962Spjd} 3284168962Spjd 3285168962Spjdstatic int 3286168962Spjdzfs_freebsd_rmdir(ap) 3287168962Spjd struct vop_rmdir_args /* { 3288168962Spjd struct vnode *a_dvp; 3289168962Spjd struct vnode *a_vp; 3290168962Spjd struct componentname *a_cnp; 3291168962Spjd } */ *ap; 3292168962Spjd{ 3293168962Spjd struct componentname *cnp = ap->a_cnp; 3294168962Spjd 3295168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3296168962Spjd 3297168962Spjd return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred)); 3298168962Spjd} 3299168962Spjd 3300168962Spjdstatic int 3301168962Spjdzfs_freebsd_readdir(ap) 3302168962Spjd struct vop_readdir_args /* { 3303168962Spjd struct vnode *a_vp; 3304168962Spjd struct uio *a_uio; 3305168962Spjd struct ucred *a_cred; 3306168962Spjd int *a_eofflag; 3307168962Spjd int *a_ncookies; 3308168962Spjd u_long **a_cookies; 3309168962Spjd } */ *ap; 3310168962Spjd{ 3311168962Spjd 3312168962Spjd return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, 3313168962Spjd ap->a_ncookies, ap->a_cookies)); 3314168962Spjd} 3315168962Spjd 3316168962Spjdstatic int 3317168962Spjdzfs_freebsd_fsync(ap) 3318168962Spjd struct vop_fsync_args /* { 3319168962Spjd struct vnode *a_vp; 3320168962Spjd int a_waitfor; 3321168962Spjd struct thread *a_td; 3322168962Spjd } */ *ap; 3323168962Spjd{ 3324168962Spjd 3325168962Spjd vop_stdfsync(ap); 3326168962Spjd return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred)); 3327168962Spjd} 3328168962Spjd 3329168962Spjdstatic int 3330168962Spjdzfs_freebsd_getattr(ap) 3331168962Spjd struct vop_getattr_args /* { 3332168962Spjd struct vnode *a_vp; 3333168962Spjd struct vattr *a_vap; 3334168962Spjd struct ucred *a_cred; 3335168962Spjd struct thread *a_td; 3336168962Spjd } */ *ap; 3337168962Spjd{ 3338168962Spjd 3339168962Spjd return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred)); 3340168962Spjd} 3341168962Spjd 3342168962Spjdstatic int 3343168962Spjdzfs_freebsd_setattr(ap) 3344168962Spjd struct vop_setattr_args /* { 3345168962Spjd struct vnode *a_vp; 3346168962Spjd struct vattr *a_vap; 3347168962Spjd struct ucred *a_cred; 3348168962Spjd struct thread *a_td; 3349168962Spjd } */ *ap; 3350168962Spjd{ 3351168962Spjd vattr_t *vap = ap->a_vap; 3352168962Spjd 3353168962Spjd /* No support for FreeBSD's chflags(2). */ 3354168962Spjd if (vap->va_flags != VNOVAL) 3355168962Spjd return (EOPNOTSUPP); 3356168962Spjd 3357168962Spjd vattr_init_mask(vap); 3358170044Spjd vap->va_mask &= ~AT_NOSET; 3359168962Spjd 3360168962Spjd return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL)); 3361168962Spjd} 3362168962Spjd 3363168962Spjdstatic int 3364168962Spjdzfs_freebsd_rename(ap) 3365168962Spjd struct vop_rename_args /* { 3366168962Spjd struct vnode *a_fdvp; 3367168962Spjd struct vnode *a_fvp; 3368168962Spjd struct componentname *a_fcnp; 3369168962Spjd struct vnode *a_tdvp; 3370168962Spjd struct vnode *a_tvp; 3371168962Spjd struct componentname *a_tcnp; 3372168962Spjd } */ *ap; 3373168962Spjd{ 3374168962Spjd vnode_t *fdvp = ap->a_fdvp; 3375168962Spjd vnode_t *fvp = ap->a_fvp; 3376168962Spjd vnode_t *tdvp = ap->a_tdvp; 3377168962Spjd vnode_t *tvp = ap->a_tvp; 3378168962Spjd int error; 3379168962Spjd 3380168962Spjd ASSERT(ap->a_fcnp->cn_flags & SAVENAME); 3381168962Spjd ASSERT(ap->a_tcnp->cn_flags & SAVENAME); 3382168962Spjd 3383168962Spjd error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp, 3384168962Spjd ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred); 3385168962Spjd 3386168962Spjd if (tdvp == tvp) 3387168962Spjd VN_RELE(tdvp); 3388168962Spjd else 3389168962Spjd VN_URELE(tdvp); 3390168962Spjd if (tvp) 3391168962Spjd VN_URELE(tvp); 3392168962Spjd VN_RELE(fdvp); 3393168962Spjd VN_RELE(fvp); 3394168962Spjd 3395168962Spjd return (error); 3396168962Spjd} 3397168962Spjd 3398168962Spjdstatic int 3399168962Spjdzfs_freebsd_symlink(ap) 3400168962Spjd struct vop_symlink_args /* { 3401168962Spjd struct vnode *a_dvp; 3402168962Spjd struct vnode **a_vpp; 3403168962Spjd struct componentname *a_cnp; 3404168962Spjd struct vattr *a_vap; 3405168962Spjd char *a_target; 3406168962Spjd } */ *ap; 3407168962Spjd{ 3408168962Spjd struct componentname *cnp = ap->a_cnp; 3409168962Spjd vattr_t *vap = ap->a_vap; 3410168962Spjd 3411168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3412168962Spjd 3413168962Spjd vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ 3414168962Spjd vattr_init_mask(vap); 3415168962Spjd 3416168962Spjd return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap, 3417168962Spjd ap->a_target, cnp->cn_cred, cnp->cn_thread)); 3418168962Spjd} 3419168962Spjd 3420168962Spjdstatic int 3421168962Spjdzfs_freebsd_readlink(ap) 3422168962Spjd struct vop_readlink_args /* { 3423168962Spjd struct vnode *a_vp; 3424168962Spjd struct uio *a_uio; 3425168962Spjd struct ucred *a_cred; 3426168962Spjd } */ *ap; 3427168962Spjd{ 3428168962Spjd 3429168962Spjd return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred)); 3430168962Spjd} 3431168962Spjd 3432168962Spjdstatic int 3433168962Spjdzfs_freebsd_link(ap) 3434168962Spjd struct vop_link_args /* { 3435168962Spjd struct vnode *a_tdvp; 3436168962Spjd struct vnode *a_vp; 3437168962Spjd struct componentname *a_cnp; 3438168962Spjd } */ *ap; 3439168962Spjd{ 3440168962Spjd struct componentname *cnp = ap->a_cnp; 3441168962Spjd 3442168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3443168962Spjd 3444168962Spjd return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred)); 3445168962Spjd} 3446168962Spjd 3447168962Spjdstatic int 3448168962Spjdzfs_freebsd_inactive(ap) 3449169170Spjd struct vop_inactive_args /* { 3450169170Spjd struct vnode *a_vp; 3451169170Spjd struct thread *a_td; 3452169170Spjd } */ *ap; 3453168962Spjd{ 3454168962Spjd vnode_t *vp = ap->a_vp; 3455168962Spjd 3456168962Spjd zfs_inactive(vp, ap->a_td->td_ucred); 3457168962Spjd return (0); 3458168962Spjd} 3459168962Spjd 3460168962Spjdstatic int 3461168962Spjdzfs_freebsd_reclaim(ap) 3462168962Spjd struct vop_reclaim_args /* { 3463168962Spjd struct vnode *a_vp; 3464168962Spjd struct thread *a_td; 3465168962Spjd } */ *ap; 3466168962Spjd{ 3467169170Spjd vnode_t *vp = ap->a_vp; 3468168962Spjd znode_t *zp = VTOZ(vp); 3469169025Spjd zfsvfs_t *zfsvfs; 3470169025Spjd int rele = 1; 3471168962Spjd 3472169025Spjd ASSERT(zp != NULL); 3473169025Spjd 3474168962Spjd /* 3475168962Spjd * Destroy the vm object and flush associated pages. 3476168962Spjd */ 3477168962Spjd vnode_destroy_vobject(vp); 3478169025Spjd 3479169025Spjd mutex_enter(&zp->z_lock); 3480169025Spjd ASSERT(zp->z_phys); 3481169025Spjd ASSERT(zp->z_dbuf_held); 3482169025Spjd zfsvfs = zp->z_zfsvfs; 3483169025Spjd if (!zp->z_unlinked) { 3484169025Spjd zp->z_dbuf_held = 0; 3485169025Spjd ZTOV(zp) = NULL; 3486169025Spjd mutex_exit(&zp->z_lock); 3487169025Spjd dmu_buf_rele(zp->z_dbuf, NULL); 3488169025Spjd } else { 3489169025Spjd mutex_exit(&zp->z_lock); 3490169025Spjd } 3491168962Spjd VI_LOCK(vp); 3492169025Spjd if (vp->v_count > 0) 3493169025Spjd rele = 0; 3494168962Spjd vp->v_data = NULL; 3495171567Spjd ASSERT(vp->v_holdcnt >= 1); 3496171316Sdfr VI_UNLOCK(vp); 3497169025Spjd if (!zp->z_unlinked && rele) 3498169025Spjd VFS_RELE(zfsvfs->z_vfs); 3499168962Spjd return (0); 3500168962Spjd} 3501168962Spjd 3502168962Spjdstatic int 3503168962Spjdzfs_freebsd_fid(ap) 3504168962Spjd struct vop_fid_args /* { 3505168962Spjd struct vnode *a_vp; 3506168962Spjd struct fid *a_fid; 3507168962Spjd } */ *ap; 3508168962Spjd{ 3509168962Spjd 3510168962Spjd return (zfs_fid(ap->a_vp, (void *)ap->a_fid)); 3511168962Spjd} 3512168962Spjd 3513168962Spjdstatic int 3514168962Spjdzfs_freebsd_pathconf(ap) 3515168962Spjd struct vop_pathconf_args /* { 3516168962Spjd struct vnode *a_vp; 3517168962Spjd int a_name; 3518168962Spjd register_t *a_retval; 3519168962Spjd } */ *ap; 3520168962Spjd{ 3521168962Spjd ulong_t val; 3522168962Spjd int error; 3523168962Spjd 3524168962Spjd error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred); 3525168962Spjd if (error == 0) 3526168962Spjd *ap->a_retval = val; 3527168962Spjd else if (error == EOPNOTSUPP) 3528168962Spjd error = vop_stdpathconf(ap); 3529168962Spjd return (error); 3530168962Spjd} 3531168962Spjd 3532168404Spjd/* 3533168404Spjd * Advisory record locking support 3534168404Spjd */ 3535168404Spjdstatic int 3536168962Spjdzfs_freebsd_advlock(ap) 3537168404Spjd struct vop_advlock_args /* { 3538168404Spjd struct vnode *a_vp; 3539168404Spjd caddr_t a_id; 3540168404Spjd int a_op; 3541168404Spjd struct flock *a_fl; 3542168404Spjd int a_flags; 3543168404Spjd } */ *ap; 3544168404Spjd{ 3545168404Spjd znode_t *zp = VTOZ(ap->a_vp); 3546168404Spjd 3547168404Spjd return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size)); 3548168404Spjd} 3549168404Spjd 3550168404Spjdstruct vop_vector zfs_vnodeops; 3551168404Spjdstruct vop_vector zfs_fifoops; 3552168404Spjd 3553168404Spjdstruct vop_vector zfs_vnodeops = { 3554168404Spjd .vop_default = &default_vnodeops, 3555168962Spjd .vop_inactive = zfs_freebsd_inactive, 3556168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3557168962Spjd .vop_access = zfs_freebsd_access, 3558168404Spjd#ifdef FREEBSD_NAMECACHE 3559168404Spjd .vop_lookup = vfs_cache_lookup, 3560168962Spjd .vop_cachedlookup = zfs_freebsd_lookup, 3561168404Spjd#else 3562168962Spjd .vop_lookup = zfs_freebsd_lookup, 3563168404Spjd#endif 3564168962Spjd .vop_getattr = zfs_freebsd_getattr, 3565168962Spjd .vop_setattr = zfs_freebsd_setattr, 3566168962Spjd .vop_create = zfs_freebsd_create, 3567168962Spjd .vop_mknod = zfs_freebsd_create, 3568168962Spjd .vop_mkdir = zfs_freebsd_mkdir, 3569168962Spjd .vop_readdir = zfs_freebsd_readdir, 3570168962Spjd .vop_fsync = zfs_freebsd_fsync, 3571168962Spjd .vop_open = zfs_freebsd_open, 3572168962Spjd .vop_close = zfs_freebsd_close, 3573168962Spjd .vop_rmdir = zfs_freebsd_rmdir, 3574168962Spjd .vop_ioctl = zfs_freebsd_ioctl, 3575168962Spjd .vop_link = zfs_freebsd_link, 3576168962Spjd .vop_symlink = zfs_freebsd_symlink, 3577168962Spjd .vop_readlink = zfs_freebsd_readlink, 3578168962Spjd .vop_read = zfs_freebsd_read, 3579168962Spjd .vop_write = zfs_freebsd_write, 3580168962Spjd .vop_remove = zfs_freebsd_remove, 3581168962Spjd .vop_rename = zfs_freebsd_rename, 3582168962Spjd .vop_advlock = zfs_freebsd_advlock, 3583168962Spjd .vop_pathconf = zfs_freebsd_pathconf, 3584168404Spjd .vop_bmap = VOP_EOPNOTSUPP, 3585168962Spjd .vop_fid = zfs_freebsd_fid, 3586168404Spjd}; 3587168404Spjd 3588169170Spjdstruct vop_vector zfs_fifoops = { 3589168404Spjd .vop_default = &fifo_specops, 3590168404Spjd .vop_fsync = VOP_PANIC, 3591168962Spjd .vop_access = zfs_freebsd_access, 3592168962Spjd .vop_getattr = zfs_freebsd_getattr, 3593168962Spjd .vop_inactive = zfs_freebsd_inactive, 3594168404Spjd .vop_read = VOP_PANIC, 3595168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3596168962Spjd .vop_setattr = zfs_freebsd_setattr, 3597168404Spjd .vop_write = VOP_PANIC, 3598168962Spjd .vop_fid = zfs_freebsd_fid, 3599168404Spjd}; 3600