zfs_vnops.c revision 169167
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22168404Spjd * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 27168404Spjd 28168404Spjd#include <sys/types.h> 29168404Spjd#include <sys/param.h> 30168404Spjd#include <sys/time.h> 31168404Spjd#include <sys/systm.h> 32168404Spjd#include <sys/sysmacros.h> 33168404Spjd#include <sys/resource.h> 34168404Spjd#include <sys/vfs.h> 35168404Spjd#include <sys/vnode.h> 36168404Spjd#include <sys/file.h> 37168404Spjd#include <sys/stat.h> 38168404Spjd#include <sys/kmem.h> 39168404Spjd#include <sys/taskq.h> 40168404Spjd#include <sys/uio.h> 41168404Spjd#include <sys/atomic.h> 42168404Spjd#include <sys/namei.h> 43168404Spjd#include <sys/mman.h> 44168404Spjd#include <sys/cmn_err.h> 45168404Spjd#include <sys/errno.h> 46168404Spjd#include <sys/unistd.h> 47168404Spjd#include <sys/zfs_vfsops.h> 48168404Spjd#include <sys/zfs_dir.h> 49168404Spjd#include <sys/zfs_acl.h> 50168404Spjd#include <sys/zfs_ioctl.h> 51168404Spjd#include <sys/fs/zfs.h> 52168404Spjd#include <sys/dmu.h> 53168404Spjd#include <sys/spa.h> 54168404Spjd#include <sys/txg.h> 55168404Spjd#include <sys/dbuf.h> 56168404Spjd#include <sys/zap.h> 57168404Spjd#include <sys/dirent.h> 58168962Spjd#include <sys/policy.h> 59168962Spjd#include <sys/sunddi.h> 60168404Spjd#include <sys/filio.h> 61168404Spjd#include <sys/zfs_ctldir.h> 62168404Spjd#include <sys/dnlc.h> 63168404Spjd#include <sys/zfs_rlock.h> 64168404Spjd#include <sys/bio.h> 65168404Spjd#include <sys/buf.h> 66168404Spjd#include <sys/sf_buf.h> 67168404Spjd#include <sys/sched.h> 68168404Spjd 69168404Spjd/* 70168404Spjd * Programming rules. 71168404Spjd * 72168404Spjd * Each vnode op performs some logical unit of work. To do this, the ZPL must 73168404Spjd * properly lock its in-core state, create a DMU transaction, do the work, 74168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction, 75168404Spjd * and wait the the intent log to commit if it's is a synchronous operation. 76168404Spjd * Morover, the vnode ops must work in both normal and log replay context. 77168404Spjd * The ordering of events is important to avoid deadlocks and references 78168404Spjd * to freed memory. The example below illustrates the following Big Rules: 79168404Spjd * 80168404Spjd * (1) A check must be made in each zfs thread for a mounted file system. 81168404Spjd * This is done avoiding races using ZFS_ENTER(zfsvfs). 82168404Spjd * A ZFS_EXIT(zfsvfs) is needed before all returns. 83168404Spjd * 84168404Spjd * (2) VN_RELE() should always be the last thing except for zil_commit() 85168404Spjd * (if necessary) and ZFS_EXIT(). This is for 3 reasons: 86168404Spjd * First, if it's the last reference, the vnode/znode 87168404Spjd * can be freed, so the zp may point to freed memory. Second, the last 88168404Spjd * reference will call zfs_zinactive(), which may induce a lot of work -- 89168404Spjd * pushing cached pages (which acquires range locks) and syncing out 90168404Spjd * cached atime changes. Third, zfs_zinactive() may require a new tx, 91168404Spjd * which could deadlock the system if you were already holding one. 92168404Spjd * 93168404Spjd * (3) All range locks must be grabbed before calling dmu_tx_assign(), 94168404Spjd * as they can span dmu_tx_assign() calls. 95168404Spjd * 96168404Spjd * (4) Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign(). 97168404Spjd * In normal operation, this will be TXG_NOWAIT. During ZIL replay, 98168404Spjd * it will be a specific txg. Either way, dmu_tx_assign() never blocks. 99168404Spjd * This is critical because we don't want to block while holding locks. 100168404Spjd * Note, in particular, that if a lock is sometimes acquired before 101168404Spjd * the tx assigns, and sometimes after (e.g. z_lock), then failing to 102168404Spjd * use a non-blocking assign can deadlock the system. The scenario: 103168404Spjd * 104168404Spjd * Thread A has grabbed a lock before calling dmu_tx_assign(). 105168404Spjd * Thread B is in an already-assigned tx, and blocks for this lock. 106168404Spjd * Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open() 107168404Spjd * forever, because the previous txg can't quiesce until B's tx commits. 108168404Spjd * 109168404Spjd * If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT, 110168404Spjd * then drop all locks, call dmu_tx_wait(), and try again. 111168404Spjd * 112168404Spjd * (5) If the operation succeeded, generate the intent log entry for it 113168404Spjd * before dropping locks. This ensures that the ordering of events 114168404Spjd * in the intent log matches the order in which they actually occurred. 115168404Spjd * 116168404Spjd * (6) At the end of each vnode op, the DMU tx must always commit, 117168404Spjd * regardless of whether there were any errors. 118168404Spjd * 119168404Spjd * (7) After dropping all locks, invoke zil_commit(zilog, seq, foid) 120168404Spjd * to ensure that synchronous semantics are provided when necessary. 121168404Spjd * 122168404Spjd * In general, this is how things should be ordered in each vnode op: 123168404Spjd * 124168404Spjd * ZFS_ENTER(zfsvfs); // exit if unmounted 125168404Spjd * top: 126168404Spjd * zfs_dirent_lock(&dl, ...) // lock directory entry (may VN_HOLD()) 127168404Spjd * rw_enter(...); // grab any other locks you need 128168404Spjd * tx = dmu_tx_create(...); // get DMU tx 129168404Spjd * dmu_tx_hold_*(); // hold each object you might modify 130168404Spjd * error = dmu_tx_assign(tx, zfsvfs->z_assign); // try to assign 131168404Spjd * if (error) { 132168404Spjd * rw_exit(...); // drop locks 133168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 134168404Spjd * VN_RELE(...); // release held vnodes 135168404Spjd * if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 136168404Spjd * dmu_tx_wait(tx); 137168404Spjd * dmu_tx_abort(tx); 138168404Spjd * goto top; 139168404Spjd * } 140168404Spjd * dmu_tx_abort(tx); // abort DMU tx 141168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 142168404Spjd * return (error); // really out of space 143168404Spjd * } 144168404Spjd * error = do_real_work(); // do whatever this VOP does 145168404Spjd * if (error == 0) 146168404Spjd * zfs_log_*(...); // on success, make ZIL entry 147168404Spjd * dmu_tx_commit(tx); // commit DMU tx -- error or not 148168404Spjd * rw_exit(...); // drop locks 149168404Spjd * zfs_dirent_unlock(dl); // unlock directory entry 150168404Spjd * VN_RELE(...); // release held vnodes 151168404Spjd * zil_commit(zilog, seq, foid); // synchronous when necessary 152168404Spjd * ZFS_EXIT(zfsvfs); // finished in zfs 153168404Spjd * return (error); // done, report error 154168404Spjd */ 155168404Spjd/* ARGSUSED */ 156168404Spjdstatic int 157168962Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr) 158168404Spjd{ 159168962Spjd znode_t *zp = VTOZ(*vpp); 160168404Spjd 161168404Spjd /* Keep a count of the synchronous opens in the znode */ 162168962Spjd if (flag & (FSYNC | FDSYNC)) 163168404Spjd atomic_inc_32(&zp->z_sync_cnt); 164168404Spjd return (0); 165168404Spjd} 166168404Spjd 167168404Spjd/* ARGSUSED */ 168168404Spjdstatic int 169168962Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) 170168404Spjd{ 171168962Spjd znode_t *zp = VTOZ(vp); 172168404Spjd 173168404Spjd /* Decrement the synchronous opens in the znode */ 174168962Spjd if (flag & (FSYNC | FDSYNC)) 175168404Spjd atomic_dec_32(&zp->z_sync_cnt); 176168404Spjd 177168962Spjd /* 178168962Spjd * Clean up any locks held by this process on the vp. 179168962Spjd */ 180168962Spjd cleanlocks(vp, ddi_get_pid(), 0); 181168962Spjd cleanshares(vp, ddi_get_pid()); 182168962Spjd 183168404Spjd return (0); 184168404Spjd} 185168404Spjd 186168404Spjd/* 187168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and 188168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. 189168404Spjd */ 190168404Spjdstatic int 191168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off) 192168404Spjd{ 193168404Spjd znode_t *zp = VTOZ(vp); 194168404Spjd uint64_t noff = (uint64_t)*off; /* new offset */ 195168404Spjd uint64_t file_sz; 196168404Spjd int error; 197168404Spjd boolean_t hole; 198168404Spjd 199168404Spjd file_sz = zp->z_phys->zp_size; 200168404Spjd if (noff >= file_sz) { 201168404Spjd return (ENXIO); 202168404Spjd } 203168404Spjd 204168962Spjd if (cmd == _FIO_SEEK_HOLE) 205168404Spjd hole = B_TRUE; 206168404Spjd else 207168404Spjd hole = B_FALSE; 208168404Spjd 209168404Spjd error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); 210168404Spjd 211168404Spjd /* end of file? */ 212168404Spjd if ((error == ESRCH) || (noff > file_sz)) { 213168404Spjd /* 214168404Spjd * Handle the virtual hole at the end of file. 215168404Spjd */ 216168404Spjd if (hole) { 217168404Spjd *off = file_sz; 218168404Spjd return (0); 219168404Spjd } 220168404Spjd return (ENXIO); 221168404Spjd } 222168404Spjd 223168404Spjd if (noff < *off) 224168404Spjd return (error); 225168404Spjd *off = noff; 226168404Spjd return (error); 227168404Spjd} 228168404Spjd 229168404Spjd/* ARGSUSED */ 230168404Spjdstatic int 231168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred, 232168962Spjd int *rvalp) 233168404Spjd{ 234168962Spjd offset_t off; 235168962Spjd int error; 236168962Spjd zfsvfs_t *zfsvfs; 237168404Spjd 238168404Spjd switch (com) { 239168962Spjd case _FIOFFS: 240168962Spjd return (0); 241168404Spjd 242168962Spjd /* 243168962Spjd * The following two ioctls are used by bfu. Faking out, 244168962Spjd * necessary to avoid bfu errors. 245168962Spjd */ 246168962Spjd case _FIOGDIO: 247168962Spjd case _FIOSDIO: 248168962Spjd return (0); 249168962Spjd 250168962Spjd case _FIO_SEEK_DATA: 251168962Spjd case _FIO_SEEK_HOLE: 252168962Spjd if (ddi_copyin((void *)data, &off, sizeof (off), flag)) 253168962Spjd return (EFAULT); 254168962Spjd 255168404Spjd zfsvfs = VTOZ(vp)->z_zfsvfs; 256168404Spjd ZFS_ENTER(zfsvfs); 257168404Spjd 258168404Spjd /* offset parameter is in/out */ 259168404Spjd error = zfs_holey(vp, com, &off); 260168404Spjd ZFS_EXIT(zfsvfs); 261168404Spjd if (error) 262168404Spjd return (error); 263168962Spjd if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) 264168962Spjd return (EFAULT); 265168404Spjd return (0); 266168404Spjd } 267168404Spjd return (ENOTTY); 268168404Spjd} 269168404Spjd 270168404Spjd/* 271168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 272168404Spjd * between the DMU cache and the memory mapped pages. What this means: 273168404Spjd * 274168404Spjd * On Write: If we find a memory mapped page, we write to *both* 275168404Spjd * the page and the dmu buffer. 276168404Spjd * 277168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 278168404Spjd * the file is memory mapped. 279168404Spjd */ 280168404Spjdstatic int 281168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) 282168404Spjd{ 283168404Spjd znode_t *zp = VTOZ(vp); 284168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 285168404Spjd vm_object_t obj; 286168404Spjd vm_page_t m; 287168404Spjd struct sf_buf *sf; 288168404Spjd int64_t start, off; 289168404Spjd int len = nbytes; 290168404Spjd int error = 0; 291169059Spjd uint64_t dirbytes; 292168404Spjd 293168404Spjd ASSERT(vp->v_mount != NULL); 294168404Spjd obj = vp->v_object; 295168404Spjd ASSERT(obj != NULL); 296168404Spjd 297168404Spjd start = uio->uio_loffset; 298168404Spjd off = start & PAGEOFFSET; 299169059Spjd dirbytes = 0; 300168404Spjd VM_OBJECT_LOCK(obj); 301168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 302168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 303169059Spjd uint64_t fsize; 304168404Spjd 305168404Spjdagain: 306168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 307168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 308169059Spjd uint64_t woff; 309168404Spjd caddr_t va; 310168404Spjd 311168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) 312168404Spjd goto again; 313169059Spjd fsize = obj->un_pager.vnp.vnp_size; 314168404Spjd vm_page_busy(m); 315169057Spjd vm_page_lock_queues(); 316169057Spjd vm_page_undirty(m); 317169057Spjd vm_page_unlock_queues(); 318168404Spjd VM_OBJECT_UNLOCK(obj); 319169059Spjd if (dirbytes > 0) { 320169059Spjd error = dmu_write_uio(os, zp->z_id, uio, 321169059Spjd dirbytes, tx); 322169059Spjd dirbytes = 0; 323169059Spjd } 324169059Spjd if (error == 0) { 325169059Spjd sched_pin(); 326169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 327169059Spjd va = (caddr_t)sf_buf_kva(sf); 328169059Spjd woff = uio->uio_loffset - off; 329169059Spjd error = uiomove(va + off, bytes, UIO_WRITE, uio); 330169167Spjd /* 331169167Spjd * The uiomove() above could have been partially 332169167Spjd * successful, that's why we call dmu_write() 333169167Spjd * below unconditionally. The page was marked 334169167Spjd * non-dirty above and we would lose the changes 335169167Spjd * without doing so. If the uiomove() failed 336169167Spjd * entirely, well, we just write what we got 337169167Spjd * before one more time. 338169167Spjd */ 339169059Spjd dmu_write(os, zp->z_id, woff, 340169059Spjd MIN(PAGESIZE, fsize - woff), va, tx); 341169059Spjd sf_buf_free(sf); 342169059Spjd sched_unpin(); 343169059Spjd } 344168404Spjd VM_OBJECT_LOCK(obj); 345168404Spjd vm_page_wakeup(m); 346168404Spjd } else { 347169059Spjd dirbytes += bytes; 348168404Spjd } 349168404Spjd len -= bytes; 350168404Spjd off = 0; 351168404Spjd if (error) 352168404Spjd break; 353168404Spjd } 354168404Spjd VM_OBJECT_UNLOCK(obj); 355169059Spjd if (error == 0 && dirbytes > 0) 356169059Spjd error = dmu_write_uio(os, zp->z_id, uio, dirbytes, tx); 357168404Spjd return (error); 358168404Spjd} 359168404Spjd 360168404Spjd/* 361168404Spjd * When a file is memory mapped, we must keep the IO data synchronized 362168404Spjd * between the DMU cache and the memory mapped pages. What this means: 363168404Spjd * 364168404Spjd * On Read: We "read" preferentially from memory mapped pages, 365168404Spjd * else we default from the dmu buffer. 366168404Spjd * 367168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when 368168404Spjd * the file is memory mapped. 369168404Spjd */ 370168404Spjdstatic int 371168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio) 372168404Spjd{ 373168404Spjd znode_t *zp = VTOZ(vp); 374168404Spjd objset_t *os = zp->z_zfsvfs->z_os; 375168404Spjd vm_object_t obj; 376168404Spjd vm_page_t m; 377168404Spjd struct sf_buf *sf; 378168404Spjd int64_t start, off; 379168926Spjd caddr_t va; 380168404Spjd int len = nbytes; 381168404Spjd int error = 0; 382169059Spjd uint64_t dirbytes; 383168404Spjd 384168404Spjd ASSERT(vp->v_mount != NULL); 385168404Spjd obj = vp->v_object; 386168404Spjd ASSERT(obj != NULL); 387168404Spjd 388168404Spjd start = uio->uio_loffset; 389168404Spjd off = start & PAGEOFFSET; 390169059Spjd dirbytes = 0; 391168404Spjd VM_OBJECT_LOCK(obj); 392168404Spjd for (start &= PAGEMASK; len > 0; start += PAGESIZE) { 393168404Spjd uint64_t bytes = MIN(PAGESIZE - off, len); 394168404Spjd 395168404Spjdagain: 396168404Spjd if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && 397168404Spjd vm_page_is_valid(m, (vm_offset_t)off, bytes)) { 398168404Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 399168404Spjd goto again; 400168404Spjd vm_page_busy(m); 401168404Spjd VM_OBJECT_UNLOCK(obj); 402169059Spjd if (dirbytes > 0) { 403169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 404169059Spjd dirbytes); 405169059Spjd dirbytes = 0; 406169059Spjd } 407169059Spjd if (error == 0) { 408169059Spjd sched_pin(); 409169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 410169059Spjd va = (caddr_t)sf_buf_kva(sf); 411169059Spjd error = uiomove(va + off, bytes, UIO_READ, uio); 412169059Spjd sf_buf_free(sf); 413169059Spjd sched_unpin(); 414169059Spjd } 415168404Spjd VM_OBJECT_LOCK(obj); 416168404Spjd vm_page_wakeup(m); 417168926Spjd } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { 418168962Spjd /* 419168962Spjd * The code below is here to make sendfile(2) work 420168962Spjd * correctly with ZFS. As pointed out by ups@ 421168962Spjd * sendfile(2) should be changed to use VOP_GETPAGES(), 422168962Spjd * but it pessimize performance of sendfile/UFS, that's 423168962Spjd * why I handle this special case in ZFS code. 424168962Spjd */ 425168926Spjd if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) 426168926Spjd goto again; 427168926Spjd vm_page_busy(m); 428168926Spjd VM_OBJECT_UNLOCK(obj); 429169059Spjd if (dirbytes > 0) { 430169059Spjd error = dmu_read_uio(os, zp->z_id, uio, 431169059Spjd dirbytes); 432169059Spjd dirbytes = 0; 433169059Spjd } 434169059Spjd if (error == 0) { 435169059Spjd sched_pin(); 436169059Spjd sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 437169059Spjd va = (caddr_t)sf_buf_kva(sf); 438169059Spjd error = dmu_read(os, zp->z_id, start + off, 439169059Spjd bytes, (void *)(va + off)); 440169059Spjd sf_buf_free(sf); 441169059Spjd sched_unpin(); 442169059Spjd } 443168926Spjd VM_OBJECT_LOCK(obj); 444168926Spjd vm_page_wakeup(m); 445169059Spjd if (error == 0) 446169059Spjd uio->uio_resid -= bytes; 447168404Spjd } else { 448169059Spjd dirbytes += bytes; 449168404Spjd } 450168404Spjd len -= bytes; 451168404Spjd off = 0; 452168404Spjd if (error) 453168404Spjd break; 454168404Spjd } 455168404Spjd VM_OBJECT_UNLOCK(obj); 456169059Spjd if (error == 0 && dirbytes > 0) 457169059Spjd error = dmu_read_uio(os, zp->z_id, uio, dirbytes); 458168404Spjd return (error); 459168404Spjd} 460168404Spjd 461168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */ 462168404Spjd 463168404Spjd/* 464168404Spjd * Read bytes from specified file into supplied buffer. 465168404Spjd * 466168404Spjd * IN: vp - vnode of file to be read from. 467168404Spjd * uio - structure supplying read location, range info, 468168404Spjd * and return buffer. 469168404Spjd * ioflag - SYNC flags; used to provide FRSYNC semantics. 470168404Spjd * cr - credentials of caller. 471168404Spjd * 472168404Spjd * OUT: uio - updated offset and range, buffer filled. 473168404Spjd * 474168404Spjd * RETURN: 0 if success 475168404Spjd * error code if failure 476168404Spjd * 477168404Spjd * Side Effects: 478168404Spjd * vp - atime updated if byte count > 0 479168404Spjd */ 480168404Spjd/* ARGSUSED */ 481168404Spjdstatic int 482168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 483168404Spjd{ 484168404Spjd znode_t *zp = VTOZ(vp); 485168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 486168404Spjd objset_t *os = zfsvfs->z_os; 487168404Spjd ssize_t n, nbytes; 488168404Spjd int error; 489168404Spjd rl_t *rl; 490168404Spjd 491168404Spjd ZFS_ENTER(zfsvfs); 492168404Spjd 493168404Spjd /* 494168404Spjd * Validate file offset 495168404Spjd */ 496168404Spjd if (uio->uio_loffset < (offset_t)0) { 497168404Spjd ZFS_EXIT(zfsvfs); 498168404Spjd return (EINVAL); 499168404Spjd } 500168404Spjd 501168404Spjd /* 502168404Spjd * Fasttrack empty reads 503168404Spjd */ 504168404Spjd if (uio->uio_resid == 0) { 505168404Spjd ZFS_EXIT(zfsvfs); 506168404Spjd return (0); 507168404Spjd } 508168404Spjd 509168404Spjd /* 510168962Spjd * Check for mandatory locks 511168962Spjd */ 512168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode)) { 513168962Spjd if (error = chklock(vp, FREAD, 514168962Spjd uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { 515168962Spjd ZFS_EXIT(zfsvfs); 516168962Spjd return (error); 517168962Spjd } 518168962Spjd } 519168962Spjd 520168962Spjd /* 521168404Spjd * If we're in FRSYNC mode, sync out this znode before reading it. 522168404Spjd */ 523168962Spjd if (ioflag & FRSYNC) 524168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 525168404Spjd 526168404Spjd /* 527168404Spjd * Lock the range against changes. 528168404Spjd */ 529168404Spjd rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER); 530168404Spjd 531168404Spjd /* 532168404Spjd * If we are reading past end-of-file we can skip 533168404Spjd * to the end; but we might still need to set atime. 534168404Spjd */ 535168404Spjd if (uio->uio_loffset >= zp->z_phys->zp_size) { 536168404Spjd error = 0; 537168404Spjd goto out; 538168404Spjd } 539168404Spjd 540168404Spjd ASSERT(uio->uio_loffset < zp->z_phys->zp_size); 541168404Spjd n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset); 542168404Spjd 543168404Spjd while (n > 0) { 544168404Spjd nbytes = MIN(n, zfs_read_chunk_size - 545168404Spjd P2PHASE(uio->uio_loffset, zfs_read_chunk_size)); 546168404Spjd 547168404Spjd if (vn_has_cached_data(vp)) 548168404Spjd error = mappedread(vp, nbytes, uio); 549168404Spjd else 550168404Spjd error = dmu_read_uio(os, zp->z_id, uio, nbytes); 551168404Spjd if (error) 552168404Spjd break; 553168962Spjd 554168404Spjd n -= nbytes; 555168404Spjd } 556168404Spjd 557168404Spjdout: 558168404Spjd zfs_range_unlock(rl); 559168404Spjd 560168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 561168404Spjd ZFS_EXIT(zfsvfs); 562168404Spjd return (error); 563168404Spjd} 564168404Spjd 565168404Spjd/* 566168404Spjd * Fault in the pages of the first n bytes specified by the uio structure. 567168404Spjd * 1 byte in each page is touched and the uio struct is unmodified. 568168404Spjd * Any error will exit this routine as this is only a best 569168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch(). 570168404Spjd */ 571168404Spjdstatic void 572168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio) 573168404Spjd{ 574168404Spjd struct iovec *iov; 575168404Spjd ulong_t cnt, incr; 576168404Spjd caddr_t p; 577168404Spjd 578168404Spjd if (uio->uio_segflg != UIO_USERSPACE) 579168404Spjd return; 580168404Spjd 581168404Spjd iov = uio->uio_iov; 582168404Spjd 583168404Spjd while (n) { 584168404Spjd cnt = MIN(iov->iov_len, n); 585168404Spjd if (cnt == 0) { 586168404Spjd /* empty iov entry */ 587168404Spjd iov++; 588168404Spjd continue; 589168404Spjd } 590168404Spjd n -= cnt; 591168404Spjd /* 592168404Spjd * touch each page in this segment. 593168404Spjd */ 594168404Spjd p = iov->iov_base; 595168404Spjd while (cnt) { 596168404Spjd if (fubyte(p) == -1) 597168404Spjd return; 598168404Spjd incr = MIN(cnt, PAGESIZE); 599168404Spjd p += incr; 600168404Spjd cnt -= incr; 601168404Spjd } 602168404Spjd /* 603168404Spjd * touch the last byte in case it straddles a page. 604168404Spjd */ 605168404Spjd p--; 606168404Spjd if (fubyte(p) == -1) 607168404Spjd return; 608168404Spjd iov++; 609168404Spjd } 610168404Spjd} 611168404Spjd 612168404Spjd/* 613168404Spjd * Write the bytes to a file. 614168404Spjd * 615168404Spjd * IN: vp - vnode of file to be written to. 616168404Spjd * uio - structure supplying write location, range info, 617168404Spjd * and data buffer. 618168404Spjd * ioflag - IO_APPEND flag set if in append mode. 619168404Spjd * cr - credentials of caller. 620168404Spjd * 621168404Spjd * OUT: uio - updated offset and range. 622168404Spjd * 623168404Spjd * RETURN: 0 if success 624168404Spjd * error code if failure 625168404Spjd * 626168404Spjd * Timestamps: 627168404Spjd * vp - ctime|mtime updated if byte count > 0 628168404Spjd */ 629168404Spjd/* ARGSUSED */ 630168404Spjdstatic int 631168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) 632168404Spjd{ 633168404Spjd znode_t *zp = VTOZ(vp); 634168962Spjd rlim64_t limit = MAXOFFSET_T; 635168404Spjd ssize_t start_resid = uio->uio_resid; 636168404Spjd ssize_t tx_bytes; 637168404Spjd uint64_t end_size; 638168404Spjd dmu_tx_t *tx; 639168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 640168404Spjd zilog_t *zilog = zfsvfs->z_log; 641168404Spjd offset_t woff; 642168404Spjd ssize_t n, nbytes; 643168404Spjd rl_t *rl; 644168404Spjd int max_blksz = zfsvfs->z_max_blksz; 645168404Spjd int error; 646168404Spjd 647168404Spjd /* 648168404Spjd * Fasttrack empty write 649168404Spjd */ 650168404Spjd n = start_resid; 651168404Spjd if (n == 0) 652168404Spjd return (0); 653168404Spjd 654168962Spjd if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 655168962Spjd limit = MAXOFFSET_T; 656168962Spjd 657168404Spjd ZFS_ENTER(zfsvfs); 658168404Spjd 659168404Spjd /* 660168404Spjd * Pre-fault the pages to ensure slow (eg NFS) pages 661168404Spjd * don't hold up txg. 662168404Spjd */ 663168404Spjd zfs_prefault_write(n, uio); 664168404Spjd 665168404Spjd /* 666168404Spjd * If in append mode, set the io offset pointer to eof. 667168404Spjd */ 668168404Spjd if (ioflag & IO_APPEND) { 669168404Spjd /* 670168404Spjd * Range lock for a file append: 671168404Spjd * The value for the start of range will be determined by 672168404Spjd * zfs_range_lock() (to guarantee append semantics). 673168404Spjd * If this write will cause the block size to increase, 674168404Spjd * zfs_range_lock() will lock the entire file, so we must 675168404Spjd * later reduce the range after we grow the block size. 676168404Spjd */ 677168404Spjd rl = zfs_range_lock(zp, 0, n, RL_APPEND); 678168404Spjd if (rl->r_len == UINT64_MAX) { 679168404Spjd /* overlocked, zp_size can't change */ 680168404Spjd woff = uio->uio_loffset = zp->z_phys->zp_size; 681168404Spjd } else { 682168404Spjd woff = uio->uio_loffset = rl->r_off; 683168404Spjd } 684168404Spjd } else { 685168404Spjd woff = uio->uio_loffset; 686168404Spjd /* 687168404Spjd * Validate file offset 688168404Spjd */ 689168404Spjd if (woff < 0) { 690168404Spjd ZFS_EXIT(zfsvfs); 691168404Spjd return (EINVAL); 692168404Spjd } 693168404Spjd 694168404Spjd /* 695168404Spjd * If we need to grow the block size then zfs_range_lock() 696168404Spjd * will lock a wider range than we request here. 697168404Spjd * Later after growing the block size we reduce the range. 698168404Spjd */ 699168404Spjd rl = zfs_range_lock(zp, woff, n, RL_WRITER); 700168404Spjd } 701168404Spjd 702168962Spjd if (woff >= limit) { 703168962Spjd zfs_range_unlock(rl); 704168962Spjd ZFS_EXIT(zfsvfs); 705168962Spjd return (EFBIG); 706168962Spjd } 707168962Spjd 708168962Spjd if ((woff + n) > limit || woff > (limit - n)) 709168962Spjd n = limit - woff; 710168962Spjd 711168962Spjd /* 712168962Spjd * Check for mandatory locks 713168962Spjd */ 714168962Spjd if (MANDMODE((mode_t)zp->z_phys->zp_mode) && 715168962Spjd (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { 716168962Spjd zfs_range_unlock(rl); 717168962Spjd ZFS_EXIT(zfsvfs); 718168962Spjd return (error); 719168962Spjd } 720168404Spjd end_size = MAX(zp->z_phys->zp_size, woff + n); 721168404Spjd 722168404Spjd /* 723168404Spjd * Write the file in reasonable size chunks. Each chunk is written 724168404Spjd * in a separate transaction; this keeps the intent log records small 725168404Spjd * and allows us to do more fine-grained space accounting. 726168404Spjd */ 727168404Spjd while (n > 0) { 728168404Spjd /* 729168404Spjd * Start a transaction. 730168404Spjd */ 731168404Spjd woff = uio->uio_loffset; 732168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 733168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 734168404Spjd dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); 735168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 736168404Spjd if (error) { 737168404Spjd if (error == ERESTART && 738168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 739168404Spjd dmu_tx_wait(tx); 740168404Spjd dmu_tx_abort(tx); 741168404Spjd continue; 742168404Spjd } 743168404Spjd dmu_tx_abort(tx); 744168404Spjd break; 745168404Spjd } 746168404Spjd 747168404Spjd /* 748168404Spjd * If zfs_range_lock() over-locked we grow the blocksize 749168404Spjd * and then reduce the lock range. This will only happen 750168404Spjd * on the first iteration since zfs_range_reduce() will 751168404Spjd * shrink down r_len to the appropriate size. 752168404Spjd */ 753168404Spjd if (rl->r_len == UINT64_MAX) { 754168404Spjd uint64_t new_blksz; 755168404Spjd 756168404Spjd if (zp->z_blksz > max_blksz) { 757168404Spjd ASSERT(!ISP2(zp->z_blksz)); 758168404Spjd new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE); 759168404Spjd } else { 760168404Spjd new_blksz = MIN(end_size, max_blksz); 761168404Spjd } 762168404Spjd zfs_grow_blocksize(zp, new_blksz, tx); 763168404Spjd zfs_range_reduce(rl, woff, n); 764168404Spjd } 765168404Spjd 766168404Spjd /* 767168404Spjd * XXX - should we really limit each write to z_max_blksz? 768168404Spjd * Perhaps we should use SPA_MAXBLOCKSIZE chunks? 769168404Spjd */ 770168404Spjd nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz)); 771168404Spjd rw_enter(&zp->z_map_lock, RW_READER); 772168404Spjd 773168404Spjd if (woff + nbytes > zp->z_phys->zp_size) 774168404Spjd vnode_pager_setsize(vp, woff + nbytes); 775168404Spjd 776168962Spjd tx_bytes = uio->uio_resid; 777168404Spjd if (vn_has_cached_data(vp)) { 778168404Spjd rw_exit(&zp->z_map_lock); 779168404Spjd error = mappedwrite(vp, nbytes, uio, tx); 780168404Spjd } else { 781168404Spjd error = dmu_write_uio(zfsvfs->z_os, zp->z_id, 782168404Spjd uio, nbytes, tx); 783168404Spjd rw_exit(&zp->z_map_lock); 784168404Spjd } 785168404Spjd tx_bytes -= uio->uio_resid; 786168404Spjd 787168404Spjd /* 788168404Spjd * If we made no progress, we're done. If we made even 789168404Spjd * partial progress, update the znode and ZIL accordingly. 790168404Spjd */ 791168404Spjd if (tx_bytes == 0) { 792168404Spjd dmu_tx_commit(tx); 793168404Spjd ASSERT(error != 0); 794168404Spjd break; 795168404Spjd } 796168404Spjd 797168404Spjd /* 798168404Spjd * Clear Set-UID/Set-GID bits on successful write if not 799168404Spjd * privileged and at least one of the excute bits is set. 800168404Spjd * 801168404Spjd * It would be nice to to this after all writes have 802168404Spjd * been done, but that would still expose the ISUID/ISGID 803168404Spjd * to another app after the partial write is committed. 804168404Spjd */ 805168404Spjd mutex_enter(&zp->z_acl_lock); 806168404Spjd if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) | 807168404Spjd (S_IXUSR >> 6))) != 0 && 808168404Spjd (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 && 809168404Spjd secpolicy_vnode_setid_retain(cr, 810168404Spjd (zp->z_phys->zp_mode & S_ISUID) != 0 && 811168404Spjd zp->z_phys->zp_uid == 0) != 0) { 812168404Spjd zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID); 813168404Spjd } 814168404Spjd mutex_exit(&zp->z_acl_lock); 815168404Spjd 816168404Spjd /* 817168404Spjd * Update time stamp. NOTE: This marks the bonus buffer as 818168404Spjd * dirty, so we don't have to do it again for zp_size. 819168404Spjd */ 820168404Spjd zfs_time_stamper(zp, CONTENT_MODIFIED, tx); 821168404Spjd 822168404Spjd /* 823168404Spjd * Update the file size (zp_size) if it has changed; 824168404Spjd * account for possible concurrent updates. 825168404Spjd */ 826168404Spjd while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset) 827168404Spjd (void) atomic_cas_64(&zp->z_phys->zp_size, end_size, 828168404Spjd uio->uio_loffset); 829168404Spjd zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); 830168404Spjd dmu_tx_commit(tx); 831168404Spjd 832168404Spjd if (error != 0) 833168404Spjd break; 834168404Spjd ASSERT(tx_bytes == nbytes); 835168404Spjd n -= nbytes; 836168404Spjd } 837168404Spjd 838168404Spjd zfs_range_unlock(rl); 839168404Spjd 840168404Spjd /* 841168404Spjd * If we're in replay mode, or we made no progress, return error. 842168404Spjd * Otherwise, it's at least a partial write, so it's successful. 843168404Spjd */ 844168404Spjd if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) { 845168404Spjd ZFS_EXIT(zfsvfs); 846168404Spjd return (error); 847168404Spjd } 848168404Spjd 849168962Spjd if (ioflag & (FSYNC | FDSYNC)) 850168404Spjd zil_commit(zilog, zp->z_last_itx, zp->z_id); 851168404Spjd 852168404Spjd ZFS_EXIT(zfsvfs); 853168404Spjd return (0); 854168404Spjd} 855168404Spjd 856168404Spjdvoid 857168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd) 858168404Spjd{ 859168404Spjd zgd_t *zgd = (zgd_t *)vzgd; 860168404Spjd rl_t *rl = zgd->zgd_rl; 861168404Spjd vnode_t *vp = ZTOV(rl->r_zp); 862168404Spjd int vfslocked; 863168404Spjd 864168404Spjd vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); 865168404Spjd dmu_buf_rele(db, vzgd); 866168404Spjd zfs_range_unlock(rl); 867168404Spjd VN_RELE(vp); 868168404Spjd zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp))); 869168404Spjd kmem_free(zgd, sizeof (zgd_t)); 870168404Spjd VFS_UNLOCK_GIANT(vfslocked); 871168404Spjd} 872168404Spjd 873168404Spjd/* 874168404Spjd * Get data to generate a TX_WRITE intent log record. 875168404Spjd */ 876168404Spjdint 877168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) 878168404Spjd{ 879168404Spjd zfsvfs_t *zfsvfs = arg; 880168404Spjd objset_t *os = zfsvfs->z_os; 881168404Spjd znode_t *zp; 882168404Spjd uint64_t off = lr->lr_offset; 883168404Spjd dmu_buf_t *db; 884168404Spjd rl_t *rl; 885168404Spjd zgd_t *zgd; 886168404Spjd int dlen = lr->lr_length; /* length of user data */ 887168404Spjd int error = 0; 888168404Spjd 889168404Spjd ASSERT(zio); 890168404Spjd ASSERT(dlen != 0); 891168404Spjd 892168404Spjd /* 893168404Spjd * Nothing to do if the file has been removed 894168404Spjd */ 895168404Spjd if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0) 896168404Spjd return (ENOENT); 897168404Spjd if (zp->z_unlinked) { 898168404Spjd VN_RELE(ZTOV(zp)); 899168404Spjd return (ENOENT); 900168404Spjd } 901168404Spjd 902168404Spjd /* 903168404Spjd * Write records come in two flavors: immediate and indirect. 904168404Spjd * For small writes it's cheaper to store the data with the 905168404Spjd * log record (immediate); for large writes it's cheaper to 906168404Spjd * sync the data and get a pointer to it (indirect) so that 907168404Spjd * we don't have to write the data twice. 908168404Spjd */ 909168404Spjd if (buf != NULL) { /* immediate write */ 910168404Spjd rl = zfs_range_lock(zp, off, dlen, RL_READER); 911168404Spjd /* test for truncation needs to be done while range locked */ 912168404Spjd if (off >= zp->z_phys->zp_size) { 913168404Spjd error = ENOENT; 914168404Spjd goto out; 915168404Spjd } 916168404Spjd VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf)); 917168404Spjd } else { /* indirect write */ 918168404Spjd uint64_t boff; /* block starting offset */ 919168404Spjd 920168404Spjd /* 921168404Spjd * Have to lock the whole block to ensure when it's 922168404Spjd * written out and it's checksum is being calculated 923168404Spjd * that no one can change the data. We need to re-check 924168404Spjd * blocksize after we get the lock in case it's changed! 925168404Spjd */ 926168404Spjd for (;;) { 927168404Spjd if (ISP2(zp->z_blksz)) { 928168404Spjd boff = P2ALIGN_TYPED(off, zp->z_blksz, 929168404Spjd uint64_t); 930168404Spjd } else { 931168404Spjd boff = 0; 932168404Spjd } 933168404Spjd dlen = zp->z_blksz; 934168404Spjd rl = zfs_range_lock(zp, boff, dlen, RL_READER); 935168404Spjd if (zp->z_blksz == dlen) 936168404Spjd break; 937168404Spjd zfs_range_unlock(rl); 938168404Spjd } 939168404Spjd /* test for truncation needs to be done while range locked */ 940168404Spjd if (off >= zp->z_phys->zp_size) { 941168404Spjd error = ENOENT; 942168404Spjd goto out; 943168404Spjd } 944168404Spjd zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP); 945168404Spjd zgd->zgd_rl = rl; 946168404Spjd zgd->zgd_zilog = zfsvfs->z_log; 947168404Spjd zgd->zgd_bp = &lr->lr_blkptr; 948168404Spjd VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db)); 949168404Spjd ASSERT(boff == db->db_offset); 950168404Spjd lr->lr_blkoff = off - boff; 951168404Spjd error = dmu_sync(zio, db, &lr->lr_blkptr, 952168404Spjd lr->lr_common.lrc_txg, zfs_get_done, zgd); 953168404Spjd ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz); 954168404Spjd if (error == 0) { 955168404Spjd zil_add_vdev(zfsvfs->z_log, 956168404Spjd DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr))); 957168404Spjd } 958168404Spjd /* 959168404Spjd * If we get EINPROGRESS, then we need to wait for a 960168404Spjd * write IO initiated by dmu_sync() to complete before 961168404Spjd * we can release this dbuf. We will finish everything 962168404Spjd * up in the zfs_get_done() callback. 963168404Spjd */ 964168404Spjd if (error == EINPROGRESS) 965168404Spjd return (0); 966168404Spjd dmu_buf_rele(db, zgd); 967168404Spjd kmem_free(zgd, sizeof (zgd_t)); 968168404Spjd } 969168404Spjdout: 970168404Spjd zfs_range_unlock(rl); 971168404Spjd VN_RELE(ZTOV(zp)); 972168404Spjd return (error); 973168404Spjd} 974168404Spjd 975168404Spjd/*ARGSUSED*/ 976168404Spjdstatic int 977168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr) 978168404Spjd{ 979168404Spjd znode_t *zp = VTOZ(vp); 980168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 981168404Spjd int error; 982168404Spjd 983168404Spjd ZFS_ENTER(zfsvfs); 984168962Spjd error = zfs_zaccess_rwx(zp, mode, cr); 985168404Spjd ZFS_EXIT(zfsvfs); 986168404Spjd return (error); 987168404Spjd} 988168404Spjd 989168404Spjd/* 990168404Spjd * Lookup an entry in a directory, or an extended attribute directory. 991168404Spjd * If it exists, return a held vnode reference for it. 992168404Spjd * 993168404Spjd * IN: dvp - vnode of directory to search. 994168404Spjd * nm - name of entry to lookup. 995168404Spjd * pnp - full pathname to lookup [UNUSED]. 996168404Spjd * flags - LOOKUP_XATTR set if looking for an attribute. 997168404Spjd * rdir - root directory vnode [UNUSED]. 998168404Spjd * cr - credentials of caller. 999168404Spjd * 1000168404Spjd * OUT: vpp - vnode of located entry, NULL if not found. 1001168404Spjd * 1002168404Spjd * RETURN: 0 if success 1003168404Spjd * error code if failure 1004168404Spjd * 1005168404Spjd * Timestamps: 1006168404Spjd * NA 1007168404Spjd */ 1008168404Spjd/* ARGSUSED */ 1009168962Spjdstatic int 1010168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, 1011168962Spjd int nameiop, cred_t *cr, kthread_t *td) 1012168404Spjd{ 1013168404Spjd 1014168962Spjd znode_t *zdp = VTOZ(dvp); 1015168962Spjd zfsvfs_t *zfsvfs = zdp->z_zfsvfs; 1016168962Spjd int error; 1017168404Spjd 1018168404Spjd ZFS_ENTER(zfsvfs); 1019168404Spjd 1020168404Spjd *vpp = NULL; 1021168404Spjd 1022168404Spjd#ifdef TODO 1023168404Spjd if (flags & LOOKUP_XATTR) { 1024168404Spjd /* 1025168404Spjd * If the xattr property is off, refuse the lookup request. 1026168404Spjd */ 1027168404Spjd if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) { 1028168404Spjd ZFS_EXIT(zfsvfs); 1029168404Spjd return (EINVAL); 1030168404Spjd } 1031168404Spjd 1032168404Spjd /* 1033168404Spjd * We don't allow recursive attributes.. 1034168404Spjd * Maybe someday we will. 1035168404Spjd */ 1036168404Spjd if (zdp->z_phys->zp_flags & ZFS_XATTR) { 1037168404Spjd ZFS_EXIT(zfsvfs); 1038168404Spjd return (EINVAL); 1039168404Spjd } 1040168404Spjd 1041168404Spjd if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) { 1042168404Spjd ZFS_EXIT(zfsvfs); 1043168404Spjd return (error); 1044168404Spjd } 1045168404Spjd 1046168404Spjd /* 1047168404Spjd * Do we have permission to get into attribute directory? 1048168404Spjd */ 1049168404Spjd 1050168404Spjd if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) { 1051168404Spjd VN_RELE(*vpp); 1052168404Spjd } 1053168404Spjd 1054168404Spjd ZFS_EXIT(zfsvfs); 1055168404Spjd return (error); 1056168404Spjd } 1057168404Spjd#endif /* TODO */ 1058168404Spjd 1059168404Spjd if (dvp->v_type != VDIR) { 1060168404Spjd ZFS_EXIT(zfsvfs); 1061168404Spjd return (ENOTDIR); 1062168404Spjd } 1063168404Spjd 1064168404Spjd /* 1065168404Spjd * Check accessibility of directory. 1066168404Spjd */ 1067168404Spjd 1068168404Spjd if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) { 1069168404Spjd ZFS_EXIT(zfsvfs); 1070168404Spjd return (error); 1071168404Spjd } 1072168404Spjd 1073168962Spjd if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) { 1074168404Spjd 1075168962Spjd /* 1076168962Spjd * Convert device special files 1077168962Spjd */ 1078168962Spjd if (IS_DEVVP(*vpp)) { 1079168962Spjd vnode_t *svp; 1080168962Spjd 1081168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1082168962Spjd VN_RELE(*vpp); 1083168962Spjd if (svp == NULL) 1084168962Spjd error = ENOSYS; 1085168962Spjd else 1086168962Spjd *vpp = svp; 1087168962Spjd } 1088168962Spjd } 1089168962Spjd 1090168404Spjd ZFS_EXIT(zfsvfs); 1091168404Spjd 1092168404Spjd /* Translate errors and add SAVENAME when needed. */ 1093168404Spjd if (cnp->cn_flags & ISLASTCN) { 1094168404Spjd switch (nameiop) { 1095168404Spjd case CREATE: 1096168404Spjd case RENAME: 1097168404Spjd if (error == ENOENT) { 1098168404Spjd error = EJUSTRETURN; 1099168404Spjd cnp->cn_flags |= SAVENAME; 1100168404Spjd break; 1101168404Spjd } 1102168404Spjd /* FALLTHROUGH */ 1103168404Spjd case DELETE: 1104168404Spjd if (error == 0) 1105168404Spjd cnp->cn_flags |= SAVENAME; 1106168404Spjd break; 1107168404Spjd } 1108168404Spjd } 1109168404Spjd if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) { 1110168962Spjd if (cnp->cn_flags & ISDOTDOT) 1111168404Spjd VOP_UNLOCK(dvp, 0, td); 1112168404Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 1113168962Spjd if (cnp->cn_flags & ISDOTDOT) 1114168404Spjd vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); 1115168404Spjd } 1116168404Spjd 1117168404Spjd#ifdef FREEBSD_NAMECACHE 1118168404Spjd /* 1119168404Spjd * Insert name into cache (as non-existent) if appropriate. 1120168404Spjd */ 1121168404Spjd if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 1122168404Spjd cache_enter(dvp, *vpp, cnp); 1123168404Spjd /* 1124168404Spjd * Insert name into cache if appropriate. 1125168404Spjd */ 1126168404Spjd if (error == 0 && (cnp->cn_flags & MAKEENTRY)) { 1127168404Spjd if (!(cnp->cn_flags & ISLASTCN) || 1128168404Spjd (nameiop != DELETE && nameiop != RENAME)) { 1129168404Spjd cache_enter(dvp, *vpp, cnp); 1130168404Spjd } 1131168404Spjd } 1132168404Spjd#endif 1133168404Spjd 1134168404Spjd return (error); 1135168404Spjd} 1136168404Spjd 1137168404Spjd/* 1138168404Spjd * Attempt to create a new entry in a directory. If the entry 1139168404Spjd * already exists, truncate the file if permissible, else return 1140168404Spjd * an error. Return the vp of the created or trunc'd file. 1141168404Spjd * 1142168404Spjd * IN: dvp - vnode of directory to put new file entry in. 1143168404Spjd * name - name of new file entry. 1144168404Spjd * vap - attributes of new file. 1145168404Spjd * excl - flag indicating exclusive or non-exclusive mode. 1146168404Spjd * mode - mode to open file with. 1147168404Spjd * cr - credentials of caller. 1148168404Spjd * flag - large file flag [UNUSED]. 1149168404Spjd * 1150168404Spjd * OUT: vpp - vnode of created or trunc'd entry. 1151168404Spjd * 1152168404Spjd * RETURN: 0 if success 1153168404Spjd * error code if failure 1154168404Spjd * 1155168404Spjd * Timestamps: 1156168404Spjd * dvp - ctime|mtime updated if new entry created 1157168404Spjd * vp - ctime|mtime always, atime if new 1158168404Spjd */ 1159168404Spjd/* ARGSUSED */ 1160168404Spjdstatic int 1161168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode, 1162168962Spjd vnode_t **vpp, cred_t *cr, kthread_t *td) 1163168404Spjd{ 1164168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1165168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1166168404Spjd zilog_t *zilog = zfsvfs->z_log; 1167168404Spjd objset_t *os = zfsvfs->z_os; 1168168404Spjd zfs_dirlock_t *dl; 1169168404Spjd dmu_tx_t *tx; 1170168404Spjd int error; 1171168404Spjd uint64_t zoid; 1172168404Spjd 1173168404Spjd ZFS_ENTER(zfsvfs); 1174168404Spjd 1175168404Spjdtop: 1176168404Spjd *vpp = NULL; 1177168404Spjd 1178168404Spjd if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr)) 1179168404Spjd vap->va_mode &= ~VSVTX; 1180168404Spjd 1181168404Spjd if (*name == '\0') { 1182168404Spjd /* 1183168404Spjd * Null component name refers to the directory itself. 1184168404Spjd */ 1185168404Spjd VN_HOLD(dvp); 1186168404Spjd zp = dzp; 1187168404Spjd dl = NULL; 1188168404Spjd error = 0; 1189168404Spjd } else { 1190168404Spjd /* possible VN_HOLD(zp) */ 1191168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) { 1192168404Spjd if (strcmp(name, "..") == 0) 1193168404Spjd error = EISDIR; 1194168404Spjd ZFS_EXIT(zfsvfs); 1195168404Spjd return (error); 1196168404Spjd } 1197168404Spjd } 1198168404Spjd 1199168404Spjd zoid = zp ? zp->z_id : -1ULL; 1200168404Spjd 1201168404Spjd if (zp == NULL) { 1202168404Spjd /* 1203168404Spjd * Create a new file object and update the directory 1204168404Spjd * to reference it. 1205168404Spjd */ 1206168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 1207168404Spjd goto out; 1208168404Spjd } 1209168404Spjd 1210168404Spjd /* 1211168404Spjd * We only support the creation of regular files in 1212168404Spjd * extended attribute directories. 1213168404Spjd */ 1214168404Spjd if ((dzp->z_phys->zp_flags & ZFS_XATTR) && 1215168404Spjd (vap->va_type != VREG)) { 1216168404Spjd error = EINVAL; 1217168404Spjd goto out; 1218168404Spjd } 1219168404Spjd 1220168404Spjd tx = dmu_tx_create(os); 1221168404Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1222168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 1223168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 1224168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1225168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1226168404Spjd 0, SPA_MAXBLOCKSIZE); 1227168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1228168404Spjd if (error) { 1229168404Spjd zfs_dirent_unlock(dl); 1230168404Spjd if (error == ERESTART && 1231168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1232168404Spjd dmu_tx_wait(tx); 1233168404Spjd dmu_tx_abort(tx); 1234168404Spjd goto top; 1235168404Spjd } 1236168404Spjd dmu_tx_abort(tx); 1237168404Spjd ZFS_EXIT(zfsvfs); 1238168404Spjd return (error); 1239168404Spjd } 1240168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1241168404Spjd ASSERT(zp->z_id == zoid); 1242168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1243168404Spjd zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name); 1244168404Spjd dmu_tx_commit(tx); 1245168404Spjd } else { 1246168404Spjd /* 1247168404Spjd * A directory entry already exists for this name. 1248168404Spjd */ 1249168404Spjd /* 1250168962Spjd * Can't truncate an existing file if in exclusive mode. 1251168962Spjd */ 1252168962Spjd if (excl == EXCL) { 1253168962Spjd error = EEXIST; 1254168962Spjd goto out; 1255168962Spjd } 1256168962Spjd /* 1257168404Spjd * Can't open a directory for writing. 1258168404Spjd */ 1259168404Spjd if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) { 1260168404Spjd error = EISDIR; 1261168404Spjd goto out; 1262168404Spjd } 1263168404Spjd /* 1264168404Spjd * Verify requested access to file. 1265168404Spjd */ 1266168404Spjd if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) { 1267168404Spjd goto out; 1268168404Spjd } 1269168404Spjd 1270168404Spjd mutex_enter(&dzp->z_lock); 1271168404Spjd dzp->z_seq++; 1272168404Spjd mutex_exit(&dzp->z_lock); 1273168404Spjd 1274168404Spjd /* 1275168404Spjd * Truncate regular files if requested. 1276168404Spjd */ 1277168404Spjd if ((ZTOV(zp)->v_type == VREG) && 1278168404Spjd (zp->z_phys->zp_size != 0) && 1279168404Spjd (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) { 1280168404Spjd error = zfs_freesp(zp, 0, 0, mode, TRUE); 1281168404Spjd if (error == ERESTART && 1282168404Spjd zfsvfs->z_assign == TXG_NOWAIT) { 1283168404Spjd /* NB: we already did dmu_tx_wait() */ 1284168404Spjd zfs_dirent_unlock(dl); 1285168404Spjd VN_RELE(ZTOV(zp)); 1286168404Spjd goto top; 1287168404Spjd } 1288168404Spjd } 1289168404Spjd } 1290168404Spjdout: 1291168404Spjd 1292168404Spjd if (error == 0) { 1293168404Spjd *vpp = ZTOV(zp); 1294168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 1295168404Spjd } 1296168404Spjd 1297168404Spjd if (dl) 1298168404Spjd zfs_dirent_unlock(dl); 1299168404Spjd 1300168404Spjd if (error) { 1301168404Spjd if (zp) 1302168404Spjd VN_RELE(ZTOV(zp)); 1303168962Spjd } else { 1304168962Spjd *vpp = ZTOV(zp); 1305168962Spjd /* 1306168962Spjd * If vnode is for a device return a specfs vnode instead. 1307168962Spjd */ 1308168962Spjd if (IS_DEVVP(*vpp)) { 1309168962Spjd struct vnode *svp; 1310168962Spjd 1311168962Spjd svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 1312168962Spjd VN_RELE(*vpp); 1313168962Spjd if (svp == NULL) { 1314168962Spjd error = ENOSYS; 1315168962Spjd } 1316168962Spjd *vpp = svp; 1317168962Spjd } 1318168404Spjd } 1319168404Spjd 1320168404Spjd ZFS_EXIT(zfsvfs); 1321168404Spjd return (error); 1322168404Spjd} 1323168404Spjd 1324168404Spjd/* 1325168404Spjd * Remove an entry from a directory. 1326168404Spjd * 1327168404Spjd * IN: dvp - vnode of directory to remove entry from. 1328168404Spjd * name - name of entry to remove. 1329168404Spjd * cr - credentials of caller. 1330168404Spjd * 1331168404Spjd * RETURN: 0 if success 1332168404Spjd * error code if failure 1333168404Spjd * 1334168404Spjd * Timestamps: 1335168404Spjd * dvp - ctime|mtime 1336168404Spjd * vp - ctime (if nlink > 0) 1337168404Spjd */ 1338168404Spjdstatic int 1339168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr) 1340168404Spjd{ 1341168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1342168404Spjd znode_t *xzp = NULL; 1343168404Spjd vnode_t *vp; 1344168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1345168404Spjd zilog_t *zilog = zfsvfs->z_log; 1346168962Spjd uint64_t acl_obj, xattr_obj; 1347168404Spjd zfs_dirlock_t *dl; 1348168404Spjd dmu_tx_t *tx; 1349168962Spjd boolean_t may_delete_now, delete_now = FALSE; 1350168404Spjd boolean_t unlinked; 1351168404Spjd int error; 1352168404Spjd 1353168404Spjd ZFS_ENTER(zfsvfs); 1354168404Spjd 1355168404Spjdtop: 1356168404Spjd /* 1357168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1358168404Spjd */ 1359168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1360168404Spjd ZFS_EXIT(zfsvfs); 1361168404Spjd return (error); 1362168404Spjd } 1363168404Spjd 1364168404Spjd vp = ZTOV(zp); 1365168404Spjd 1366168962Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1367168404Spjd goto out; 1368168962Spjd } 1369168404Spjd 1370168962Spjd /* 1371168962Spjd * Need to use rmdir for removing directories. 1372168962Spjd */ 1373168962Spjd if (vp->v_type == VDIR) { 1374168962Spjd error = EPERM; 1375168962Spjd goto out; 1376168962Spjd } 1377168962Spjd 1378168962Spjd vnevent_remove(vp); 1379168962Spjd 1380168404Spjd dnlc_remove(dvp, name); 1381168404Spjd 1382168962Spjd may_delete_now = FALSE; 1383168962Spjd 1384168404Spjd /* 1385168404Spjd * We may delete the znode now, or we may put it in the unlinked set; 1386168404Spjd * it depends on whether we're the last link, and on whether there are 1387168404Spjd * other holds on the vnode. So we dmu_tx_hold() the right things to 1388168404Spjd * allow for either case. 1389168404Spjd */ 1390168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1391168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1392168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1393168962Spjd if (may_delete_now) 1394168962Spjd dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END); 1395168404Spjd 1396168404Spjd /* are there any extended attributes? */ 1397168404Spjd if ((xattr_obj = zp->z_phys->zp_xattr) != 0) { 1398168404Spjd /* XXX - do we need this if we are deleting? */ 1399168404Spjd dmu_tx_hold_bonus(tx, xattr_obj); 1400168404Spjd } 1401168404Spjd 1402168962Spjd /* are there any additional acls */ 1403168962Spjd if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 && 1404168962Spjd may_delete_now) 1405168962Spjd dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); 1406168962Spjd 1407168404Spjd /* charge as an update -- would be nice not to charge at all */ 1408168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1409168404Spjd 1410168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1411168404Spjd if (error) { 1412168404Spjd zfs_dirent_unlock(dl); 1413168962Spjd VN_RELE(vp); 1414168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1415168404Spjd dmu_tx_wait(tx); 1416168404Spjd dmu_tx_abort(tx); 1417168404Spjd goto top; 1418168404Spjd } 1419168404Spjd dmu_tx_abort(tx); 1420168404Spjd ZFS_EXIT(zfsvfs); 1421168404Spjd return (error); 1422168404Spjd } 1423168404Spjd 1424168404Spjd /* 1425168404Spjd * Remove the directory entry. 1426168404Spjd */ 1427168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, &unlinked); 1428168404Spjd 1429168404Spjd if (error) { 1430168404Spjd dmu_tx_commit(tx); 1431168404Spjd goto out; 1432168404Spjd } 1433168404Spjd 1434168962Spjd if (0 && unlinked) { 1435168962Spjd VI_LOCK(vp); 1436168962Spjd delete_now = may_delete_now && 1437168962Spjd vp->v_count == 1 && !vn_has_cached_data(vp) && 1438168962Spjd zp->z_phys->zp_xattr == xattr_obj && 1439168962Spjd zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj; 1440168962Spjd VI_UNLOCK(vp); 1441168962Spjd } 1442168962Spjd 1443168962Spjd if (delete_now) { 1444168962Spjd if (zp->z_phys->zp_xattr) { 1445168962Spjd error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp); 1446168962Spjd ASSERT3U(error, ==, 0); 1447168962Spjd ASSERT3U(xzp->z_phys->zp_links, ==, 2); 1448168962Spjd dmu_buf_will_dirty(xzp->z_dbuf, tx); 1449168962Spjd mutex_enter(&xzp->z_lock); 1450168962Spjd xzp->z_unlinked = 1; 1451168962Spjd xzp->z_phys->zp_links = 0; 1452168962Spjd mutex_exit(&xzp->z_lock); 1453168962Spjd zfs_unlinked_add(xzp, tx); 1454168962Spjd zp->z_phys->zp_xattr = 0; /* probably unnecessary */ 1455168962Spjd } 1456168962Spjd mutex_enter(&zp->z_lock); 1457168962Spjd VI_LOCK(vp); 1458168962Spjd vp->v_count--; 1459168962Spjd ASSERT3U(vp->v_count, ==, 0); 1460168962Spjd VI_UNLOCK(vp); 1461168962Spjd mutex_exit(&zp->z_lock); 1462168962Spjd zfs_znode_delete(zp, tx); 1463168962Spjd VFS_RELE(zfsvfs->z_vfs); 1464168962Spjd } else if (unlinked) { 1465168404Spjd zfs_unlinked_add(zp, tx); 1466168962Spjd } 1467168404Spjd 1468168404Spjd zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name); 1469168404Spjd 1470168404Spjd dmu_tx_commit(tx); 1471168404Spjdout: 1472168404Spjd zfs_dirent_unlock(dl); 1473168404Spjd 1474168962Spjd if (!delete_now) { 1475168962Spjd VN_RELE(vp); 1476168962Spjd } else if (xzp) { 1477168962Spjd /* this rele delayed to prevent nesting transactions */ 1478168962Spjd VN_RELE(ZTOV(xzp)); 1479168962Spjd } 1480168962Spjd 1481168404Spjd ZFS_EXIT(zfsvfs); 1482168404Spjd return (error); 1483168404Spjd} 1484168404Spjd 1485168404Spjd/* 1486168404Spjd * Create a new directory and insert it into dvp using the name 1487168404Spjd * provided. Return a pointer to the inserted directory. 1488168404Spjd * 1489168404Spjd * IN: dvp - vnode of directory to add subdir to. 1490168404Spjd * dirname - name of new directory. 1491168404Spjd * vap - attributes of new directory. 1492168404Spjd * cr - credentials of caller. 1493168404Spjd * 1494168404Spjd * OUT: vpp - vnode of created directory. 1495168404Spjd * 1496168404Spjd * RETURN: 0 if success 1497168404Spjd * error code if failure 1498168404Spjd * 1499168404Spjd * Timestamps: 1500168404Spjd * dvp - ctime|mtime updated 1501168404Spjd * vp - ctime|mtime|atime updated 1502168404Spjd */ 1503168404Spjdstatic int 1504168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr) 1505168404Spjd{ 1506168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 1507168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1508168404Spjd zilog_t *zilog = zfsvfs->z_log; 1509168404Spjd zfs_dirlock_t *dl; 1510168404Spjd uint64_t zoid = 0; 1511168404Spjd dmu_tx_t *tx; 1512168404Spjd int error; 1513168404Spjd 1514168404Spjd ASSERT(vap->va_type == VDIR); 1515168404Spjd 1516168404Spjd ZFS_ENTER(zfsvfs); 1517168404Spjd 1518168404Spjd if (dzp->z_phys->zp_flags & ZFS_XATTR) { 1519168404Spjd ZFS_EXIT(zfsvfs); 1520168404Spjd return (EINVAL); 1521168404Spjd } 1522168404Spjdtop: 1523168404Spjd *vpp = NULL; 1524168404Spjd 1525168404Spjd /* 1526168404Spjd * First make sure the new directory doesn't exist. 1527168404Spjd */ 1528168404Spjd if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) { 1529168404Spjd ZFS_EXIT(zfsvfs); 1530168404Spjd return (error); 1531168404Spjd } 1532168404Spjd 1533168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) { 1534168404Spjd zfs_dirent_unlock(dl); 1535168404Spjd ZFS_EXIT(zfsvfs); 1536168404Spjd return (error); 1537168404Spjd } 1538168404Spjd 1539168404Spjd /* 1540168404Spjd * Add a new entry to the directory. 1541168404Spjd */ 1542168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1543168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname); 1544168404Spjd dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); 1545168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 1546168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 1547168404Spjd 0, SPA_MAXBLOCKSIZE); 1548168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1549168404Spjd if (error) { 1550168404Spjd zfs_dirent_unlock(dl); 1551168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1552168404Spjd dmu_tx_wait(tx); 1553168404Spjd dmu_tx_abort(tx); 1554168404Spjd goto top; 1555168404Spjd } 1556168404Spjd dmu_tx_abort(tx); 1557168404Spjd ZFS_EXIT(zfsvfs); 1558168404Spjd return (error); 1559168404Spjd } 1560168404Spjd 1561168404Spjd /* 1562168404Spjd * Create new node. 1563168404Spjd */ 1564168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 1565168404Spjd 1566168404Spjd /* 1567168404Spjd * Now put new name in parent dir. 1568168404Spjd */ 1569168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 1570168404Spjd 1571168404Spjd *vpp = ZTOV(zp); 1572168404Spjd 1573168404Spjd zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname); 1574168404Spjd dmu_tx_commit(tx); 1575168404Spjd 1576168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread); 1577168404Spjd 1578168404Spjd zfs_dirent_unlock(dl); 1579168404Spjd 1580168404Spjd ZFS_EXIT(zfsvfs); 1581168404Spjd return (0); 1582168404Spjd} 1583168404Spjd 1584168404Spjd/* 1585168404Spjd * Remove a directory subdir entry. If the current working 1586168404Spjd * directory is the same as the subdir to be removed, the 1587168404Spjd * remove will fail. 1588168404Spjd * 1589168404Spjd * IN: dvp - vnode of directory to remove from. 1590168404Spjd * name - name of directory to be removed. 1591168404Spjd * cwd - vnode of current working directory. 1592168404Spjd * cr - credentials of caller. 1593168404Spjd * 1594168404Spjd * RETURN: 0 if success 1595168404Spjd * error code if failure 1596168404Spjd * 1597168404Spjd * Timestamps: 1598168404Spjd * dvp - ctime|mtime updated 1599168404Spjd */ 1600168404Spjdstatic int 1601168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr) 1602168404Spjd{ 1603168404Spjd znode_t *dzp = VTOZ(dvp); 1604168404Spjd znode_t *zp; 1605168404Spjd vnode_t *vp; 1606168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1607168404Spjd zilog_t *zilog = zfsvfs->z_log; 1608168404Spjd zfs_dirlock_t *dl; 1609168404Spjd dmu_tx_t *tx; 1610168404Spjd int error; 1611168404Spjd 1612168962Spjd ZFS_ENTER(zfsvfs); 1613168404Spjd 1614168404Spjdtop: 1615168404Spjd zp = NULL; 1616168404Spjd 1617168404Spjd /* 1618168404Spjd * Attempt to lock directory; fail if entry doesn't exist. 1619168404Spjd */ 1620168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) { 1621168404Spjd ZFS_EXIT(zfsvfs); 1622168404Spjd return (error); 1623168404Spjd } 1624168404Spjd 1625168404Spjd vp = ZTOV(zp); 1626168404Spjd 1627168404Spjd if (error = zfs_zaccess_delete(dzp, zp, cr)) { 1628168404Spjd goto out; 1629168404Spjd } 1630168404Spjd 1631168962Spjd if (vp->v_type != VDIR) { 1632168962Spjd error = ENOTDIR; 1633168962Spjd goto out; 1634168962Spjd } 1635168962Spjd 1636168962Spjd if (vp == cwd) { 1637168962Spjd error = EINVAL; 1638168962Spjd goto out; 1639168962Spjd } 1640168962Spjd 1641168962Spjd vnevent_rmdir(vp); 1642168962Spjd 1643168404Spjd /* 1644168404Spjd * Grab a lock on the directory to make sure that noone is 1645168404Spjd * trying to add (or lookup) entries while we are removing it. 1646168404Spjd */ 1647168404Spjd rw_enter(&zp->z_name_lock, RW_WRITER); 1648168404Spjd 1649168404Spjd /* 1650168404Spjd * Grab a lock on the parent pointer to make sure we play well 1651168404Spjd * with the treewalk and directory rename code. 1652168404Spjd */ 1653168404Spjd rw_enter(&zp->z_parent_lock, RW_WRITER); 1654168404Spjd 1655168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1656168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); 1657168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 1658168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 1659168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 1660168404Spjd if (error) { 1661168404Spjd rw_exit(&zp->z_parent_lock); 1662168404Spjd rw_exit(&zp->z_name_lock); 1663168404Spjd zfs_dirent_unlock(dl); 1664168962Spjd VN_RELE(vp); 1665168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1666168404Spjd dmu_tx_wait(tx); 1667168404Spjd dmu_tx_abort(tx); 1668168404Spjd goto top; 1669168404Spjd } 1670168404Spjd dmu_tx_abort(tx); 1671168404Spjd ZFS_EXIT(zfsvfs); 1672168404Spjd return (error); 1673168404Spjd } 1674168404Spjd 1675168404Spjd#ifdef FREEBSD_NAMECACHE 1676168404Spjd cache_purge(dvp); 1677168404Spjd#endif 1678168404Spjd 1679168404Spjd error = zfs_link_destroy(dl, zp, tx, 0, NULL); 1680168404Spjd 1681168404Spjd if (error == 0) 1682168404Spjd zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name); 1683168404Spjd 1684168404Spjd dmu_tx_commit(tx); 1685168404Spjd 1686168404Spjd rw_exit(&zp->z_parent_lock); 1687168404Spjd rw_exit(&zp->z_name_lock); 1688168404Spjd#ifdef FREEBSD_NAMECACHE 1689168404Spjd cache_purge(vp); 1690168404Spjd#endif 1691168404Spjdout: 1692168404Spjd zfs_dirent_unlock(dl); 1693168404Spjd 1694168962Spjd VN_RELE(vp); 1695168962Spjd 1696168404Spjd ZFS_EXIT(zfsvfs); 1697168404Spjd return (error); 1698168404Spjd} 1699168404Spjd 1700168404Spjd/* 1701168404Spjd * Read as many directory entries as will fit into the provided 1702168404Spjd * buffer from the given directory cursor position (specified in 1703168404Spjd * the uio structure. 1704168404Spjd * 1705168404Spjd * IN: vp - vnode of directory to read. 1706168404Spjd * uio - structure supplying read location, range info, 1707168404Spjd * and return buffer. 1708168404Spjd * cr - credentials of caller. 1709168404Spjd * 1710168404Spjd * OUT: uio - updated offset and range, buffer filled. 1711168404Spjd * eofp - set to true if end-of-file detected. 1712168404Spjd * 1713168404Spjd * RETURN: 0 if success 1714168404Spjd * error code if failure 1715168404Spjd * 1716168404Spjd * Timestamps: 1717168404Spjd * vp - atime updated 1718168404Spjd * 1719168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero. 1720168404Spjd * This allows us to use the low range for "special" directory entries: 1721168404Spjd * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, 1722168404Spjd * we use the offset 2 for the '.zfs' directory. 1723168404Spjd */ 1724168404Spjd/* ARGSUSED */ 1725168404Spjdstatic int 1726168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies) 1727168404Spjd{ 1728168404Spjd znode_t *zp = VTOZ(vp); 1729168404Spjd iovec_t *iovp; 1730168404Spjd dirent64_t *odp; 1731168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1732168404Spjd objset_t *os; 1733168404Spjd caddr_t outbuf; 1734168404Spjd size_t bufsize; 1735168404Spjd zap_cursor_t zc; 1736168404Spjd zap_attribute_t zap; 1737168404Spjd uint_t bytes_wanted; 1738168404Spjd uint64_t offset; /* must be unsigned; checks for < 1 */ 1739168404Spjd int local_eof; 1740168404Spjd int outcount; 1741168404Spjd int error; 1742168404Spjd uint8_t prefetch; 1743168404Spjd uint8_t type; 1744168962Spjd int ncooks; 1745168962Spjd u_long *cooks = NULL; 1746168404Spjd 1747168404Spjd ZFS_ENTER(zfsvfs); 1748168404Spjd 1749168404Spjd /* 1750168404Spjd * If we are not given an eof variable, 1751168404Spjd * use a local one. 1752168404Spjd */ 1753168404Spjd if (eofp == NULL) 1754168404Spjd eofp = &local_eof; 1755168404Spjd 1756168404Spjd /* 1757168404Spjd * Check for valid iov_len. 1758168404Spjd */ 1759168404Spjd if (uio->uio_iov->iov_len <= 0) { 1760168404Spjd ZFS_EXIT(zfsvfs); 1761168404Spjd return (EINVAL); 1762168404Spjd } 1763168404Spjd 1764168404Spjd /* 1765168404Spjd * Quit if directory has been removed (posix) 1766168404Spjd */ 1767168404Spjd if ((*eofp = zp->z_unlinked) != 0) { 1768168404Spjd ZFS_EXIT(zfsvfs); 1769168404Spjd return (0); 1770168404Spjd } 1771168404Spjd 1772168404Spjd error = 0; 1773168404Spjd os = zfsvfs->z_os; 1774168404Spjd offset = uio->uio_loffset; 1775168404Spjd prefetch = zp->z_zn_prefetch; 1776168404Spjd 1777168404Spjd /* 1778168404Spjd * Initialize the iterator cursor. 1779168404Spjd */ 1780168404Spjd if (offset <= 3) { 1781168404Spjd /* 1782168404Spjd * Start iteration from the beginning of the directory. 1783168404Spjd */ 1784168404Spjd zap_cursor_init(&zc, os, zp->z_id); 1785168404Spjd } else { 1786168404Spjd /* 1787168404Spjd * The offset is a serialized cursor. 1788168404Spjd */ 1789168404Spjd zap_cursor_init_serialized(&zc, os, zp->z_id, offset); 1790168404Spjd } 1791168404Spjd 1792168404Spjd /* 1793168404Spjd * Get space to change directory entries into fs independent format. 1794168404Spjd */ 1795168404Spjd iovp = uio->uio_iov; 1796168404Spjd bytes_wanted = iovp->iov_len; 1797168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { 1798168404Spjd bufsize = bytes_wanted; 1799168404Spjd outbuf = kmem_alloc(bufsize, KM_SLEEP); 1800168404Spjd odp = (struct dirent64 *)outbuf; 1801168404Spjd } else { 1802168404Spjd bufsize = bytes_wanted; 1803168404Spjd odp = (struct dirent64 *)iovp->iov_base; 1804168404Spjd } 1805168404Spjd 1806168962Spjd if (ncookies != NULL) { 1807168404Spjd /* 1808168404Spjd * Minimum entry size is dirent size and 1 byte for a file name. 1809168404Spjd */ 1810168962Spjd ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1); 1811168962Spjd cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK); 1812168962Spjd *cookies = cooks; 1813168962Spjd *ncookies = ncooks; 1814168404Spjd } 1815168404Spjd 1816168404Spjd /* 1817168404Spjd * Transform to file-system independent format 1818168404Spjd */ 1819168404Spjd outcount = 0; 1820168404Spjd while (outcount < bytes_wanted) { 1821168404Spjd ino64_t objnum; 1822168404Spjd ushort_t reclen; 1823168404Spjd 1824168404Spjd /* 1825168404Spjd * Special case `.', `..', and `.zfs'. 1826168404Spjd */ 1827168404Spjd if (offset == 0) { 1828168404Spjd (void) strcpy(zap.za_name, "."); 1829168404Spjd objnum = zp->z_id; 1830169108Spjd type = DT_DIR; 1831168404Spjd } else if (offset == 1) { 1832168404Spjd (void) strcpy(zap.za_name, ".."); 1833168404Spjd objnum = zp->z_phys->zp_parent; 1834169108Spjd type = DT_DIR; 1835168404Spjd } else if (offset == 2 && zfs_show_ctldir(zp)) { 1836168404Spjd (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME); 1837168404Spjd objnum = ZFSCTL_INO_ROOT; 1838169108Spjd type = DT_DIR; 1839168404Spjd } else { 1840168404Spjd /* 1841168404Spjd * Grab next entry. 1842168404Spjd */ 1843168404Spjd if (error = zap_cursor_retrieve(&zc, &zap)) { 1844168404Spjd if ((*eofp = (error == ENOENT)) != 0) 1845168404Spjd break; 1846168404Spjd else 1847168404Spjd goto update; 1848168404Spjd } 1849168404Spjd 1850168404Spjd if (zap.za_integer_length != 8 || 1851168404Spjd zap.za_num_integers != 1) { 1852168404Spjd cmn_err(CE_WARN, "zap_readdir: bad directory " 1853168404Spjd "entry, obj = %lld, offset = %lld\n", 1854168404Spjd (u_longlong_t)zp->z_id, 1855168404Spjd (u_longlong_t)offset); 1856168404Spjd error = ENXIO; 1857168404Spjd goto update; 1858168404Spjd } 1859168404Spjd 1860168404Spjd objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); 1861168404Spjd /* 1862168404Spjd * MacOS X can extract the object type here such as: 1863168404Spjd * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1864168404Spjd */ 1865168404Spjd type = ZFS_DIRENT_TYPE(zap.za_first_integer); 1866168404Spjd } 1867168404Spjd reclen = DIRENT64_RECLEN(strlen(zap.za_name)); 1868168404Spjd 1869168404Spjd /* 1870168404Spjd * Will this entry fit in the buffer? 1871168404Spjd */ 1872168404Spjd if (outcount + reclen > bufsize) { 1873168404Spjd /* 1874168404Spjd * Did we manage to fit anything in the buffer? 1875168404Spjd */ 1876168404Spjd if (!outcount) { 1877168404Spjd error = EINVAL; 1878168404Spjd goto update; 1879168404Spjd } 1880168404Spjd break; 1881168404Spjd } 1882168404Spjd /* 1883168404Spjd * Add this entry: 1884168404Spjd */ 1885168404Spjd odp->d_ino = objnum; 1886168404Spjd odp->d_reclen = reclen; 1887168404Spjd odp->d_namlen = strlen(zap.za_name); 1888168404Spjd (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); 1889168404Spjd odp->d_type = type; 1890168404Spjd outcount += reclen; 1891168404Spjd odp = (dirent64_t *)((intptr_t)odp + reclen); 1892168404Spjd 1893168404Spjd ASSERT(outcount <= bufsize); 1894168404Spjd 1895168404Spjd /* Prefetch znode */ 1896168404Spjd if (prefetch) 1897168404Spjd dmu_prefetch(os, objnum, 0, 0); 1898168404Spjd 1899168404Spjd /* 1900168404Spjd * Move to the next entry, fill in the previous offset. 1901168404Spjd */ 1902168404Spjd if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) { 1903168404Spjd zap_cursor_advance(&zc); 1904168404Spjd offset = zap_cursor_serialize(&zc); 1905168404Spjd } else { 1906168404Spjd offset += 1; 1907168404Spjd } 1908168404Spjd 1909168962Spjd if (cooks != NULL) { 1910168962Spjd *cooks++ = offset; 1911168962Spjd ncooks--; 1912168962Spjd KASSERT(ncooks >= 0, ("ncookies=%d", ncooks)); 1913168404Spjd } 1914168404Spjd } 1915168404Spjd zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ 1916168404Spjd 1917168404Spjd /* Subtract unused cookies */ 1918168962Spjd if (ncookies != NULL) 1919168962Spjd *ncookies -= ncooks; 1920168404Spjd 1921168404Spjd if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { 1922168404Spjd iovp->iov_base += outcount; 1923168404Spjd iovp->iov_len -= outcount; 1924168404Spjd uio->uio_resid -= outcount; 1925168404Spjd } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) { 1926168404Spjd /* 1927168404Spjd * Reset the pointer. 1928168404Spjd */ 1929168404Spjd offset = uio->uio_loffset; 1930168404Spjd } 1931168404Spjd 1932168404Spjdupdate: 1933168404Spjd zap_cursor_fini(&zc); 1934168404Spjd if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1935168404Spjd kmem_free(outbuf, bufsize); 1936168404Spjd 1937168404Spjd if (error == ENOENT) 1938168404Spjd error = 0; 1939168404Spjd 1940168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 1941168404Spjd 1942168404Spjd uio->uio_loffset = offset; 1943168404Spjd ZFS_EXIT(zfsvfs); 1944169107Spjd if (error != 0 && cookies != NULL) { 1945168962Spjd free(*cookies, M_TEMP); 1946168962Spjd *cookies = NULL; 1947168962Spjd *ncookies = 0; 1948168404Spjd } 1949168404Spjd return (error); 1950168404Spjd} 1951168404Spjd 1952168404Spjdstatic int 1953168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr) 1954168404Spjd{ 1955168962Spjd znode_t *zp = VTOZ(vp); 1956168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1957168404Spjd 1958168404Spjd ZFS_ENTER(zfsvfs); 1959168404Spjd zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id); 1960168404Spjd ZFS_EXIT(zfsvfs); 1961168404Spjd return (0); 1962168404Spjd} 1963168404Spjd 1964168404Spjd/* 1965168404Spjd * Get the requested file attributes and place them in the provided 1966168404Spjd * vattr structure. 1967168404Spjd * 1968168404Spjd * IN: vp - vnode of file. 1969168404Spjd * vap - va_mask identifies requested attributes. 1970168404Spjd * flags - [UNUSED] 1971168404Spjd * cr - credentials of caller. 1972168404Spjd * 1973168404Spjd * OUT: vap - attribute values. 1974168404Spjd * 1975168404Spjd * RETURN: 0 (always succeeds) 1976168404Spjd */ 1977168404Spjd/* ARGSUSED */ 1978168404Spjdstatic int 1979168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 1980168404Spjd{ 1981168962Spjd znode_t *zp = VTOZ(vp); 1982168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1983168962Spjd znode_phys_t *pzp = zp->z_phys; 1984168962Spjd uint32_t blksize; 1985168962Spjd u_longlong_t nblocks; 1986168962Spjd int error; 1987168404Spjd 1988168404Spjd ZFS_ENTER(zfsvfs); 1989168404Spjd 1990168404Spjd /* 1991168404Spjd * Return all attributes. It's cheaper to provide the answer 1992168404Spjd * than to determine whether we were asked the question. 1993168404Spjd */ 1994168404Spjd mutex_enter(&zp->z_lock); 1995168404Spjd 1996168404Spjd vap->va_type = IFTOVT(pzp->zp_mode); 1997168404Spjd vap->va_mode = pzp->zp_mode & ~S_IFMT; 1998168404Spjd vap->va_uid = zp->z_phys->zp_uid; 1999168404Spjd vap->va_gid = zp->z_phys->zp_gid; 2000168404Spjd vap->va_nodeid = zp->z_id; 2001168404Spjd vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX); /* nlink_t limit! */ 2002168404Spjd vap->va_size = pzp->zp_size; 2003168404Spjd vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 2004168958Spjd vap->va_rdev = zfs_cmpldev(pzp->zp_rdev); 2005168404Spjd vap->va_seq = zp->z_seq; 2006168404Spjd vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */ 2007168404Spjd 2008168404Spjd ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime); 2009168404Spjd ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime); 2010168404Spjd ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime); 2011168404Spjd ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime); 2012168404Spjd 2013168404Spjd /* 2014168404Spjd * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES. 2015168404Spjd * Also, if we are the owner don't bother, since owner should 2016168404Spjd * always be allowed to read basic attributes of file. 2017168404Spjd */ 2018168404Spjd if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) && 2019168404Spjd (zp->z_phys->zp_uid != crgetuid(cr))) { 2020168404Spjd if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) { 2021168404Spjd mutex_exit(&zp->z_lock); 2022168404Spjd ZFS_EXIT(zfsvfs); 2023168404Spjd return (error); 2024168404Spjd } 2025168404Spjd } 2026168404Spjd 2027168404Spjd mutex_exit(&zp->z_lock); 2028168404Spjd 2029168404Spjd dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks); 2030168404Spjd vap->va_blksize = blksize; 2031168404Spjd vap->va_bytes = nblocks << 9; /* nblocks * 512 */ 2032168404Spjd 2033168404Spjd if (zp->z_blksz == 0) { 2034168404Spjd /* 2035168404Spjd * Block size hasn't been set; suggest maximal I/O transfers. 2036168404Spjd */ 2037168404Spjd vap->va_blksize = zfsvfs->z_max_blksz; 2038168404Spjd } 2039168404Spjd 2040168404Spjd ZFS_EXIT(zfsvfs); 2041168404Spjd return (0); 2042168404Spjd} 2043168404Spjd 2044168404Spjd/* 2045168404Spjd * Set the file attributes to the values contained in the 2046168404Spjd * vattr structure. 2047168404Spjd * 2048168404Spjd * IN: vp - vnode of file to be modified. 2049168404Spjd * vap - new attribute values. 2050168404Spjd * flags - ATTR_UTIME set if non-default time values provided. 2051168404Spjd * cr - credentials of caller. 2052168404Spjd * 2053168404Spjd * RETURN: 0 if success 2054168404Spjd * error code if failure 2055168404Spjd * 2056168404Spjd * Timestamps: 2057168404Spjd * vp - ctime updated, mtime updated if size changed. 2058168404Spjd */ 2059168404Spjd/* ARGSUSED */ 2060168404Spjdstatic int 2061168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 2062168962Spjd caller_context_t *ct) 2063168404Spjd{ 2064168962Spjd struct znode *zp = VTOZ(vp); 2065168404Spjd znode_phys_t *pzp = zp->z_phys; 2066168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2067168404Spjd zilog_t *zilog = zfsvfs->z_log; 2068168404Spjd dmu_tx_t *tx; 2069168404Spjd vattr_t oldva; 2070168962Spjd uint_t mask = vap->va_mask; 2071168404Spjd uint_t saved_mask; 2072168404Spjd int trim_mask = 0; 2073168404Spjd uint64_t new_mode; 2074168404Spjd znode_t *attrzp; 2075168404Spjd int need_policy = FALSE; 2076168404Spjd int err; 2077168404Spjd 2078168404Spjd if (mask == 0) 2079168404Spjd return (0); 2080168404Spjd 2081168962Spjd if (mask & AT_NOSET) 2082168962Spjd return (EINVAL); 2083168962Spjd 2084168404Spjd if (mask & AT_SIZE && vp->v_type == VDIR) 2085168404Spjd return (EISDIR); 2086168404Spjd 2087168404Spjd if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) 2088168404Spjd return (EINVAL); 2089168404Spjd 2090168404Spjd ZFS_ENTER(zfsvfs); 2091168404Spjd 2092168404Spjdtop: 2093168404Spjd attrzp = NULL; 2094168404Spjd 2095168404Spjd if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { 2096168404Spjd ZFS_EXIT(zfsvfs); 2097168404Spjd return (EROFS); 2098168404Spjd } 2099168404Spjd 2100168404Spjd /* 2101168404Spjd * First validate permissions 2102168404Spjd */ 2103168404Spjd 2104168404Spjd if (mask & AT_SIZE) { 2105168404Spjd err = zfs_zaccess(zp, ACE_WRITE_DATA, cr); 2106168404Spjd if (err) { 2107168404Spjd ZFS_EXIT(zfsvfs); 2108168404Spjd return (err); 2109168404Spjd } 2110168404Spjd /* 2111168404Spjd * XXX - Note, we are not providing any open 2112168404Spjd * mode flags here (like FNDELAY), so we may 2113168404Spjd * block if there are locks present... this 2114168404Spjd * should be addressed in openat(). 2115168404Spjd */ 2116168404Spjd do { 2117168404Spjd err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); 2118168404Spjd /* NB: we already did dmu_tx_wait() if necessary */ 2119168404Spjd } while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT); 2120168404Spjd if (err) { 2121168404Spjd ZFS_EXIT(zfsvfs); 2122168404Spjd return (err); 2123168404Spjd } 2124168404Spjd } 2125168404Spjd 2126168404Spjd if (mask & (AT_ATIME|AT_MTIME)) 2127168404Spjd need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr); 2128168404Spjd 2129168404Spjd if (mask & (AT_UID|AT_GID)) { 2130168404Spjd int idmask = (mask & (AT_UID|AT_GID)); 2131168404Spjd int take_owner; 2132168404Spjd int take_group; 2133168404Spjd 2134168404Spjd /* 2135168404Spjd * NOTE: even if a new mode is being set, 2136168404Spjd * we may clear S_ISUID/S_ISGID bits. 2137168404Spjd */ 2138168404Spjd 2139168404Spjd if (!(mask & AT_MODE)) 2140168404Spjd vap->va_mode = pzp->zp_mode; 2141168404Spjd 2142168404Spjd /* 2143168404Spjd * Take ownership or chgrp to group we are a member of 2144168404Spjd */ 2145168404Spjd 2146168404Spjd take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr)); 2147168404Spjd take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr); 2148168404Spjd 2149168404Spjd /* 2150168404Spjd * If both AT_UID and AT_GID are set then take_owner and 2151168404Spjd * take_group must both be set in order to allow taking 2152168404Spjd * ownership. 2153168404Spjd * 2154168404Spjd * Otherwise, send the check through secpolicy_vnode_setattr() 2155168404Spjd * 2156168404Spjd */ 2157168404Spjd 2158168404Spjd if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) || 2159168404Spjd ((idmask == AT_UID) && take_owner) || 2160168404Spjd ((idmask == AT_GID) && take_group)) { 2161168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) { 2162168404Spjd /* 2163168404Spjd * Remove setuid/setgid for non-privileged users 2164168404Spjd */ 2165168404Spjd secpolicy_setid_clear(vap, cr); 2166168404Spjd trim_mask = (mask & (AT_UID|AT_GID)); 2167168404Spjd } else { 2168168404Spjd need_policy = TRUE; 2169168404Spjd } 2170168404Spjd } else { 2171168404Spjd need_policy = TRUE; 2172168404Spjd } 2173168404Spjd } 2174168404Spjd 2175168404Spjd mutex_enter(&zp->z_lock); 2176168404Spjd oldva.va_mode = pzp->zp_mode; 2177168404Spjd oldva.va_uid = zp->z_phys->zp_uid; 2178168404Spjd oldva.va_gid = zp->z_phys->zp_gid; 2179168404Spjd mutex_exit(&zp->z_lock); 2180168404Spjd 2181168404Spjd if (mask & AT_MODE) { 2182168404Spjd if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) { 2183168962Spjd err = secpolicy_setid_setsticky_clear(vp, vap, 2184168962Spjd &oldva, cr); 2185168962Spjd if (err) { 2186168962Spjd ZFS_EXIT(zfsvfs); 2187168962Spjd return (err); 2188168962Spjd } 2189168404Spjd trim_mask |= AT_MODE; 2190168404Spjd } else { 2191168404Spjd need_policy = TRUE; 2192168404Spjd } 2193168404Spjd } 2194168404Spjd 2195168404Spjd if (need_policy) { 2196168404Spjd /* 2197168404Spjd * If trim_mask is set then take ownership 2198168404Spjd * has been granted or write_acl is present and user 2199168404Spjd * has the ability to modify mode. In that case remove 2200168404Spjd * UID|GID and or MODE from mask so that 2201168404Spjd * secpolicy_vnode_setattr() doesn't revoke it. 2202168404Spjd */ 2203168404Spjd 2204168404Spjd if (trim_mask) { 2205168404Spjd saved_mask = vap->va_mask; 2206168404Spjd vap->va_mask &= ~trim_mask; 2207168404Spjd 2208168404Spjd } 2209168404Spjd err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 2210168404Spjd (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp); 2211168404Spjd if (err) { 2212168404Spjd ZFS_EXIT(zfsvfs); 2213168404Spjd return (err); 2214168404Spjd } 2215168404Spjd 2216168404Spjd if (trim_mask) 2217168404Spjd vap->va_mask |= saved_mask; 2218168404Spjd } 2219168404Spjd 2220168404Spjd /* 2221168404Spjd * secpolicy_vnode_setattr, or take ownership may have 2222168404Spjd * changed va_mask 2223168404Spjd */ 2224168404Spjd mask = vap->va_mask; 2225168404Spjd 2226168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2227168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2228168404Spjd 2229168404Spjd if (mask & AT_MODE) { 2230168404Spjd uint64_t pmode = pzp->zp_mode; 2231168404Spjd 2232168404Spjd new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); 2233168404Spjd 2234168404Spjd if (zp->z_phys->zp_acl.z_acl_extern_obj) 2235168404Spjd dmu_tx_hold_write(tx, 2236168404Spjd pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE); 2237168404Spjd else 2238168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2239168404Spjd 0, ZFS_ACL_SIZE(MAX_ACL_SIZE)); 2240168404Spjd } 2241168404Spjd 2242168404Spjd if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) { 2243168404Spjd err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp); 2244168404Spjd if (err) { 2245168404Spjd dmu_tx_abort(tx); 2246168404Spjd ZFS_EXIT(zfsvfs); 2247168404Spjd return (err); 2248168404Spjd } 2249168404Spjd dmu_tx_hold_bonus(tx, attrzp->z_id); 2250168404Spjd } 2251168404Spjd 2252168404Spjd err = dmu_tx_assign(tx, zfsvfs->z_assign); 2253168404Spjd if (err) { 2254168404Spjd if (attrzp) 2255168404Spjd VN_RELE(ZTOV(attrzp)); 2256168404Spjd if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2257168404Spjd dmu_tx_wait(tx); 2258168404Spjd dmu_tx_abort(tx); 2259168404Spjd goto top; 2260168404Spjd } 2261168404Spjd dmu_tx_abort(tx); 2262168404Spjd ZFS_EXIT(zfsvfs); 2263168404Spjd return (err); 2264168404Spjd } 2265168404Spjd 2266168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2267168404Spjd 2268168404Spjd /* 2269168404Spjd * Set each attribute requested. 2270168404Spjd * We group settings according to the locks they need to acquire. 2271168404Spjd * 2272168404Spjd * Note: you cannot set ctime directly, although it will be 2273168404Spjd * updated as a side-effect of calling this function. 2274168404Spjd */ 2275168404Spjd 2276168404Spjd mutex_enter(&zp->z_lock); 2277168404Spjd 2278168404Spjd if (mask & AT_MODE) { 2279168404Spjd err = zfs_acl_chmod_setattr(zp, new_mode, tx); 2280168404Spjd ASSERT3U(err, ==, 0); 2281168404Spjd } 2282168404Spjd 2283168404Spjd if (attrzp) 2284168404Spjd mutex_enter(&attrzp->z_lock); 2285168404Spjd 2286168404Spjd if (mask & AT_UID) { 2287168404Spjd zp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2288168404Spjd if (attrzp) { 2289168404Spjd attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid; 2290168404Spjd } 2291168404Spjd } 2292168404Spjd 2293168404Spjd if (mask & AT_GID) { 2294168404Spjd zp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2295168404Spjd if (attrzp) 2296168404Spjd attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid; 2297168404Spjd } 2298168404Spjd 2299168404Spjd if (attrzp) 2300168404Spjd mutex_exit(&attrzp->z_lock); 2301168404Spjd 2302168404Spjd if (mask & AT_ATIME) 2303168404Spjd ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); 2304168404Spjd 2305168404Spjd if (mask & AT_MTIME) 2306168404Spjd ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime); 2307168404Spjd 2308168404Spjd if (mask & AT_SIZE) 2309168404Spjd zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx); 2310168404Spjd else if (mask != 0) 2311168404Spjd zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 2312168404Spjd 2313168404Spjd if (mask != 0) 2314168404Spjd zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask); 2315168404Spjd 2316168404Spjd mutex_exit(&zp->z_lock); 2317168404Spjd 2318168404Spjd if (attrzp) 2319168404Spjd VN_RELE(ZTOV(attrzp)); 2320168404Spjd 2321168404Spjd dmu_tx_commit(tx); 2322168404Spjd 2323168404Spjd ZFS_EXIT(zfsvfs); 2324168404Spjd return (err); 2325168404Spjd} 2326168404Spjd 2327168404Spjdtypedef struct zfs_zlock { 2328168404Spjd krwlock_t *zl_rwlock; /* lock we acquired */ 2329168404Spjd znode_t *zl_znode; /* znode we held */ 2330168404Spjd struct zfs_zlock *zl_next; /* next in list */ 2331168404Spjd} zfs_zlock_t; 2332168404Spjd 2333168404Spjd/* 2334168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock(). 2335168404Spjd */ 2336168404Spjdstatic void 2337168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp) 2338168404Spjd{ 2339168404Spjd zfs_zlock_t *zl; 2340168404Spjd 2341168404Spjd while ((zl = *zlpp) != NULL) { 2342168404Spjd if (zl->zl_znode != NULL) 2343168404Spjd VN_RELE(ZTOV(zl->zl_znode)); 2344168404Spjd rw_exit(zl->zl_rwlock); 2345168404Spjd *zlpp = zl->zl_next; 2346168404Spjd kmem_free(zl, sizeof (*zl)); 2347168404Spjd } 2348168404Spjd} 2349168404Spjd 2350168404Spjd/* 2351168404Spjd * Search back through the directory tree, using the ".." entries. 2352168404Spjd * Lock each directory in the chain to prevent concurrent renames. 2353168404Spjd * Fail any attempt to move a directory into one of its own descendants. 2354168404Spjd * XXX - z_parent_lock can overlap with map or grow locks 2355168404Spjd */ 2356168404Spjdstatic int 2357168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) 2358168404Spjd{ 2359168404Spjd zfs_zlock_t *zl; 2360168404Spjd znode_t *zp = tdzp; 2361168404Spjd uint64_t rootid = zp->z_zfsvfs->z_root; 2362168404Spjd uint64_t *oidp = &zp->z_id; 2363168404Spjd krwlock_t *rwlp = &szp->z_parent_lock; 2364168404Spjd krw_t rw = RW_WRITER; 2365168404Spjd 2366168404Spjd /* 2367168404Spjd * First pass write-locks szp and compares to zp->z_id. 2368168404Spjd * Later passes read-lock zp and compare to zp->z_parent. 2369168404Spjd */ 2370168404Spjd do { 2371168404Spjd if (!rw_tryenter(rwlp, rw)) { 2372168404Spjd /* 2373168404Spjd * Another thread is renaming in this path. 2374168404Spjd * Note that if we are a WRITER, we don't have any 2375168404Spjd * parent_locks held yet. 2376168404Spjd */ 2377168404Spjd if (rw == RW_READER && zp->z_id > szp->z_id) { 2378168404Spjd /* 2379168404Spjd * Drop our locks and restart 2380168404Spjd */ 2381168404Spjd zfs_rename_unlock(&zl); 2382168404Spjd *zlpp = NULL; 2383168404Spjd zp = tdzp; 2384168404Spjd oidp = &zp->z_id; 2385168404Spjd rwlp = &szp->z_parent_lock; 2386168404Spjd rw = RW_WRITER; 2387168404Spjd continue; 2388168404Spjd } else { 2389168404Spjd /* 2390168404Spjd * Wait for other thread to drop its locks 2391168404Spjd */ 2392168404Spjd rw_enter(rwlp, rw); 2393168404Spjd } 2394168404Spjd } 2395168404Spjd 2396168404Spjd zl = kmem_alloc(sizeof (*zl), KM_SLEEP); 2397168404Spjd zl->zl_rwlock = rwlp; 2398168404Spjd zl->zl_znode = NULL; 2399168404Spjd zl->zl_next = *zlpp; 2400168404Spjd *zlpp = zl; 2401168404Spjd 2402168404Spjd if (*oidp == szp->z_id) /* We're a descendant of szp */ 2403168404Spjd return (EINVAL); 2404168404Spjd 2405168404Spjd if (*oidp == rootid) /* We've hit the top */ 2406168404Spjd return (0); 2407168404Spjd 2408168404Spjd if (rw == RW_READER) { /* i.e. not the first pass */ 2409168404Spjd int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp); 2410168404Spjd if (error) 2411168404Spjd return (error); 2412168404Spjd zl->zl_znode = zp; 2413168404Spjd } 2414168404Spjd oidp = &zp->z_phys->zp_parent; 2415168404Spjd rwlp = &zp->z_parent_lock; 2416168404Spjd rw = RW_READER; 2417168404Spjd 2418168404Spjd } while (zp->z_id != sdzp->z_id); 2419168404Spjd 2420168404Spjd return (0); 2421168404Spjd} 2422168404Spjd 2423168404Spjd/* 2424168404Spjd * Move an entry from the provided source directory to the target 2425168404Spjd * directory. Change the entry name as indicated. 2426168404Spjd * 2427168404Spjd * IN: sdvp - Source directory containing the "old entry". 2428168404Spjd * snm - Old entry name. 2429168404Spjd * tdvp - Target directory to contain the "new entry". 2430168404Spjd * tnm - New entry name. 2431168404Spjd * cr - credentials of caller. 2432168404Spjd * 2433168404Spjd * RETURN: 0 if success 2434168404Spjd * error code if failure 2435168404Spjd * 2436168404Spjd * Timestamps: 2437168404Spjd * sdvp,tdvp - ctime|mtime updated 2438168404Spjd */ 2439168404Spjdstatic int 2440168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr) 2441168404Spjd{ 2442168404Spjd znode_t *tdzp, *szp, *tzp; 2443168404Spjd znode_t *sdzp = VTOZ(sdvp); 2444168404Spjd zfsvfs_t *zfsvfs = sdzp->z_zfsvfs; 2445168404Spjd zilog_t *zilog = zfsvfs->z_log; 2446168962Spjd vnode_t *realvp; 2447168404Spjd zfs_dirlock_t *sdl, *tdl; 2448168404Spjd dmu_tx_t *tx; 2449168404Spjd zfs_zlock_t *zl; 2450168962Spjd int cmp, serr, terr, error; 2451168404Spjd 2452168404Spjd ZFS_ENTER(zfsvfs); 2453168404Spjd 2454168962Spjd /* 2455168962Spjd * Make sure we have the real vp for the target directory. 2456168962Spjd */ 2457168962Spjd if (VOP_REALVP(tdvp, &realvp) == 0) 2458168962Spjd tdvp = realvp; 2459168962Spjd 2460168404Spjd if (tdvp->v_vfsp != sdvp->v_vfsp) { 2461168404Spjd ZFS_EXIT(zfsvfs); 2462168962Spjd return (EXDEV); 2463168404Spjd } 2464168404Spjd 2465168404Spjd tdzp = VTOZ(tdvp); 2466168404Spjdtop: 2467168404Spjd szp = NULL; 2468168404Spjd tzp = NULL; 2469168404Spjd zl = NULL; 2470168404Spjd 2471168404Spjd /* 2472168404Spjd * This is to prevent the creation of links into attribute space 2473168404Spjd * by renaming a linked file into/outof an attribute directory. 2474168404Spjd * See the comment in zfs_link() for why this is considered bad. 2475168404Spjd */ 2476168404Spjd if ((tdzp->z_phys->zp_flags & ZFS_XATTR) != 2477168404Spjd (sdzp->z_phys->zp_flags & ZFS_XATTR)) { 2478168962Spjd ZFS_EXIT(zfsvfs); 2479168962Spjd return (EINVAL); 2480168404Spjd } 2481168404Spjd 2482168404Spjd /* 2483168404Spjd * Lock source and target directory entries. To prevent deadlock, 2484168404Spjd * a lock ordering must be defined. We lock the directory with 2485168404Spjd * the smallest object id first, or if it's a tie, the one with 2486168404Spjd * the lexically first name. 2487168404Spjd */ 2488168404Spjd if (sdzp->z_id < tdzp->z_id) { 2489168962Spjd cmp = -1; 2490168962Spjd } else if (sdzp->z_id > tdzp->z_id) { 2491168962Spjd cmp = 1; 2492168962Spjd } else { 2493168962Spjd cmp = strcmp(snm, tnm); 2494168962Spjd if (cmp == 0) { 2495168962Spjd /* 2496168962Spjd * POSIX: "If the old argument and the new argument 2497168962Spjd * both refer to links to the same existing file, 2498168962Spjd * the rename() function shall return successfully 2499168962Spjd * and perform no other action." 2500168962Spjd */ 2501168962Spjd ZFS_EXIT(zfsvfs); 2502168962Spjd return (0); 2503168962Spjd } 2504168962Spjd } 2505168962Spjd if (cmp < 0) { 2506168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2507168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2508168962Spjd } else { 2509168404Spjd terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0); 2510168404Spjd serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS); 2511168404Spjd } 2512168404Spjd 2513168962Spjd if (serr) { 2514168404Spjd /* 2515168404Spjd * Source entry invalid or not there. 2516168404Spjd */ 2517168962Spjd if (!terr) { 2518168404Spjd zfs_dirent_unlock(tdl); 2519168962Spjd if (tzp) 2520168962Spjd VN_RELE(ZTOV(tzp)); 2521168962Spjd } 2522168404Spjd if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0) 2523168404Spjd serr = EINVAL; 2524168962Spjd ZFS_EXIT(zfsvfs); 2525168962Spjd return (serr); 2526168404Spjd } 2527168404Spjd if (terr) { 2528168404Spjd zfs_dirent_unlock(sdl); 2529168962Spjd VN_RELE(ZTOV(szp)); 2530168404Spjd if (strcmp(tnm, "..") == 0) 2531168404Spjd terr = EINVAL; 2532168962Spjd ZFS_EXIT(zfsvfs); 2533168962Spjd return (terr); 2534168404Spjd } 2535168404Spjd 2536168404Spjd /* 2537168404Spjd * Must have write access at the source to remove the old entry 2538168404Spjd * and write access at the target to create the new entry. 2539168404Spjd * Note that if target and source are the same, this can be 2540168404Spjd * done in a single check. 2541168404Spjd */ 2542168404Spjd 2543168404Spjd if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) 2544168404Spjd goto out; 2545168404Spjd 2546168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2547168404Spjd /* 2548168404Spjd * Check to make sure rename is valid. 2549168404Spjd * Can't do a move like this: /usr/a/b to /usr/a/b/c/d 2550168404Spjd */ 2551168404Spjd if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl)) 2552168404Spjd goto out; 2553168404Spjd } 2554168404Spjd 2555168404Spjd /* 2556168404Spjd * Does target exist? 2557168404Spjd */ 2558168404Spjd if (tzp) { 2559168404Spjd /* 2560168404Spjd * Source and target must be the same type. 2561168404Spjd */ 2562168962Spjd if (ZTOV(szp)->v_type == VDIR) { 2563168962Spjd if (ZTOV(tzp)->v_type != VDIR) { 2564168404Spjd error = ENOTDIR; 2565168404Spjd goto out; 2566168404Spjd } 2567168404Spjd } else { 2568168962Spjd if (ZTOV(tzp)->v_type == VDIR) { 2569168404Spjd error = EISDIR; 2570168404Spjd goto out; 2571168404Spjd } 2572168404Spjd } 2573168404Spjd /* 2574168404Spjd * POSIX dictates that when the source and target 2575168404Spjd * entries refer to the same file object, rename 2576168404Spjd * must do nothing and exit without error. 2577168404Spjd */ 2578168404Spjd if (szp->z_id == tzp->z_id) { 2579168404Spjd error = 0; 2580168404Spjd goto out; 2581168404Spjd } 2582168404Spjd } 2583168404Spjd 2584168962Spjd vnevent_rename_src(ZTOV(szp)); 2585168962Spjd if (tzp) 2586168962Spjd vnevent_rename_dest(ZTOV(tzp)); 2587168962Spjd 2588168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2589168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); /* nlink changes */ 2590168404Spjd dmu_tx_hold_bonus(tx, sdzp->z_id); /* nlink changes */ 2591168404Spjd dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm); 2592168404Spjd dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm); 2593168404Spjd if (sdzp != tdzp) 2594168404Spjd dmu_tx_hold_bonus(tx, tdzp->z_id); /* nlink changes */ 2595168404Spjd if (tzp) 2596168404Spjd dmu_tx_hold_bonus(tx, tzp->z_id); /* parent changes */ 2597168404Spjd dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); 2598168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2599168404Spjd if (error) { 2600168404Spjd if (zl != NULL) 2601168404Spjd zfs_rename_unlock(&zl); 2602168404Spjd zfs_dirent_unlock(sdl); 2603168404Spjd zfs_dirent_unlock(tdl); 2604168962Spjd VN_RELE(ZTOV(szp)); 2605168962Spjd if (tzp) 2606168962Spjd VN_RELE(ZTOV(tzp)); 2607168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2608168404Spjd dmu_tx_wait(tx); 2609168404Spjd dmu_tx_abort(tx); 2610168404Spjd goto top; 2611168404Spjd } 2612168404Spjd dmu_tx_abort(tx); 2613168962Spjd ZFS_EXIT(zfsvfs); 2614168962Spjd return (error); 2615168404Spjd } 2616168404Spjd 2617168404Spjd if (tzp) /* Attempt to remove the existing target */ 2618168404Spjd error = zfs_link_destroy(tdl, tzp, tx, 0, NULL); 2619168404Spjd 2620168404Spjd if (error == 0) { 2621168404Spjd error = zfs_link_create(tdl, szp, tx, ZRENAMING); 2622168404Spjd if (error == 0) { 2623168404Spjd error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL); 2624168404Spjd ASSERT(error == 0); 2625168404Spjd zfs_log_rename(zilog, tx, TX_RENAME, sdzp, 2626168404Spjd sdl->dl_name, tdzp, tdl->dl_name, szp); 2627168404Spjd } 2628168404Spjd#ifdef FREEBSD_NAMECACHE 2629168404Spjd if (error == 0) { 2630168404Spjd cache_purge(sdvp); 2631168404Spjd cache_purge(tdvp); 2632168404Spjd } 2633168404Spjd#endif 2634168404Spjd } 2635168404Spjd 2636168404Spjd dmu_tx_commit(tx); 2637168404Spjdout: 2638168404Spjd if (zl != NULL) 2639168404Spjd zfs_rename_unlock(&zl); 2640168404Spjd 2641168404Spjd zfs_dirent_unlock(sdl); 2642168404Spjd zfs_dirent_unlock(tdl); 2643168404Spjd 2644168962Spjd VN_RELE(ZTOV(szp)); 2645168404Spjd if (tzp) 2646168962Spjd VN_RELE(ZTOV(tzp)); 2647168404Spjd 2648168404Spjd ZFS_EXIT(zfsvfs); 2649168404Spjd 2650168404Spjd return (error); 2651168404Spjd} 2652168404Spjd 2653168404Spjd/* 2654168404Spjd * Insert the indicated symbolic reference entry into the directory. 2655168404Spjd * 2656168404Spjd * IN: dvp - Directory to contain new symbolic link. 2657168404Spjd * link - Name for new symlink entry. 2658168404Spjd * vap - Attributes of new entry. 2659168404Spjd * target - Target path of new symlink. 2660168404Spjd * cr - credentials of caller. 2661168404Spjd * 2662168404Spjd * RETURN: 0 if success 2663168404Spjd * error code if failure 2664168404Spjd * 2665168404Spjd * Timestamps: 2666168404Spjd * dvp - ctime|mtime updated 2667168404Spjd */ 2668168404Spjdstatic int 2669168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td) 2670168404Spjd{ 2671168404Spjd znode_t *zp, *dzp = VTOZ(dvp); 2672168404Spjd zfs_dirlock_t *dl; 2673168404Spjd dmu_tx_t *tx; 2674168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2675168404Spjd zilog_t *zilog = zfsvfs->z_log; 2676168404Spjd uint64_t zoid; 2677168404Spjd int len = strlen(link); 2678168404Spjd int error; 2679168404Spjd 2680168962Spjd ASSERT(vap->va_type == VLNK); 2681168404Spjd 2682168404Spjd ZFS_ENTER(zfsvfs); 2683168404Spjdtop: 2684168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2685168404Spjd ZFS_EXIT(zfsvfs); 2686168404Spjd return (error); 2687168404Spjd } 2688168404Spjd 2689168404Spjd if (len > MAXPATHLEN) { 2690168404Spjd ZFS_EXIT(zfsvfs); 2691168404Spjd return (ENAMETOOLONG); 2692168404Spjd } 2693168404Spjd 2694168404Spjd /* 2695168404Spjd * Attempt to lock directory; fail if entry already exists. 2696168404Spjd */ 2697168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) { 2698168404Spjd ZFS_EXIT(zfsvfs); 2699168404Spjd return (error); 2700168404Spjd } 2701168404Spjd 2702168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2703168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len)); 2704168404Spjd dmu_tx_hold_bonus(tx, dzp->z_id); 2705168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2706168404Spjd if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE) 2707168404Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE); 2708168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2709168404Spjd if (error) { 2710168404Spjd zfs_dirent_unlock(dl); 2711168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2712168404Spjd dmu_tx_wait(tx); 2713168404Spjd dmu_tx_abort(tx); 2714168404Spjd goto top; 2715168404Spjd } 2716168404Spjd dmu_tx_abort(tx); 2717168404Spjd ZFS_EXIT(zfsvfs); 2718168404Spjd return (error); 2719168404Spjd } 2720168404Spjd 2721168404Spjd dmu_buf_will_dirty(dzp->z_dbuf, tx); 2722168404Spjd 2723168404Spjd /* 2724168404Spjd * Create a new object for the symlink. 2725168404Spjd * Put the link content into bonus buffer if it will fit; 2726168404Spjd * otherwise, store it just like any other file data. 2727168404Spjd */ 2728168404Spjd zoid = 0; 2729168404Spjd if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) { 2730168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len); 2731168404Spjd if (len != 0) 2732168404Spjd bcopy(link, zp->z_phys + 1, len); 2733168404Spjd } else { 2734168404Spjd dmu_buf_t *dbp; 2735168404Spjd 2736168404Spjd zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0); 2737168404Spjd 2738168404Spjd /* 2739168404Spjd * Nothing can access the znode yet so no locking needed 2740168404Spjd * for growing the znode's blocksize. 2741168404Spjd */ 2742168404Spjd zfs_grow_blocksize(zp, len, tx); 2743168404Spjd 2744168404Spjd VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp)); 2745168404Spjd dmu_buf_will_dirty(dbp, tx); 2746168404Spjd 2747168404Spjd ASSERT3U(len, <=, dbp->db_size); 2748168404Spjd bcopy(link, dbp->db_data, len); 2749168404Spjd dmu_buf_rele(dbp, FTAG); 2750168404Spjd } 2751168404Spjd zp->z_phys->zp_size = len; 2752168404Spjd 2753168404Spjd /* 2754168404Spjd * Insert the new object into the directory. 2755168404Spjd */ 2756168404Spjd (void) zfs_link_create(dl, zp, tx, ZNEW); 2757168962Spjdout: 2758168404Spjd if (error == 0) { 2759168404Spjd zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link); 2760168962Spjd *vpp = ZTOV(zp); 2761168962Spjd vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); 2762168404Spjd } 2763168404Spjd 2764168404Spjd dmu_tx_commit(tx); 2765168404Spjd 2766168404Spjd zfs_dirent_unlock(dl); 2767168404Spjd 2768168404Spjd ZFS_EXIT(zfsvfs); 2769168404Spjd return (error); 2770168404Spjd} 2771168404Spjd 2772168404Spjd/* 2773168404Spjd * Return, in the buffer contained in the provided uio structure, 2774168404Spjd * the symbolic path referred to by vp. 2775168404Spjd * 2776168404Spjd * IN: vp - vnode of symbolic link. 2777168404Spjd * uoip - structure to contain the link path. 2778168404Spjd * cr - credentials of caller. 2779168404Spjd * 2780168404Spjd * OUT: uio - structure to contain the link path. 2781168404Spjd * 2782168404Spjd * RETURN: 0 if success 2783168404Spjd * error code if failure 2784168404Spjd * 2785168404Spjd * Timestamps: 2786168404Spjd * vp - atime updated 2787168404Spjd */ 2788168404Spjd/* ARGSUSED */ 2789168404Spjdstatic int 2790168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr) 2791168404Spjd{ 2792168404Spjd znode_t *zp = VTOZ(vp); 2793168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2794168404Spjd size_t bufsz; 2795168404Spjd int error; 2796168404Spjd 2797168404Spjd ZFS_ENTER(zfsvfs); 2798168404Spjd 2799168404Spjd bufsz = (size_t)zp->z_phys->zp_size; 2800168404Spjd if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) { 2801168404Spjd error = uiomove(zp->z_phys + 1, 2802168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2803168404Spjd } else { 2804168404Spjd dmu_buf_t *dbp; 2805168404Spjd error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp); 2806168404Spjd if (error) { 2807168404Spjd ZFS_EXIT(zfsvfs); 2808168404Spjd return (error); 2809168404Spjd } 2810168404Spjd error = uiomove(dbp->db_data, 2811168404Spjd MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio); 2812168404Spjd dmu_buf_rele(dbp, FTAG); 2813168404Spjd } 2814168404Spjd 2815168404Spjd ZFS_ACCESSTIME_STAMP(zfsvfs, zp); 2816168404Spjd ZFS_EXIT(zfsvfs); 2817168404Spjd return (error); 2818168404Spjd} 2819168404Spjd 2820168404Spjd/* 2821168404Spjd * Insert a new entry into directory tdvp referencing svp. 2822168404Spjd * 2823168404Spjd * IN: tdvp - Directory to contain new entry. 2824168404Spjd * svp - vnode of new entry. 2825168404Spjd * name - name of new entry. 2826168404Spjd * cr - credentials of caller. 2827168404Spjd * 2828168404Spjd * RETURN: 0 if success 2829168404Spjd * error code if failure 2830168404Spjd * 2831168404Spjd * Timestamps: 2832168404Spjd * tdvp - ctime|mtime updated 2833168404Spjd * svp - ctime updated 2834168404Spjd */ 2835168404Spjd/* ARGSUSED */ 2836168404Spjdstatic int 2837168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr) 2838168404Spjd{ 2839168404Spjd znode_t *dzp = VTOZ(tdvp); 2840168404Spjd znode_t *tzp, *szp; 2841168404Spjd zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 2842168404Spjd zilog_t *zilog = zfsvfs->z_log; 2843168404Spjd zfs_dirlock_t *dl; 2844168404Spjd dmu_tx_t *tx; 2845168962Spjd vnode_t *realvp; 2846168404Spjd int error; 2847168404Spjd 2848168404Spjd ASSERT(tdvp->v_type == VDIR); 2849168404Spjd 2850168404Spjd ZFS_ENTER(zfsvfs); 2851168404Spjd 2852168962Spjd if (VOP_REALVP(svp, &realvp) == 0) 2853168962Spjd svp = realvp; 2854168962Spjd 2855168404Spjd if (svp->v_vfsp != tdvp->v_vfsp) { 2856168404Spjd ZFS_EXIT(zfsvfs); 2857168404Spjd return (EXDEV); 2858168404Spjd } 2859168404Spjd 2860168404Spjd szp = VTOZ(svp); 2861168404Spjdtop: 2862168404Spjd /* 2863168404Spjd * We do not support links between attributes and non-attributes 2864168404Spjd * because of the potential security risk of creating links 2865168404Spjd * into "normal" file space in order to circumvent restrictions 2866168404Spjd * imposed in attribute space. 2867168404Spjd */ 2868168404Spjd if ((szp->z_phys->zp_flags & ZFS_XATTR) != 2869168404Spjd (dzp->z_phys->zp_flags & ZFS_XATTR)) { 2870168404Spjd ZFS_EXIT(zfsvfs); 2871168404Spjd return (EINVAL); 2872168404Spjd } 2873168404Spjd 2874168404Spjd /* 2875168404Spjd * POSIX dictates that we return EPERM here. 2876168404Spjd * Better choices include ENOTSUP or EISDIR. 2877168404Spjd */ 2878168404Spjd if (svp->v_type == VDIR) { 2879168404Spjd ZFS_EXIT(zfsvfs); 2880168404Spjd return (EPERM); 2881168404Spjd } 2882168404Spjd 2883168404Spjd if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) && 2884168404Spjd secpolicy_basic_link(cr) != 0) { 2885168404Spjd ZFS_EXIT(zfsvfs); 2886168404Spjd return (EPERM); 2887168404Spjd } 2888168404Spjd 2889168404Spjd if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) { 2890168404Spjd ZFS_EXIT(zfsvfs); 2891168404Spjd return (error); 2892168404Spjd } 2893168404Spjd 2894168404Spjd /* 2895168404Spjd * Attempt to lock directory; fail if entry already exists. 2896168404Spjd */ 2897168404Spjd if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) { 2898168404Spjd ZFS_EXIT(zfsvfs); 2899168404Spjd return (error); 2900168404Spjd } 2901168404Spjd 2902168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2903168404Spjd dmu_tx_hold_bonus(tx, szp->z_id); 2904168404Spjd dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); 2905168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2906168404Spjd if (error) { 2907168404Spjd zfs_dirent_unlock(dl); 2908168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2909168404Spjd dmu_tx_wait(tx); 2910168404Spjd dmu_tx_abort(tx); 2911168404Spjd goto top; 2912168404Spjd } 2913168404Spjd dmu_tx_abort(tx); 2914168404Spjd ZFS_EXIT(zfsvfs); 2915168404Spjd return (error); 2916168404Spjd } 2917168404Spjd 2918168404Spjd error = zfs_link_create(dl, szp, tx, 0); 2919168404Spjd 2920168404Spjd if (error == 0) 2921168404Spjd zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name); 2922168404Spjd 2923168404Spjd dmu_tx_commit(tx); 2924168404Spjd 2925168404Spjd zfs_dirent_unlock(dl); 2926168404Spjd 2927168404Spjd ZFS_EXIT(zfsvfs); 2928168404Spjd return (error); 2929168404Spjd} 2930168404Spjd 2931168962Spjdvoid 2932168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr) 2933168404Spjd{ 2934168962Spjd znode_t *zp = VTOZ(vp); 2935168962Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2936168962Spjd int error; 2937168404Spjd 2938168404Spjd rw_enter(&zfsvfs->z_um_lock, RW_READER); 2939168404Spjd if (zfsvfs->z_unmounted2) { 2940168404Spjd ASSERT(zp->z_dbuf_held == 0); 2941168404Spjd 2942168404Spjd mutex_enter(&zp->z_lock); 2943168404Spjd VI_LOCK(vp); 2944168404Spjd vp->v_count = 0; /* count arrives as 1 */ 2945168404Spjd VI_UNLOCK(vp); 2946168404Spjd if (zp->z_dbuf == NULL) { 2947168404Spjd mutex_exit(&zp->z_lock); 2948168404Spjd zfs_znode_free(zp); 2949168404Spjd } else { 2950168404Spjd mutex_exit(&zp->z_lock); 2951168404Spjd } 2952168404Spjd rw_exit(&zfsvfs->z_um_lock); 2953168404Spjd VFS_RELE(zfsvfs->z_vfs); 2954168962Spjd return; 2955168404Spjd } 2956168404Spjd 2957168404Spjd if (zp->z_atime_dirty && zp->z_unlinked == 0) { 2958168404Spjd dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 2959168404Spjd 2960168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2961168404Spjd error = dmu_tx_assign(tx, TXG_WAIT); 2962168404Spjd if (error) { 2963168404Spjd dmu_tx_abort(tx); 2964168404Spjd } else { 2965168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 2966168404Spjd mutex_enter(&zp->z_lock); 2967168404Spjd zp->z_atime_dirty = 0; 2968168404Spjd mutex_exit(&zp->z_lock); 2969168404Spjd dmu_tx_commit(tx); 2970168404Spjd } 2971168404Spjd } 2972168404Spjd 2973168404Spjd zfs_zinactive(zp); 2974168404Spjd rw_exit(&zfsvfs->z_um_lock); 2975168404Spjd} 2976168404Spjd 2977168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid)); 2978168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid)); 2979168404Spjd 2980168404Spjdstatic int 2981168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp) 2982168404Spjd{ 2983168404Spjd znode_t *zp = VTOZ(vp); 2984168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2985168404Spjd uint32_t gen = (uint32_t)zp->z_phys->zp_gen; 2986168404Spjd uint64_t object = zp->z_id; 2987168404Spjd zfid_short_t *zfid; 2988168404Spjd int size, i; 2989168404Spjd 2990168404Spjd ZFS_ENTER(zfsvfs); 2991168404Spjd 2992168404Spjd size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN; 2993168404Spjd fidp->fid_len = size; 2994168404Spjd 2995168404Spjd zfid = (zfid_short_t *)fidp; 2996168404Spjd 2997168404Spjd zfid->zf_len = size; 2998168404Spjd 2999168404Spjd for (i = 0; i < sizeof (zfid->zf_object); i++) 3000168404Spjd zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 3001168404Spjd 3002168404Spjd /* Must have a non-zero generation number to distinguish from .zfs */ 3003168404Spjd if (gen == 0) 3004168404Spjd gen = 1; 3005168404Spjd for (i = 0; i < sizeof (zfid->zf_gen); i++) 3006168404Spjd zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i)); 3007168404Spjd 3008168404Spjd if (size == LONG_FID_LEN) { 3009168404Spjd uint64_t objsetid = dmu_objset_id(zfsvfs->z_os); 3010169023Spjd zfid_long_t *zlfid; 3011168404Spjd 3012168404Spjd zlfid = (zfid_long_t *)fidp; 3013168404Spjd 3014168404Spjd for (i = 0; i < sizeof (zlfid->zf_setid); i++) 3015168404Spjd zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i)); 3016168404Spjd 3017168404Spjd /* XXX - this should be the generation number for the objset */ 3018168404Spjd for (i = 0; i < sizeof (zlfid->zf_setgen); i++) 3019168404Spjd zlfid->zf_setgen[i] = 0; 3020168404Spjd } 3021168404Spjd 3022168404Spjd ZFS_EXIT(zfsvfs); 3023168404Spjd return (0); 3024168404Spjd} 3025168404Spjd 3026168404Spjdstatic int 3027168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) 3028168404Spjd{ 3029168404Spjd znode_t *zp, *xzp; 3030168404Spjd zfsvfs_t *zfsvfs; 3031168404Spjd zfs_dirlock_t *dl; 3032168404Spjd int error; 3033168404Spjd 3034168404Spjd switch (cmd) { 3035168404Spjd case _PC_LINK_MAX: 3036168404Spjd *valp = INT_MAX; 3037168404Spjd return (0); 3038168404Spjd 3039168404Spjd case _PC_FILESIZEBITS: 3040168404Spjd *valp = 64; 3041168404Spjd return (0); 3042168404Spjd 3043168404Spjd#if 0 3044168404Spjd case _PC_XATTR_EXISTS: 3045168404Spjd zp = VTOZ(vp); 3046168404Spjd zfsvfs = zp->z_zfsvfs; 3047168404Spjd ZFS_ENTER(zfsvfs); 3048168404Spjd *valp = 0; 3049168404Spjd error = zfs_dirent_lock(&dl, zp, "", &xzp, 3050168404Spjd ZXATTR | ZEXISTS | ZSHARED); 3051168404Spjd if (error == 0) { 3052168404Spjd zfs_dirent_unlock(dl); 3053168404Spjd if (!zfs_dirempty(xzp)) 3054168404Spjd *valp = 1; 3055168404Spjd VN_RELE(ZTOV(xzp)); 3056168404Spjd } else if (error == ENOENT) { 3057168404Spjd /* 3058168404Spjd * If there aren't extended attributes, it's the 3059168404Spjd * same as having zero of them. 3060168404Spjd */ 3061168404Spjd error = 0; 3062168404Spjd } 3063168404Spjd ZFS_EXIT(zfsvfs); 3064168404Spjd return (error); 3065168404Spjd#endif 3066168404Spjd 3067168404Spjd case _PC_ACL_EXTENDED: 3068168404Spjd *valp = 0; /* TODO */ 3069168404Spjd return (0); 3070168404Spjd 3071168404Spjd case _PC_MIN_HOLE_SIZE: 3072168404Spjd *valp = (int)SPA_MINBLOCKSIZE; 3073168404Spjd return (0); 3074168404Spjd 3075168404Spjd default: 3076168962Spjd return (EOPNOTSUPP); 3077168404Spjd } 3078168404Spjd} 3079168404Spjd 3080168404Spjd#ifdef TODO 3081168404Spjd/*ARGSUSED*/ 3082168404Spjdstatic int 3083168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3084168404Spjd{ 3085168404Spjd znode_t *zp = VTOZ(vp); 3086168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3087168404Spjd int error; 3088168404Spjd 3089168404Spjd ZFS_ENTER(zfsvfs); 3090168404Spjd error = zfs_getacl(zp, vsecp, cr); 3091168404Spjd ZFS_EXIT(zfsvfs); 3092168404Spjd 3093168404Spjd return (error); 3094168404Spjd} 3095168404Spjd#endif /* TODO */ 3096168404Spjd 3097168404Spjd#ifdef TODO 3098168404Spjd/*ARGSUSED*/ 3099168404Spjdstatic int 3100168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr) 3101168404Spjd{ 3102168404Spjd znode_t *zp = VTOZ(vp); 3103168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 3104168404Spjd int error; 3105168404Spjd 3106168404Spjd ZFS_ENTER(zfsvfs); 3107168404Spjd error = zfs_setacl(zp, vsecp, cr); 3108168404Spjd ZFS_EXIT(zfsvfs); 3109168404Spjd return (error); 3110168404Spjd} 3111168404Spjd#endif /* TODO */ 3112168404Spjd 3113168962Spjdstatic int 3114168962Spjdzfs_freebsd_open(ap) 3115168962Spjd struct vop_open_args /* { 3116168962Spjd struct vnode *a_vp; 3117168962Spjd int a_mode; 3118168962Spjd struct ucred *a_cred; 3119168962Spjd struct thread *a_td; 3120168962Spjd } */ *ap; 3121168962Spjd{ 3122168962Spjd vnode_t *vp = ap->a_vp; 3123168962Spjd znode_t *zp = VTOZ(vp); 3124168962Spjd int error; 3125168962Spjd 3126168962Spjd error = zfs_open(&vp, ap->a_mode, ap->a_cred); 3127168962Spjd if (error == 0) 3128168962Spjd vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); 3129168962Spjd return (error); 3130168962Spjd} 3131168962Spjd 3132168962Spjdstatic int 3133168962Spjdzfs_freebsd_close(ap) 3134168962Spjd struct vop_close_args /* { 3135168962Spjd struct vnode *a_vp; 3136168962Spjd int a_fflag; 3137168962Spjd struct ucred *a_cred; 3138168962Spjd struct thread *a_td; 3139168962Spjd } */ *ap; 3140168962Spjd{ 3141168962Spjd 3142168962Spjd return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred)); 3143168962Spjd} 3144168962Spjd 3145168962Spjdstatic int 3146168962Spjdzfs_freebsd_ioctl(ap) 3147168962Spjd struct vop_ioctl_args /* { 3148168962Spjd struct vnode *a_vp; 3149168962Spjd u_long a_command; 3150168962Spjd caddr_t a_data; 3151168962Spjd int a_fflag; 3152168962Spjd struct ucred *cred; 3153168962Spjd struct thread *td; 3154168962Spjd } */ *ap; 3155168962Spjd{ 3156168962Spjd 3157168978Spjd return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data, 3158168962Spjd ap->a_fflag, ap->a_cred, NULL)); 3159168962Spjd} 3160168962Spjd 3161168962Spjdstatic int 3162168962Spjdzfs_freebsd_read(ap) 3163168962Spjd struct vop_read_args /* { 3164168962Spjd struct vnode *a_vp; 3165168962Spjd struct uio *a_uio; 3166168962Spjd int a_ioflag; 3167168962Spjd struct ucred *a_cred; 3168168962Spjd } */ *ap; 3169168962Spjd{ 3170168962Spjd 3171168962Spjd return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3172168962Spjd} 3173168962Spjd 3174168962Spjdstatic int 3175168962Spjdzfs_freebsd_write(ap) 3176168962Spjd struct vop_write_args /* { 3177168962Spjd struct vnode *a_vp; 3178168962Spjd struct uio *a_uio; 3179168962Spjd int a_ioflag; 3180168962Spjd struct ucred *a_cred; 3181168962Spjd } */ *ap; 3182168962Spjd{ 3183168962Spjd 3184168962Spjd return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL)); 3185168962Spjd} 3186168962Spjd 3187168962Spjdstatic int 3188168962Spjdzfs_freebsd_access(ap) 3189168962Spjd struct vop_access_args /* { 3190168962Spjd struct vnode *a_vp; 3191168962Spjd int a_mode; 3192168962Spjd struct ucred *a_cred; 3193168962Spjd struct thread *a_td; 3194168962Spjd } */ *ap; 3195168962Spjd{ 3196168962Spjd 3197168962Spjd return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred)); 3198168962Spjd} 3199168962Spjd 3200168962Spjdstatic int 3201168962Spjdzfs_freebsd_lookup(ap) 3202168962Spjd struct vop_lookup_args /* { 3203168962Spjd struct vnode *a_dvp; 3204168962Spjd struct vnode **a_vpp; 3205168962Spjd struct componentname *a_cnp; 3206168962Spjd } */ *ap; 3207168962Spjd{ 3208168962Spjd struct componentname *cnp = ap->a_cnp; 3209168962Spjd char nm[NAME_MAX + 1]; 3210168962Spjd 3211168962Spjd ASSERT(cnp->cn_namelen < sizeof(nm)); 3212168962Spjd strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm))); 3213168962Spjd 3214168962Spjd return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop, 3215168962Spjd cnp->cn_cred, cnp->cn_thread)); 3216168962Spjd} 3217168962Spjd 3218168962Spjdstatic int 3219168962Spjdzfs_freebsd_create(ap) 3220168962Spjd struct vop_create_args /* { 3221168962Spjd struct vnode *a_dvp; 3222168962Spjd struct vnode **a_vpp; 3223168962Spjd struct componentname *a_cnp; 3224168962Spjd struct vattr *a_vap; 3225168962Spjd } */ *ap; 3226168962Spjd{ 3227168962Spjd struct componentname *cnp = ap->a_cnp; 3228168962Spjd vattr_t *vap = ap->a_vap; 3229168962Spjd int mode; 3230168962Spjd 3231168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3232168962Spjd 3233168962Spjd vattr_init_mask(vap); 3234168962Spjd mode = vap->va_mode & ALLPERMS; 3235168962Spjd 3236168962Spjd return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode, 3237168962Spjd ap->a_vpp, cnp->cn_cred, cnp->cn_thread)); 3238168962Spjd} 3239168962Spjd 3240168962Spjdstatic int 3241168962Spjdzfs_freebsd_remove(ap) 3242168962Spjd struct vop_remove_args /* { 3243168962Spjd struct vnode *a_dvp; 3244168962Spjd struct vnode *a_vp; 3245168962Spjd struct componentname *a_cnp; 3246168962Spjd } */ *ap; 3247168962Spjd{ 3248168962Spjd 3249168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3250168962Spjd 3251168962Spjd return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr, 3252168962Spjd ap->a_cnp->cn_cred)); 3253168962Spjd} 3254168962Spjd 3255168962Spjdstatic int 3256168962Spjdzfs_freebsd_mkdir(ap) 3257168962Spjd struct vop_mkdir_args /* { 3258168962Spjd struct vnode *a_dvp; 3259168962Spjd struct vnode **a_vpp; 3260168962Spjd struct componentname *a_cnp; 3261168962Spjd struct vattr *a_vap; 3262168962Spjd } */ *ap; 3263168962Spjd{ 3264168962Spjd vattr_t *vap = ap->a_vap; 3265168962Spjd 3266168962Spjd ASSERT(ap->a_cnp->cn_flags & SAVENAME); 3267168962Spjd 3268168962Spjd vattr_init_mask(vap); 3269168962Spjd 3270168962Spjd return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp, 3271168962Spjd ap->a_cnp->cn_cred)); 3272168962Spjd} 3273168962Spjd 3274168962Spjdstatic int 3275168962Spjdzfs_freebsd_rmdir(ap) 3276168962Spjd struct vop_rmdir_args /* { 3277168962Spjd struct vnode *a_dvp; 3278168962Spjd struct vnode *a_vp; 3279168962Spjd struct componentname *a_cnp; 3280168962Spjd } */ *ap; 3281168962Spjd{ 3282168962Spjd struct componentname *cnp = ap->a_cnp; 3283168962Spjd 3284168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3285168962Spjd 3286168962Spjd return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred)); 3287168962Spjd} 3288168962Spjd 3289168962Spjdstatic int 3290168962Spjdzfs_freebsd_readdir(ap) 3291168962Spjd struct vop_readdir_args /* { 3292168962Spjd struct vnode *a_vp; 3293168962Spjd struct uio *a_uio; 3294168962Spjd struct ucred *a_cred; 3295168962Spjd int *a_eofflag; 3296168962Spjd int *a_ncookies; 3297168962Spjd u_long **a_cookies; 3298168962Spjd } */ *ap; 3299168962Spjd{ 3300168962Spjd 3301168962Spjd return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, 3302168962Spjd ap->a_ncookies, ap->a_cookies)); 3303168962Spjd} 3304168962Spjd 3305168962Spjdstatic int 3306168962Spjdzfs_freebsd_fsync(ap) 3307168962Spjd struct vop_fsync_args /* { 3308168962Spjd struct vnode *a_vp; 3309168962Spjd int a_waitfor; 3310168962Spjd struct thread *a_td; 3311168962Spjd } */ *ap; 3312168962Spjd{ 3313168962Spjd 3314168962Spjd vop_stdfsync(ap); 3315168962Spjd return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred)); 3316168962Spjd} 3317168962Spjd 3318168962Spjdstatic int 3319168962Spjdzfs_freebsd_getattr(ap) 3320168962Spjd struct vop_getattr_args /* { 3321168962Spjd struct vnode *a_vp; 3322168962Spjd struct vattr *a_vap; 3323168962Spjd struct ucred *a_cred; 3324168962Spjd struct thread *a_td; 3325168962Spjd } */ *ap; 3326168962Spjd{ 3327168962Spjd 3328168962Spjd return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred)); 3329168962Spjd} 3330168962Spjd 3331168962Spjdstatic int 3332168962Spjdzfs_freebsd_setattr(ap) 3333168962Spjd struct vop_setattr_args /* { 3334168962Spjd struct vnode *a_vp; 3335168962Spjd struct vattr *a_vap; 3336168962Spjd struct ucred *a_cred; 3337168962Spjd struct thread *a_td; 3338168962Spjd } */ *ap; 3339168962Spjd{ 3340168962Spjd vattr_t *vap = ap->a_vap; 3341168962Spjd 3342168962Spjd /* No support for FreeBSD's chflags(2). */ 3343168962Spjd if (vap->va_flags != VNOVAL) 3344168962Spjd return (EOPNOTSUPP); 3345168962Spjd 3346168962Spjd vattr_init_mask(vap); 3347168962Spjd 3348168962Spjd return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL)); 3349168962Spjd} 3350168962Spjd 3351168962Spjdstatic int 3352168962Spjdzfs_freebsd_rename(ap) 3353168962Spjd struct vop_rename_args /* { 3354168962Spjd struct vnode *a_fdvp; 3355168962Spjd struct vnode *a_fvp; 3356168962Spjd struct componentname *a_fcnp; 3357168962Spjd struct vnode *a_tdvp; 3358168962Spjd struct vnode *a_tvp; 3359168962Spjd struct componentname *a_tcnp; 3360168962Spjd } */ *ap; 3361168962Spjd{ 3362168962Spjd vnode_t *fdvp = ap->a_fdvp; 3363168962Spjd vnode_t *fvp = ap->a_fvp; 3364168962Spjd vnode_t *tdvp = ap->a_tdvp; 3365168962Spjd vnode_t *tvp = ap->a_tvp; 3366168962Spjd int error; 3367168962Spjd 3368168962Spjd ASSERT(ap->a_fcnp->cn_flags & SAVENAME); 3369168962Spjd ASSERT(ap->a_tcnp->cn_flags & SAVENAME); 3370168962Spjd 3371168962Spjd error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp, 3372168962Spjd ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred); 3373168962Spjd 3374168962Spjd if (tdvp == tvp) 3375168962Spjd VN_RELE(tdvp); 3376168962Spjd else 3377168962Spjd VN_URELE(tdvp); 3378168962Spjd if (tvp) 3379168962Spjd VN_URELE(tvp); 3380168962Spjd VN_RELE(fdvp); 3381168962Spjd VN_RELE(fvp); 3382168962Spjd 3383168962Spjd return (error); 3384168962Spjd} 3385168962Spjd 3386168962Spjdstatic int 3387168962Spjdzfs_freebsd_symlink(ap) 3388168962Spjd struct vop_symlink_args /* { 3389168962Spjd struct vnode *a_dvp; 3390168962Spjd struct vnode **a_vpp; 3391168962Spjd struct componentname *a_cnp; 3392168962Spjd struct vattr *a_vap; 3393168962Spjd char *a_target; 3394168962Spjd } */ *ap; 3395168962Spjd{ 3396168962Spjd struct componentname *cnp = ap->a_cnp; 3397168962Spjd vattr_t *vap = ap->a_vap; 3398168962Spjd 3399168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3400168962Spjd 3401168962Spjd vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */ 3402168962Spjd vattr_init_mask(vap); 3403168962Spjd 3404168962Spjd return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap, 3405168962Spjd ap->a_target, cnp->cn_cred, cnp->cn_thread)); 3406168962Spjd} 3407168962Spjd 3408168962Spjdstatic int 3409168962Spjdzfs_freebsd_readlink(ap) 3410168962Spjd struct vop_readlink_args /* { 3411168962Spjd struct vnode *a_vp; 3412168962Spjd struct uio *a_uio; 3413168962Spjd struct ucred *a_cred; 3414168962Spjd } */ *ap; 3415168962Spjd{ 3416168962Spjd 3417168962Spjd return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred)); 3418168962Spjd} 3419168962Spjd 3420168962Spjdstatic int 3421168962Spjdzfs_freebsd_link(ap) 3422168962Spjd struct vop_link_args /* { 3423168962Spjd struct vnode *a_tdvp; 3424168962Spjd struct vnode *a_vp; 3425168962Spjd struct componentname *a_cnp; 3426168962Spjd } */ *ap; 3427168962Spjd{ 3428168962Spjd struct componentname *cnp = ap->a_cnp; 3429168962Spjd 3430168962Spjd ASSERT(cnp->cn_flags & SAVENAME); 3431168962Spjd 3432168962Spjd return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred)); 3433168962Spjd} 3434168962Spjd 3435168962Spjdstatic int 3436168962Spjdzfs_freebsd_inactive(ap) 3437168962Spjd struct vop_inactive_args /* { 3438168962Spjd struct vnode *a_vp; 3439168962Spjd struct thread *a_td; 3440168962Spjd } */ *ap; 3441168962Spjd{ 3442168962Spjd vnode_t *vp = ap->a_vp; 3443168962Spjd 3444168962Spjd zfs_inactive(vp, ap->a_td->td_ucred); 3445168962Spjd return (0); 3446168962Spjd} 3447168962Spjd 3448168962Spjdstatic int 3449168962Spjdzfs_freebsd_reclaim(ap) 3450168962Spjd struct vop_reclaim_args /* { 3451168962Spjd struct vnode *a_vp; 3452168962Spjd struct thread *a_td; 3453168962Spjd } */ *ap; 3454168962Spjd{ 3455169025Spjd vnode_t *vp = ap->a_vp; 3456168962Spjd znode_t *zp = VTOZ(vp); 3457169025Spjd zfsvfs_t *zfsvfs; 3458169025Spjd int rele = 1; 3459168962Spjd 3460169025Spjd ASSERT(zp != NULL); 3461169025Spjd 3462168962Spjd /* 3463168962Spjd * Destroy the vm object and flush associated pages. 3464168962Spjd */ 3465168962Spjd vnode_destroy_vobject(vp); 3466169025Spjd 3467169025Spjd mutex_enter(&zp->z_lock); 3468169025Spjd ASSERT(zp->z_phys); 3469169025Spjd ASSERT(zp->z_dbuf_held); 3470169025Spjd zfsvfs = zp->z_zfsvfs; 3471169025Spjd if (!zp->z_unlinked) { 3472169025Spjd zp->z_dbuf_held = 0; 3473169025Spjd ZTOV(zp) = NULL; 3474169025Spjd mutex_exit(&zp->z_lock); 3475169025Spjd dmu_buf_rele(zp->z_dbuf, NULL); 3476169025Spjd } else { 3477169025Spjd mutex_exit(&zp->z_lock); 3478169025Spjd } 3479168962Spjd VI_LOCK(vp); 3480169025Spjd if (vp->v_count > 0) 3481169025Spjd rele = 0; 3482168962Spjd vp->v_data = NULL; 3483168962Spjd ASSERT(vp->v_holdcnt > 1); 3484168962Spjd vdropl(vp); 3485169025Spjd if (!zp->z_unlinked && rele) 3486169025Spjd VFS_RELE(zfsvfs->z_vfs); 3487168962Spjd return (0); 3488168962Spjd} 3489168962Spjd 3490168962Spjdstatic int 3491168962Spjdzfs_freebsd_fid(ap) 3492168962Spjd struct vop_fid_args /* { 3493168962Spjd struct vnode *a_vp; 3494168962Spjd struct fid *a_fid; 3495168962Spjd } */ *ap; 3496168962Spjd{ 3497168962Spjd 3498168962Spjd return (zfs_fid(ap->a_vp, (void *)ap->a_fid)); 3499168962Spjd} 3500168962Spjd 3501168962Spjdstatic int 3502168962Spjdzfs_freebsd_pathconf(ap) 3503168962Spjd struct vop_pathconf_args /* { 3504168962Spjd struct vnode *a_vp; 3505168962Spjd int a_name; 3506168962Spjd register_t *a_retval; 3507168962Spjd } */ *ap; 3508168962Spjd{ 3509168962Spjd ulong_t val; 3510168962Spjd int error; 3511168962Spjd 3512168962Spjd error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred); 3513168962Spjd if (error == 0) 3514168962Spjd *ap->a_retval = val; 3515168962Spjd else if (error == EOPNOTSUPP) 3516168962Spjd error = vop_stdpathconf(ap); 3517168962Spjd return (error); 3518168962Spjd} 3519168962Spjd 3520168404Spjd/* 3521168404Spjd * Advisory record locking support 3522168404Spjd */ 3523168404Spjdstatic int 3524168962Spjdzfs_freebsd_advlock(ap) 3525168404Spjd struct vop_advlock_args /* { 3526168404Spjd struct vnode *a_vp; 3527168404Spjd caddr_t a_id; 3528168404Spjd int a_op; 3529168404Spjd struct flock *a_fl; 3530168404Spjd int a_flags; 3531168404Spjd } */ *ap; 3532168404Spjd{ 3533168404Spjd znode_t *zp = VTOZ(ap->a_vp); 3534168404Spjd 3535168404Spjd return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size)); 3536168404Spjd} 3537168404Spjd 3538168404Spjdstruct vop_vector zfs_vnodeops; 3539168404Spjdstruct vop_vector zfs_fifoops; 3540168404Spjd 3541168404Spjdstruct vop_vector zfs_vnodeops = { 3542168404Spjd .vop_default = &default_vnodeops, 3543168962Spjd .vop_inactive = zfs_freebsd_inactive, 3544168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3545168962Spjd .vop_access = zfs_freebsd_access, 3546168404Spjd#ifdef FREEBSD_NAMECACHE 3547168404Spjd .vop_lookup = vfs_cache_lookup, 3548168962Spjd .vop_cachedlookup = zfs_freebsd_lookup, 3549168404Spjd#else 3550168962Spjd .vop_lookup = zfs_freebsd_lookup, 3551168404Spjd#endif 3552168962Spjd .vop_getattr = zfs_freebsd_getattr, 3553168962Spjd .vop_setattr = zfs_freebsd_setattr, 3554168962Spjd .vop_create = zfs_freebsd_create, 3555168962Spjd .vop_mknod = zfs_freebsd_create, 3556168962Spjd .vop_mkdir = zfs_freebsd_mkdir, 3557168962Spjd .vop_readdir = zfs_freebsd_readdir, 3558168962Spjd .vop_fsync = zfs_freebsd_fsync, 3559168962Spjd .vop_open = zfs_freebsd_open, 3560168962Spjd .vop_close = zfs_freebsd_close, 3561168962Spjd .vop_rmdir = zfs_freebsd_rmdir, 3562168962Spjd .vop_ioctl = zfs_freebsd_ioctl, 3563168962Spjd .vop_link = zfs_freebsd_link, 3564168962Spjd .vop_symlink = zfs_freebsd_symlink, 3565168962Spjd .vop_readlink = zfs_freebsd_readlink, 3566168962Spjd .vop_read = zfs_freebsd_read, 3567168962Spjd .vop_write = zfs_freebsd_write, 3568168962Spjd .vop_remove = zfs_freebsd_remove, 3569168962Spjd .vop_rename = zfs_freebsd_rename, 3570168962Spjd .vop_advlock = zfs_freebsd_advlock, 3571168962Spjd .vop_pathconf = zfs_freebsd_pathconf, 3572168404Spjd .vop_bmap = VOP_EOPNOTSUPP, 3573168962Spjd .vop_fid = zfs_freebsd_fid, 3574168404Spjd}; 3575168404Spjd 3576168404Spjdstruct vop_vector zfs_fifoops = { 3577168404Spjd .vop_default = &fifo_specops, 3578168404Spjd .vop_fsync = VOP_PANIC, 3579168962Spjd .vop_access = zfs_freebsd_access, 3580168962Spjd .vop_getattr = zfs_freebsd_getattr, 3581168962Spjd .vop_inactive = zfs_freebsd_inactive, 3582168404Spjd .vop_read = VOP_PANIC, 3583168962Spjd .vop_reclaim = zfs_freebsd_reclaim, 3584168962Spjd .vop_setattr = zfs_freebsd_setattr, 3585168404Spjd .vop_write = VOP_PANIC, 3586168962Spjd .vop_fid = zfs_freebsd_fid, 3587168404Spjd}; 3588