1/* 2 * Copyright (c) 2000-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29/* 30 * Copyright (c) 1989, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Rick Macklem at The University of Guelph. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 65 * FreeBSD-Id: nfs_vnops.c,v 1.72 1997/11/07 09:20:48 phk Exp $ 66 */ 67 68 69/* 70 * vnode op calls for Sun NFS version 2 and 3 71 */ 72#include <sys/param.h> 73#include <sys/kernel.h> 74#include <sys/systm.h> 75#include <sys/resourcevar.h> 76#include <sys/proc_internal.h> 77#include <sys/kauth.h> 78#include <sys/mount_internal.h> 79#include <sys/malloc.h> 80#include <sys/kpi_mbuf.h> 81#include <sys/conf.h> 82#include <sys/vnode_internal.h> 83#include <sys/dirent.h> 84#include <sys/fcntl.h> 85#include <sys/lockf.h> 86#include <sys/ubc_internal.h> 87#include <sys/attr.h> 88#include <sys/signalvar.h> 89#include <sys/uio_internal.h> 90 91#include <vfs/vfs_support.h> 92 93#include <sys/vm.h> 94 95#include <sys/time.h> 96#include <kern/clock.h> 97#include <libkern/OSAtomic.h> 98 99#include <miscfs/fifofs/fifo.h> 100#include <miscfs/specfs/specdev.h> 101 102#include <nfs/rpcv2.h> 103#include <nfs/nfsproto.h> 104#include <nfs/nfs.h> 105#include <nfs/nfsnode.h> 106#include <nfs/nfs_gss.h> 107#include <nfs/nfsmount.h> 108#include <nfs/nfs_lock.h> 109#include <nfs/xdr_subs.h> 110#include <nfs/nfsm_subs.h> 111 112#include <net/if.h> 113#include <netinet/in.h> 114#include <netinet/in_var.h> 115 116#include <vm/vm_kern.h> 117#include <vm/vm_pageout.h> 118 119#include <kern/task.h> 120#include <kern/sched_prim.h> 121 122#define NFS_VNOP_DBG(...) NFS_DBG(NFS_FAC_VNOP, 7, ## __VA_ARGS__) 123#define DEFAULT_READLINK_NOCACHE 0 124 125/* 126 * NFS vnode ops 127 */ 128int nfs_vnop_lookup(struct vnop_lookup_args *); 129int nfsspec_vnop_read(struct vnop_read_args *); 130int nfsspec_vnop_write(struct vnop_write_args *); 131int nfsspec_vnop_close(struct vnop_close_args *); 132#if FIFO 133int nfsfifo_vnop_read(struct vnop_read_args *); 134int nfsfifo_vnop_write(struct vnop_write_args *); 135int nfsfifo_vnop_close(struct vnop_close_args *); 136#endif 137int nfs_vnop_ioctl(struct vnop_ioctl_args *); 138int nfs_vnop_select(struct vnop_select_args *); 139int nfs_vnop_setattr(struct vnop_setattr_args *); 140int nfs_vnop_fsync(struct vnop_fsync_args *); 141int nfs_vnop_rename(struct vnop_rename_args *); 142int nfs_vnop_readdir(struct vnop_readdir_args *); 143int nfs_vnop_readlink(struct vnop_readlink_args *); 144int nfs_vnop_pathconf(struct vnop_pathconf_args *); 145int nfs_vnop_pagein(struct vnop_pagein_args *); 146int nfs_vnop_pageout(struct vnop_pageout_args *); 147int nfs_vnop_blktooff(struct vnop_blktooff_args *); 148int nfs_vnop_offtoblk(struct vnop_offtoblk_args *); 149int nfs_vnop_blockmap(struct vnop_blockmap_args *); 150int nfs_vnop_monitor(struct vnop_monitor_args *); 151 152int nfs3_vnop_create(struct vnop_create_args *); 153int nfs3_vnop_mknod(struct vnop_mknod_args *); 154int nfs3_vnop_getattr(struct vnop_getattr_args *); 155int nfs3_vnop_link(struct vnop_link_args *); 156int nfs3_vnop_mkdir(struct vnop_mkdir_args *); 157int nfs3_vnop_rmdir(struct vnop_rmdir_args *); 158int nfs3_vnop_symlink(struct vnop_symlink_args *); 159 160vnop_t **nfsv2_vnodeop_p; 161static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 162 { &vnop_default_desc, (vnop_t *)vn_default_error }, 163 { &vnop_lookup_desc, (vnop_t *)nfs_vnop_lookup }, /* lookup */ 164 { &vnop_create_desc, (vnop_t *)nfs3_vnop_create }, /* create */ 165 { &vnop_mknod_desc, (vnop_t *)nfs3_vnop_mknod }, /* mknod */ 166 { &vnop_open_desc, (vnop_t *)nfs_vnop_open }, /* open */ 167 { &vnop_close_desc, (vnop_t *)nfs_vnop_close }, /* close */ 168 { &vnop_access_desc, (vnop_t *)nfs_vnop_access }, /* access */ 169 { &vnop_getattr_desc, (vnop_t *)nfs3_vnop_getattr }, /* getattr */ 170 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 171 { &vnop_read_desc, (vnop_t *)nfs_vnop_read }, /* read */ 172 { &vnop_write_desc, (vnop_t *)nfs_vnop_write }, /* write */ 173 { &vnop_ioctl_desc, (vnop_t *)nfs_vnop_ioctl }, /* ioctl */ 174 { &vnop_select_desc, (vnop_t *)nfs_vnop_select }, /* select */ 175 { &vnop_revoke_desc, (vnop_t *)nfs_vnop_revoke }, /* revoke */ 176 { &vnop_mmap_desc, (vnop_t *)nfs_vnop_mmap }, /* mmap */ 177 { &vnop_mnomap_desc, (vnop_t *)nfs_vnop_mnomap }, /* mnomap */ 178 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 179 { &vnop_remove_desc, (vnop_t *)nfs_vnop_remove }, /* remove */ 180 { &vnop_link_desc, (vnop_t *)nfs3_vnop_link }, /* link */ 181 { &vnop_rename_desc, (vnop_t *)nfs_vnop_rename }, /* rename */ 182 { &vnop_mkdir_desc, (vnop_t *)nfs3_vnop_mkdir }, /* mkdir */ 183 { &vnop_rmdir_desc, (vnop_t *)nfs3_vnop_rmdir }, /* rmdir */ 184 { &vnop_symlink_desc, (vnop_t *)nfs3_vnop_symlink }, /* symlink */ 185 { &vnop_readdir_desc, (vnop_t *)nfs_vnop_readdir }, /* readdir */ 186 { &vnop_readlink_desc, (vnop_t *)nfs_vnop_readlink }, /* readlink */ 187 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 188 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 189 { &vnop_strategy_desc, (vnop_t *)err_strategy }, /* strategy */ 190 { &vnop_pathconf_desc, (vnop_t *)nfs_vnop_pathconf }, /* pathconf */ 191 { &vnop_advlock_desc, (vnop_t *)nfs_vnop_advlock }, /* advlock */ 192 { &vnop_bwrite_desc, (vnop_t *)err_bwrite }, /* bwrite */ 193 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 194 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 195 { &vnop_copyfile_desc, (vnop_t *)err_copyfile }, /* Copyfile */ 196 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 197 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 198 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 199 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 200 { NULL, NULL } 201}; 202struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 203 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 204 205vnop_t **nfsv4_vnodeop_p; 206static struct vnodeopv_entry_desc nfsv4_vnodeop_entries[] = { 207 { &vnop_default_desc, (vnop_t *)vn_default_error }, 208 { &vnop_lookup_desc, (vnop_t *)nfs_vnop_lookup }, /* lookup */ 209 { &vnop_create_desc, (vnop_t *)nfs4_vnop_create }, /* create */ 210 { &vnop_mknod_desc, (vnop_t *)nfs4_vnop_mknod }, /* mknod */ 211 { &vnop_open_desc, (vnop_t *)nfs_vnop_open }, /* open */ 212 { &vnop_close_desc, (vnop_t *)nfs_vnop_close }, /* close */ 213 { &vnop_access_desc, (vnop_t *)nfs_vnop_access }, /* access */ 214 { &vnop_getattr_desc, (vnop_t *)nfs4_vnop_getattr }, /* getattr */ 215 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 216 { &vnop_read_desc, (vnop_t *)nfs_vnop_read }, /* read */ 217 { &vnop_write_desc, (vnop_t *)nfs_vnop_write }, /* write */ 218 { &vnop_ioctl_desc, (vnop_t *)nfs_vnop_ioctl }, /* ioctl */ 219 { &vnop_select_desc, (vnop_t *)nfs_vnop_select }, /* select */ 220 { &vnop_revoke_desc, (vnop_t *)nfs_vnop_revoke }, /* revoke */ 221 { &vnop_mmap_desc, (vnop_t *)nfs_vnop_mmap }, /* mmap */ 222 { &vnop_mnomap_desc, (vnop_t *)nfs_vnop_mnomap }, /* mnomap */ 223 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 224 { &vnop_remove_desc, (vnop_t *)nfs_vnop_remove }, /* remove */ 225 { &vnop_link_desc, (vnop_t *)nfs4_vnop_link }, /* link */ 226 { &vnop_rename_desc, (vnop_t *)nfs_vnop_rename }, /* rename */ 227 { &vnop_mkdir_desc, (vnop_t *)nfs4_vnop_mkdir }, /* mkdir */ 228 { &vnop_rmdir_desc, (vnop_t *)nfs4_vnop_rmdir }, /* rmdir */ 229 { &vnop_symlink_desc, (vnop_t *)nfs4_vnop_symlink }, /* symlink */ 230 { &vnop_readdir_desc, (vnop_t *)nfs_vnop_readdir }, /* readdir */ 231 { &vnop_readlink_desc, (vnop_t *)nfs_vnop_readlink }, /* readlink */ 232 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 233 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 234 { &vnop_strategy_desc, (vnop_t *)err_strategy }, /* strategy */ 235 { &vnop_pathconf_desc, (vnop_t *)nfs_vnop_pathconf }, /* pathconf */ 236 { &vnop_advlock_desc, (vnop_t *)nfs_vnop_advlock }, /* advlock */ 237 { &vnop_bwrite_desc, (vnop_t *)err_bwrite }, /* bwrite */ 238 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 239 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 240 { &vnop_copyfile_desc, (vnop_t *)err_copyfile }, /* Copyfile */ 241 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 242 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 243 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 244 { &vnop_getxattr_desc, (vnop_t *)nfs4_vnop_getxattr }, /* getxattr */ 245 { &vnop_setxattr_desc, (vnop_t *)nfs4_vnop_setxattr }, /* setxattr */ 246 { &vnop_removexattr_desc, (vnop_t *)nfs4_vnop_removexattr },/* removexattr */ 247 { &vnop_listxattr_desc, (vnop_t *)nfs4_vnop_listxattr },/* listxattr */ 248#if NAMEDSTREAMS 249 { &vnop_getnamedstream_desc, (vnop_t *)nfs4_vnop_getnamedstream }, /* getnamedstream */ 250 { &vnop_makenamedstream_desc, (vnop_t *)nfs4_vnop_makenamedstream }, /* makenamedstream */ 251 { &vnop_removenamedstream_desc, (vnop_t *)nfs4_vnop_removenamedstream },/* removenamedstream */ 252#endif 253 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 254 { NULL, NULL } 255}; 256struct vnodeopv_desc nfsv4_vnodeop_opv_desc = 257 { &nfsv4_vnodeop_p, nfsv4_vnodeop_entries }; 258 259/* 260 * Special device vnode ops 261 */ 262vnop_t **spec_nfsv2nodeop_p; 263static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 264 { &vnop_default_desc, (vnop_t *)vn_default_error }, 265 { &vnop_lookup_desc, (vnop_t *)spec_lookup }, /* lookup */ 266 { &vnop_create_desc, (vnop_t *)spec_create }, /* create */ 267 { &vnop_mknod_desc, (vnop_t *)spec_mknod }, /* mknod */ 268 { &vnop_open_desc, (vnop_t *)spec_open }, /* open */ 269 { &vnop_close_desc, (vnop_t *)nfsspec_vnop_close }, /* close */ 270 { &vnop_getattr_desc, (vnop_t *)nfs3_vnop_getattr }, /* getattr */ 271 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 272 { &vnop_read_desc, (vnop_t *)nfsspec_vnop_read }, /* read */ 273 { &vnop_write_desc, (vnop_t *)nfsspec_vnop_write }, /* write */ 274 { &vnop_ioctl_desc, (vnop_t *)spec_ioctl }, /* ioctl */ 275 { &vnop_select_desc, (vnop_t *)spec_select }, /* select */ 276 { &vnop_revoke_desc, (vnop_t *)spec_revoke }, /* revoke */ 277 { &vnop_mmap_desc, (vnop_t *)spec_mmap }, /* mmap */ 278 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 279 { &vnop_remove_desc, (vnop_t *)spec_remove }, /* remove */ 280 { &vnop_link_desc, (vnop_t *)spec_link }, /* link */ 281 { &vnop_rename_desc, (vnop_t *)spec_rename }, /* rename */ 282 { &vnop_mkdir_desc, (vnop_t *)spec_mkdir }, /* mkdir */ 283 { &vnop_rmdir_desc, (vnop_t *)spec_rmdir }, /* rmdir */ 284 { &vnop_symlink_desc, (vnop_t *)spec_symlink }, /* symlink */ 285 { &vnop_readdir_desc, (vnop_t *)spec_readdir }, /* readdir */ 286 { &vnop_readlink_desc, (vnop_t *)spec_readlink }, /* readlink */ 287 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 288 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 289 { &vnop_strategy_desc, (vnop_t *)spec_strategy }, /* strategy */ 290 { &vnop_pathconf_desc, (vnop_t *)spec_pathconf }, /* pathconf */ 291 { &vnop_advlock_desc, (vnop_t *)spec_advlock }, /* advlock */ 292 { &vnop_bwrite_desc, (vnop_t *)vn_bwrite }, /* bwrite */ 293 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 294 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 295 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 296 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 297 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 298 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 299 { NULL, NULL } 300}; 301struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 302 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 303vnop_t **spec_nfsv4nodeop_p; 304static struct vnodeopv_entry_desc spec_nfsv4nodeop_entries[] = { 305 { &vnop_default_desc, (vnop_t *)vn_default_error }, 306 { &vnop_lookup_desc, (vnop_t *)spec_lookup }, /* lookup */ 307 { &vnop_create_desc, (vnop_t *)spec_create }, /* create */ 308 { &vnop_mknod_desc, (vnop_t *)spec_mknod }, /* mknod */ 309 { &vnop_open_desc, (vnop_t *)spec_open }, /* open */ 310 { &vnop_close_desc, (vnop_t *)nfsspec_vnop_close }, /* close */ 311 { &vnop_getattr_desc, (vnop_t *)nfs4_vnop_getattr }, /* getattr */ 312 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 313 { &vnop_read_desc, (vnop_t *)nfsspec_vnop_read }, /* read */ 314 { &vnop_write_desc, (vnop_t *)nfsspec_vnop_write }, /* write */ 315 { &vnop_ioctl_desc, (vnop_t *)spec_ioctl }, /* ioctl */ 316 { &vnop_select_desc, (vnop_t *)spec_select }, /* select */ 317 { &vnop_revoke_desc, (vnop_t *)spec_revoke }, /* revoke */ 318 { &vnop_mmap_desc, (vnop_t *)spec_mmap }, /* mmap */ 319 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 320 { &vnop_remove_desc, (vnop_t *)spec_remove }, /* remove */ 321 { &vnop_link_desc, (vnop_t *)spec_link }, /* link */ 322 { &vnop_rename_desc, (vnop_t *)spec_rename }, /* rename */ 323 { &vnop_mkdir_desc, (vnop_t *)spec_mkdir }, /* mkdir */ 324 { &vnop_rmdir_desc, (vnop_t *)spec_rmdir }, /* rmdir */ 325 { &vnop_symlink_desc, (vnop_t *)spec_symlink }, /* symlink */ 326 { &vnop_readdir_desc, (vnop_t *)spec_readdir }, /* readdir */ 327 { &vnop_readlink_desc, (vnop_t *)spec_readlink }, /* readlink */ 328 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 329 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 330 { &vnop_strategy_desc, (vnop_t *)spec_strategy }, /* strategy */ 331 { &vnop_pathconf_desc, (vnop_t *)spec_pathconf }, /* pathconf */ 332 { &vnop_advlock_desc, (vnop_t *)spec_advlock }, /* advlock */ 333 { &vnop_bwrite_desc, (vnop_t *)vn_bwrite }, /* bwrite */ 334 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 335 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 336 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 337 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 338 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 339 { &vnop_getxattr_desc, (vnop_t *)nfs4_vnop_getxattr }, /* getxattr */ 340 { &vnop_setxattr_desc, (vnop_t *)nfs4_vnop_setxattr }, /* setxattr */ 341 { &vnop_removexattr_desc, (vnop_t *)nfs4_vnop_removexattr },/* removexattr */ 342 { &vnop_listxattr_desc, (vnop_t *)nfs4_vnop_listxattr },/* listxattr */ 343#if NAMEDSTREAMS 344 { &vnop_getnamedstream_desc, (vnop_t *)nfs4_vnop_getnamedstream }, /* getnamedstream */ 345 { &vnop_makenamedstream_desc, (vnop_t *)nfs4_vnop_makenamedstream }, /* makenamedstream */ 346 { &vnop_removenamedstream_desc, (vnop_t *)nfs4_vnop_removenamedstream },/* removenamedstream */ 347#endif 348 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 349 { NULL, NULL } 350}; 351struct vnodeopv_desc spec_nfsv4nodeop_opv_desc = 352 { &spec_nfsv4nodeop_p, spec_nfsv4nodeop_entries }; 353 354#if FIFO 355vnop_t **fifo_nfsv2nodeop_p; 356static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 357 { &vnop_default_desc, (vnop_t *)vn_default_error }, 358 { &vnop_lookup_desc, (vnop_t *)fifo_lookup }, /* lookup */ 359 { &vnop_create_desc, (vnop_t *)fifo_create }, /* create */ 360 { &vnop_mknod_desc, (vnop_t *)fifo_mknod }, /* mknod */ 361 { &vnop_open_desc, (vnop_t *)fifo_open }, /* open */ 362 { &vnop_close_desc, (vnop_t *)nfsfifo_vnop_close }, /* close */ 363 { &vnop_getattr_desc, (vnop_t *)nfs3_vnop_getattr }, /* getattr */ 364 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 365 { &vnop_read_desc, (vnop_t *)nfsfifo_vnop_read }, /* read */ 366 { &vnop_write_desc, (vnop_t *)nfsfifo_vnop_write }, /* write */ 367 { &vnop_ioctl_desc, (vnop_t *)fifo_ioctl }, /* ioctl */ 368 { &vnop_select_desc, (vnop_t *)fifo_select }, /* select */ 369 { &vnop_revoke_desc, (vnop_t *)fifo_revoke }, /* revoke */ 370 { &vnop_mmap_desc, (vnop_t *)fifo_mmap }, /* mmap */ 371 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 372 { &vnop_remove_desc, (vnop_t *)fifo_remove }, /* remove */ 373 { &vnop_link_desc, (vnop_t *)fifo_link }, /* link */ 374 { &vnop_rename_desc, (vnop_t *)fifo_rename }, /* rename */ 375 { &vnop_mkdir_desc, (vnop_t *)fifo_mkdir }, /* mkdir */ 376 { &vnop_rmdir_desc, (vnop_t *)fifo_rmdir }, /* rmdir */ 377 { &vnop_symlink_desc, (vnop_t *)fifo_symlink }, /* symlink */ 378 { &vnop_readdir_desc, (vnop_t *)fifo_readdir }, /* readdir */ 379 { &vnop_readlink_desc, (vnop_t *)fifo_readlink }, /* readlink */ 380 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 381 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 382 { &vnop_strategy_desc, (vnop_t *)fifo_strategy }, /* strategy */ 383 { &vnop_pathconf_desc, (vnop_t *)fifo_pathconf }, /* pathconf */ 384 { &vnop_advlock_desc, (vnop_t *)fifo_advlock }, /* advlock */ 385 { &vnop_bwrite_desc, (vnop_t *)vn_bwrite }, /* bwrite */ 386 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 387 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 388 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 389 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 390 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 391 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 392 { NULL, NULL } 393}; 394struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 395 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 396 397vnop_t **fifo_nfsv4nodeop_p; 398static struct vnodeopv_entry_desc fifo_nfsv4nodeop_entries[] = { 399 { &vnop_default_desc, (vnop_t *)vn_default_error }, 400 { &vnop_lookup_desc, (vnop_t *)fifo_lookup }, /* lookup */ 401 { &vnop_create_desc, (vnop_t *)fifo_create }, /* create */ 402 { &vnop_mknod_desc, (vnop_t *)fifo_mknod }, /* mknod */ 403 { &vnop_open_desc, (vnop_t *)fifo_open }, /* open */ 404 { &vnop_close_desc, (vnop_t *)nfsfifo_vnop_close }, /* close */ 405 { &vnop_getattr_desc, (vnop_t *)nfs4_vnop_getattr }, /* getattr */ 406 { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */ 407 { &vnop_read_desc, (vnop_t *)nfsfifo_vnop_read }, /* read */ 408 { &vnop_write_desc, (vnop_t *)nfsfifo_vnop_write }, /* write */ 409 { &vnop_ioctl_desc, (vnop_t *)fifo_ioctl }, /* ioctl */ 410 { &vnop_select_desc, (vnop_t *)fifo_select }, /* select */ 411 { &vnop_revoke_desc, (vnop_t *)fifo_revoke }, /* revoke */ 412 { &vnop_mmap_desc, (vnop_t *)fifo_mmap }, /* mmap */ 413 { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */ 414 { &vnop_remove_desc, (vnop_t *)fifo_remove }, /* remove */ 415 { &vnop_link_desc, (vnop_t *)fifo_link }, /* link */ 416 { &vnop_rename_desc, (vnop_t *)fifo_rename }, /* rename */ 417 { &vnop_mkdir_desc, (vnop_t *)fifo_mkdir }, /* mkdir */ 418 { &vnop_rmdir_desc, (vnop_t *)fifo_rmdir }, /* rmdir */ 419 { &vnop_symlink_desc, (vnop_t *)fifo_symlink }, /* symlink */ 420 { &vnop_readdir_desc, (vnop_t *)fifo_readdir }, /* readdir */ 421 { &vnop_readlink_desc, (vnop_t *)fifo_readlink }, /* readlink */ 422 { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */ 423 { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */ 424 { &vnop_strategy_desc, (vnop_t *)fifo_strategy }, /* strategy */ 425 { &vnop_pathconf_desc, (vnop_t *)fifo_pathconf }, /* pathconf */ 426 { &vnop_advlock_desc, (vnop_t *)fifo_advlock }, /* advlock */ 427 { &vnop_bwrite_desc, (vnop_t *)vn_bwrite }, /* bwrite */ 428 { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */ 429 { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */ 430 { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */ 431 { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */ 432 { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */ 433 { &vnop_getxattr_desc, (vnop_t *)nfs4_vnop_getxattr }, /* getxattr */ 434 { &vnop_setxattr_desc, (vnop_t *)nfs4_vnop_setxattr }, /* setxattr */ 435 { &vnop_removexattr_desc, (vnop_t *)nfs4_vnop_removexattr },/* removexattr */ 436 { &vnop_listxattr_desc, (vnop_t *)nfs4_vnop_listxattr },/* listxattr */ 437#if NAMEDSTREAMS 438 { &vnop_getnamedstream_desc, (vnop_t *)nfs4_vnop_getnamedstream }, /* getnamedstream */ 439 { &vnop_makenamedstream_desc, (vnop_t *)nfs4_vnop_makenamedstream }, /* makenamedstream */ 440 { &vnop_removenamedstream_desc, (vnop_t *)nfs4_vnop_removenamedstream },/* removenamedstream */ 441#endif 442 { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */ 443 { NULL, NULL } 444}; 445struct vnodeopv_desc fifo_nfsv4nodeop_opv_desc = 446 { &fifo_nfsv4nodeop_p, fifo_nfsv4nodeop_entries }; 447#endif /* FIFO */ 448 449int nfs_sillyrename(nfsnode_t,nfsnode_t,struct componentname *,vfs_context_t); 450int nfs_getattr_internal(nfsnode_t, struct nfs_vattr *, vfs_context_t, int); 451int nfs_refresh_fh(nfsnode_t, vfs_context_t); 452 453/* 454 * Find the slot in the access cache for this UID. 455 * If adding and no existing slot is found, reuse slots in FIFO order. 456 * The index of the next slot to use is kept in the last entry of the n_access array. 457 */ 458int 459nfs_node_access_slot(nfsnode_t np, uid_t uid, int add) 460{ 461 int slot; 462 463 for (slot=0; slot < NFS_ACCESS_CACHE_SIZE; slot++) 464 if (np->n_accessuid[slot] == uid) 465 break; 466 if (slot == NFS_ACCESS_CACHE_SIZE) { 467 if (!add) 468 return (-1); 469 slot = np->n_access[NFS_ACCESS_CACHE_SIZE]; 470 np->n_access[NFS_ACCESS_CACHE_SIZE] = (slot + 1) % NFS_ACCESS_CACHE_SIZE; 471 } 472 return (slot); 473} 474 475int 476nfs3_access_rpc(nfsnode_t np, u_int32_t *access, int rpcflags, vfs_context_t ctx) 477{ 478 int error = 0, lockerror = ENOENT, status, slot; 479 uint32_t access_result = 0; 480 u_int64_t xid; 481 struct nfsm_chain nmreq, nmrep; 482 struct timeval now; 483 uid_t uid; 484 485 nfsm_chain_null(&nmreq); 486 nfsm_chain_null(&nmrep); 487 488 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(NFS_VER3) + NFSX_UNSIGNED); 489 nfsm_chain_add_fh(error, &nmreq, NFS_VER3, np->n_fhp, np->n_fhsize); 490 nfsm_chain_add_32(error, &nmreq, *access); 491 nfsm_chain_build_done(error, &nmreq); 492 nfsmout_if(error); 493 error = nfs_request2(np, NULL, &nmreq, NFSPROC_ACCESS, 494 vfs_context_thread(ctx), vfs_context_ucred(ctx), 495 NULL, rpcflags, &nmrep, &xid, &status); 496 if ((lockerror = nfs_node_lock(np))) 497 error = lockerror; 498 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 499 if (!error) 500 error = status; 501 nfsm_chain_get_32(error, &nmrep, access_result); 502 nfsmout_if(error); 503 504 uid = kauth_cred_getuid(vfs_context_ucred(ctx)); 505 slot = nfs_node_access_slot(np, uid, 1); 506 np->n_accessuid[slot] = uid; 507 microuptime(&now); 508 np->n_accessstamp[slot] = now.tv_sec; 509 np->n_access[slot] = access_result; 510 511 /* 512 * If we asked for DELETE but didn't get it, the server 513 * may simply not support returning that bit (possible 514 * on UNIX systems). So, we'll assume that it is OK, 515 * and just let any subsequent delete action fail if it 516 * really isn't deletable. 517 */ 518 if ((*access & NFS_ACCESS_DELETE) && 519 !(np->n_access[slot] & NFS_ACCESS_DELETE)) 520 np->n_access[slot] |= NFS_ACCESS_DELETE; 521 /* ".zfs" subdirectories may erroneously give a denied answer for add/remove */ 522 if (nfs_access_dotzfs && (np->n_flag & NISDOTZFSCHILD)) 523 np->n_access[slot] |= (NFS_ACCESS_MODIFY|NFS_ACCESS_EXTEND|NFS_ACCESS_DELETE); 524 /* pass back the access returned with this request */ 525 *access = np->n_access[slot]; 526nfsmout: 527 if (!lockerror) 528 nfs_node_unlock(np); 529 nfsm_chain_cleanup(&nmreq); 530 nfsm_chain_cleanup(&nmrep); 531 return (error); 532} 533 534/* 535 * NFS access vnode op. 536 * For NFS version 2, just return ok. File accesses may fail later. 537 * For NFS version 3+, use the access RPC to check accessibility. If file 538 * permissions are changed on the server, accesses might still fail later. 539 */ 540int 541nfs_vnop_access( 542 struct vnop_access_args /* { 543 struct vnodeop_desc *a_desc; 544 vnode_t a_vp; 545 int a_action; 546 vfs_context_t a_context; 547 } */ *ap) 548{ 549 vfs_context_t ctx = ap->a_context; 550 vnode_t vp = ap->a_vp; 551 int error = 0, slot, dorpc, rpcflags = 0; 552 u_int32_t access, waccess; 553 nfsnode_t np = VTONFS(vp); 554 struct nfsmount *nmp; 555 int nfsvers; 556 struct timeval now; 557 uid_t uid; 558 559 nmp = VTONMP(vp); 560 if (nfs_mount_gone(nmp)) 561 return (ENXIO); 562 nfsvers = nmp->nm_vers; 563 564 if (nfsvers == NFS_VER2) { 565 if ((ap->a_action & KAUTH_VNODE_WRITE_RIGHTS) && 566 vfs_isrdonly(vnode_mount(vp))) 567 return (EROFS); 568 return (0); 569 } 570 571 /* 572 * For NFS v3, do an access rpc, otherwise you are stuck emulating 573 * ufs_access() locally using the vattr. This may not be correct, 574 * since the server may apply other access criteria such as 575 * client uid-->server uid mapping that we do not know about, but 576 * this is better than just returning anything that is lying about 577 * in the cache. 578 */ 579 580 /* 581 * Convert KAUTH primitives to NFS access rights. 582 */ 583 access = 0; 584 if (vnode_isdir(vp)) { 585 /* directory */ 586 if (ap->a_action & 587 (KAUTH_VNODE_LIST_DIRECTORY | 588 KAUTH_VNODE_READ_EXTATTRIBUTES)) 589 access |= NFS_ACCESS_READ; 590 if (ap->a_action & KAUTH_VNODE_SEARCH) 591 access |= NFS_ACCESS_LOOKUP; 592 if (ap->a_action & 593 (KAUTH_VNODE_ADD_FILE | 594 KAUTH_VNODE_ADD_SUBDIRECTORY)) 595 access |= NFS_ACCESS_MODIFY | NFS_ACCESS_EXTEND; 596 if (ap->a_action & KAUTH_VNODE_DELETE_CHILD) 597 access |= NFS_ACCESS_MODIFY; 598 } else { 599 /* file */ 600 if (ap->a_action & 601 (KAUTH_VNODE_READ_DATA | 602 KAUTH_VNODE_READ_EXTATTRIBUTES)) 603 access |= NFS_ACCESS_READ; 604 if (ap->a_action & KAUTH_VNODE_WRITE_DATA) 605 access |= NFS_ACCESS_MODIFY | NFS_ACCESS_EXTEND; 606 if (ap->a_action & KAUTH_VNODE_APPEND_DATA) 607 access |= NFS_ACCESS_EXTEND; 608 if (ap->a_action & KAUTH_VNODE_EXECUTE) 609 access |= NFS_ACCESS_EXECUTE; 610 } 611 /* common */ 612 if (ap->a_action & KAUTH_VNODE_DELETE) 613 access |= NFS_ACCESS_DELETE; 614 if (ap->a_action & 615 (KAUTH_VNODE_WRITE_ATTRIBUTES | 616 KAUTH_VNODE_WRITE_EXTATTRIBUTES | 617 KAUTH_VNODE_WRITE_SECURITY)) 618 access |= NFS_ACCESS_MODIFY; 619 /* XXX this is pretty dubious */ 620 if (ap->a_action & KAUTH_VNODE_CHANGE_OWNER) 621 access |= NFS_ACCESS_MODIFY; 622 623 /* if caching, always ask for every right */ 624 if (nfs_access_cache_timeout > 0) { 625 waccess = NFS_ACCESS_READ | NFS_ACCESS_MODIFY | 626 NFS_ACCESS_EXTEND | NFS_ACCESS_EXECUTE | 627 NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP; 628 } else { 629 waccess = access; 630 } 631 632 if ((error = nfs_node_lock(np))) 633 return (error); 634 635 /* 636 * Does our cached result allow us to give a definite yes to 637 * this request? 638 */ 639 uid = kauth_cred_getuid(vfs_context_ucred(ctx)); 640 slot = nfs_node_access_slot(np, uid, 0); 641 dorpc = 1; 642 if (access == 0) { 643 /* not asking for any rights understood by NFS, so don't bother doing an RPC */ 644 /* OSAddAtomic(1, &nfsstats.accesscache_hits); */ 645 dorpc = 0; 646 waccess = 0; 647 } else if (NACCESSVALID(np, slot)) { 648 microuptime(&now); 649 if (((now.tv_sec < (np->n_accessstamp[slot] + nfs_access_cache_timeout)) && 650 ((np->n_access[slot] & access) == access)) || nfs_use_cache(nmp)) { 651 /* OSAddAtomic(1, &nfsstats.accesscache_hits); */ 652 dorpc = 0; 653 waccess = np->n_access[slot]; 654 } 655 } 656 nfs_node_unlock(np); 657 if (dorpc) { 658 /* Either a no, or a don't know. Go to the wire. */ 659 /* OSAddAtomic(1, &nfsstats.accesscache_misses); */ 660 661 /* 662 * Allow an access call to timeout if we have it cached 663 * so we won't hang if the server isn't responding. 664 */ 665 if (NACCESSVALID(np, slot)) 666 rpcflags |= R_SOFT; 667 668 error = nmp->nm_funcs->nf_access_rpc(np, &waccess, rpcflags, ctx); 669 670 /* 671 * If the server didn't respond return the cached access. 672 */ 673 if ((error == ETIMEDOUT) && (rpcflags & R_SOFT)) { 674 error = 0; 675 waccess = np->n_access[slot]; 676 } 677 } 678 if (!error && ((waccess & access) != access)) 679 error = EACCES; 680 681 return (error); 682} 683 684 685/* 686 * NFS open vnode op 687 * 688 * Perform various update/invalidation checks and then add the 689 * open to the node. Regular files will have an open file structure 690 * on the node and, for NFSv4, perform an OPEN request on the server. 691 */ 692int 693nfs_vnop_open( 694 struct vnop_open_args /* { 695 struct vnodeop_desc *a_desc; 696 vnode_t a_vp; 697 int a_mode; 698 vfs_context_t a_context; 699 } */ *ap) 700{ 701 vfs_context_t ctx = ap->a_context; 702 vnode_t vp = ap->a_vp; 703 nfsnode_t np = VTONFS(vp); 704 struct nfsmount *nmp; 705 int error, accessMode, denyMode, opened = 0; 706 struct nfs_open_owner *noop = NULL; 707 struct nfs_open_file *nofp = NULL; 708 enum vtype vtype; 709 710 if (!(ap->a_mode & (FREAD|FWRITE))) 711 return (EINVAL); 712 713 nmp = VTONMP(vp); 714 if (nfs_mount_gone(nmp)) 715 return (ENXIO); 716 if (np->n_flag & NREVOKE) 717 return (EIO); 718 719 vtype = vnode_vtype(vp); 720 if ((vtype != VREG) && (vtype != VDIR) && (vtype != VLNK)) 721 return (EACCES); 722 723 /* First, check if we need to update/invalidate */ 724 if (ISSET(np->n_flag, NUPDATESIZE)) 725 nfs_data_update_size(np, 0); 726 if ((error = nfs_node_lock(np))) 727 return (error); 728 if (np->n_flag & NNEEDINVALIDATE) { 729 np->n_flag &= ~NNEEDINVALIDATE; 730 if (vtype == VDIR) 731 nfs_invaldir(np); 732 nfs_node_unlock(np); 733 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, ctx, 1); 734 if ((error = nfs_node_lock(np))) 735 return (error); 736 } 737 if (vtype == VREG) 738 np->n_lastrahead = -1; 739 if (np->n_flag & NMODIFIED) { 740 if (vtype == VDIR) 741 nfs_invaldir(np); 742 nfs_node_unlock(np); 743 if ((error = nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, ctx, 1))) 744 return (error); 745 } else { 746 nfs_node_unlock(np); 747 } 748 749 /* nfs_getattr() will check changed and purge caches */ 750 if ((error = nfs_getattr(np, NULL, ctx, NGA_UNCACHED))) 751 return (error); 752 753 if (vtype != VREG) { 754 /* Just mark that it was opened */ 755 lck_mtx_lock(&np->n_openlock); 756 np->n_openrefcnt++; 757 lck_mtx_unlock(&np->n_openlock); 758 return (0); 759 } 760 761 /* mode contains some combination of: FREAD, FWRITE, O_SHLOCK, O_EXLOCK */ 762 accessMode = 0; 763 if (ap->a_mode & FREAD) 764 accessMode |= NFS_OPEN_SHARE_ACCESS_READ; 765 if (ap->a_mode & FWRITE) 766 accessMode |= NFS_OPEN_SHARE_ACCESS_WRITE; 767 if (ap->a_mode & O_EXLOCK) 768 denyMode = NFS_OPEN_SHARE_DENY_BOTH; 769 else if (ap->a_mode & O_SHLOCK) 770 denyMode = NFS_OPEN_SHARE_DENY_WRITE; 771 else 772 denyMode = NFS_OPEN_SHARE_DENY_NONE; 773 // XXX don't do deny modes just yet (and never do it for !v4) 774 denyMode = NFS_OPEN_SHARE_DENY_NONE; 775 776 noop = nfs_open_owner_find(nmp, vfs_context_ucred(ctx), 1); 777 if (!noop) 778 return (ENOMEM); 779 780restart: 781 error = nfs_mount_state_in_use_start(nmp, vfs_context_thread(ctx)); 782 if (error) { 783 nfs_open_owner_rele(noop); 784 return (error); 785 } 786 if (np->n_flag & NREVOKE) { 787 error = EIO; 788 nfs_mount_state_in_use_end(nmp, 0); 789 nfs_open_owner_rele(noop); 790 return (error); 791 } 792 793 error = nfs_open_file_find(np, noop, &nofp, accessMode, denyMode, 1); 794 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_LOST)) { 795 NP(np, "nfs_vnop_open: LOST %d", kauth_cred_getuid(nofp->nof_owner->noo_cred)); 796 error = EIO; 797 } 798 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) { 799 nfs_mount_state_in_use_end(nmp, 0); 800 error = nfs4_reopen(nofp, vfs_context_thread(ctx)); 801 nofp = NULL; 802 if (!error) 803 goto restart; 804 } 805 if (!error) 806 error = nfs_open_file_set_busy(nofp, vfs_context_thread(ctx)); 807 if (error) { 808 nofp = NULL; 809 goto out; 810 } 811 812 if (nmp->nm_vers < NFS_VER4) { 813 /* 814 * NFS v2/v3 opens are always allowed - so just add it. 815 */ 816 nfs_open_file_add_open(nofp, accessMode, denyMode, 0); 817 goto out; 818 } 819 820 /* 821 * If we just created the file and the modes match, then we simply use 822 * the open performed in the create. Otherwise, send the request. 823 */ 824 if ((nofp->nof_flags & NFS_OPEN_FILE_CREATE) && 825 (nofp->nof_creator == current_thread()) && 826 (accessMode == NFS_OPEN_SHARE_ACCESS_BOTH) && 827 (denyMode == NFS_OPEN_SHARE_DENY_NONE)) { 828 nofp->nof_flags &= ~NFS_OPEN_FILE_CREATE; 829 nofp->nof_creator = NULL; 830 } else { 831 if (!opened) 832 error = nfs4_open(np, nofp, accessMode, denyMode, ctx); 833 if ((error == EACCES) && (nofp->nof_flags & NFS_OPEN_FILE_CREATE) && 834 (nofp->nof_creator == current_thread())) { 835 /* 836 * Ugh. This can happen if we just created the file with read-only 837 * perms and we're trying to open it for real with different modes 838 * (e.g. write-only or with a deny mode) and the server decides to 839 * not allow the second open because of the read-only perms. 840 * The best we can do is to just use the create's open. 841 * We may have access we don't need or we may not have a requested 842 * deny mode. We may log complaints later, but we'll try to avoid it. 843 */ 844 if (denyMode != NFS_OPEN_SHARE_DENY_NONE) 845 NP(np, "nfs_vnop_open: deny mode foregone on create, %d", kauth_cred_getuid(nofp->nof_owner->noo_cred)); 846 nofp->nof_creator = NULL; 847 error = 0; 848 } 849 if (error) 850 goto out; 851 opened = 1; 852 /* 853 * If we had just created the file, we already had it open. 854 * If the actual open mode is less than what we grabbed at 855 * create time, then we'll downgrade the open here. 856 */ 857 if ((nofp->nof_flags & NFS_OPEN_FILE_CREATE) && 858 (nofp->nof_creator == current_thread())) { 859 error = nfs_close(np, nofp, NFS_OPEN_SHARE_ACCESS_BOTH, NFS_OPEN_SHARE_DENY_NONE, ctx); 860 if (error) 861 NP(np, "nfs_vnop_open: create close error %d, %d", error, kauth_cred_getuid(nofp->nof_owner->noo_cred)); 862 if (!nfs_mount_state_error_should_restart(error)) { 863 error = 0; 864 nofp->nof_flags &= ~NFS_OPEN_FILE_CREATE; 865 } 866 } 867 } 868 869out: 870 if (nofp) 871 nfs_open_file_clear_busy(nofp); 872 if (nfs_mount_state_in_use_end(nmp, error)) { 873 nofp = NULL; 874 goto restart; 875 } 876 if (error) 877 NP(np, "nfs_vnop_open: error %d, %d", error, kauth_cred_getuid(noop->noo_cred)); 878 if (noop) 879 nfs_open_owner_rele(noop); 880 if (!error && vtype == VREG && (ap->a_mode & FWRITE)) { 881 lck_mtx_lock(&nmp->nm_lock); 882 nmp->nm_state &= ~NFSSTA_SQUISHY; 883 nmp->nm_curdeadtimeout = nmp->nm_deadtimeout; 884 if (nmp->nm_curdeadtimeout <= 0) 885 nmp->nm_deadto_start = 0; 886 nmp->nm_writers++; 887 lck_mtx_unlock(&nmp->nm_lock); 888 } 889 890 return (error); 891} 892 893static uint32_t 894nfs_no_of_open_file_writers(nfsnode_t np) 895{ 896 uint32_t writers = 0; 897 struct nfs_open_file *nofp; 898 899 TAILQ_FOREACH(nofp, &np->n_opens, nof_link) { 900 writers += nofp->nof_w + nofp->nof_rw + nofp->nof_w_dw + nofp->nof_rw_dw + 901 nofp->nof_w_drw + nofp->nof_rw_drw + nofp->nof_d_w_dw + 902 nofp->nof_d_rw_dw + nofp->nof_d_w_drw + nofp->nof_d_rw_drw + 903 nofp->nof_d_w + nofp->nof_d_rw; 904 } 905 906 return (writers); 907} 908 909/* 910 * NFS close vnode op 911 * 912 * What an NFS client should do upon close after writing is a debatable issue. 913 * Most NFS clients push delayed writes to the server upon close, basically for 914 * two reasons: 915 * 1 - So that any write errors may be reported back to the client process 916 * doing the close system call. By far the two most likely errors are 917 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 918 * 2 - To put a worst case upper bound on cache inconsistency between 919 * multiple clients for the file. 920 * There is also a consistency problem for Version 2 of the protocol w.r.t. 921 * not being able to tell if other clients are writing a file concurrently, 922 * since there is no way of knowing if the changed modify time in the reply 923 * is only due to the write for this client. 924 * (NFS Version 3 provides weak cache consistency data in the reply that 925 * should be sufficient to detect and handle this case.) 926 * 927 * The current code does the following: 928 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 929 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate them. 930 * for NFS Version 4 - basically the same as NFSv3 931 */ 932int 933nfs_vnop_close( 934 struct vnop_close_args /* { 935 struct vnodeop_desc *a_desc; 936 vnode_t a_vp; 937 int a_fflag; 938 vfs_context_t a_context; 939 } */ *ap) 940{ 941 vfs_context_t ctx = ap->a_context; 942 vnode_t vp = ap->a_vp; 943 nfsnode_t np = VTONFS(vp); 944 struct nfsmount *nmp; 945 int error = 0, error1, nfsvers; 946 int fflag = ap->a_fflag; 947 enum vtype vtype; 948 int accessMode, denyMode; 949 struct nfs_open_owner *noop = NULL; 950 struct nfs_open_file *nofp = NULL; 951 952 nmp = VTONMP(vp); 953 if (!nmp) 954 return (ENXIO); 955 nfsvers = nmp->nm_vers; 956 vtype = vnode_vtype(vp); 957 958 /* First, check if we need to update/flush/invalidate */ 959 if (ISSET(np->n_flag, NUPDATESIZE)) 960 nfs_data_update_size(np, 0); 961 nfs_node_lock_force(np); 962 if (np->n_flag & NNEEDINVALIDATE) { 963 np->n_flag &= ~NNEEDINVALIDATE; 964 nfs_node_unlock(np); 965 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, ctx, 1); 966 nfs_node_lock_force(np); 967 } 968 if ((vtype == VREG) && (np->n_flag & NMODIFIED) && (fflag & FWRITE)) { 969 /* we're closing an open for write and the file is modified, so flush it */ 970 nfs_node_unlock(np); 971 if (nfsvers != NFS_VER2) 972 error = nfs_flush(np, MNT_WAIT, vfs_context_thread(ctx), 0); 973 else 974 error = nfs_vinvalbuf(vp, V_SAVE, ctx, 1); 975 nfs_node_lock_force(np); 976 NATTRINVALIDATE(np); 977 } 978 if (np->n_flag & NWRITEERR) { 979 np->n_flag &= ~NWRITEERR; 980 error = np->n_error; 981 } 982 nfs_node_unlock(np); 983 984 if (vtype != VREG) { 985 /* Just mark that it was closed */ 986 lck_mtx_lock(&np->n_openlock); 987 if (np->n_openrefcnt == 0) { 988 if (fflag & (FREAD|FWRITE)) { 989 NP(np, "nfs_vnop_close: open reference underrun"); 990 error = EINVAL; 991 } 992 } else if (fflag & (FREAD|FWRITE)) { 993 np->n_openrefcnt--; 994 } else { 995 /* No FREAD/FWRITE set - probably the final close */ 996 np->n_openrefcnt = 0; 997 } 998 lck_mtx_unlock(&np->n_openlock); 999 return (error); 1000 } 1001 error1 = error; 1002 1003 /* fflag should contain some combination of: FREAD, FWRITE, FHASLOCK */ 1004 accessMode = 0; 1005 if (fflag & FREAD) 1006 accessMode |= NFS_OPEN_SHARE_ACCESS_READ; 1007 if (fflag & FWRITE) 1008 accessMode |= NFS_OPEN_SHARE_ACCESS_WRITE; 1009// XXX It would be nice if we still had the O_EXLOCK/O_SHLOCK flags that were on the open 1010// if (fflag & O_EXLOCK) 1011// denyMode = NFS_OPEN_SHARE_DENY_BOTH; 1012// else if (fflag & O_SHLOCK) 1013// denyMode = NFS_OPEN_SHARE_DENY_WRITE; 1014// else 1015// denyMode = NFS_OPEN_SHARE_DENY_NONE; 1016#if 0 // Not yet 1017 if (fflag & FHASLOCK) { 1018 /* XXX assume FHASLOCK is for the deny mode and not flock */ 1019 /* FHASLOCK flock will be unlocked in the close path, but the flag is not cleared. */ 1020 if (nofp->nof_deny & NFS_OPEN_SHARE_DENY_READ) 1021 denyMode = NFS_OPEN_SHARE_DENY_BOTH; 1022 else if (nofp->nof_deny & NFS_OPEN_SHARE_DENY_WRITE) 1023 denyMode = NFS_OPEN_SHARE_DENY_WRITE; 1024 else 1025 denyMode = NFS_OPEN_SHARE_DENY_NONE; 1026 } else { 1027 denyMode = NFS_OPEN_SHARE_DENY_NONE; 1028 } 1029#else 1030 // XXX don't do deny modes just yet (and never do it for !v4) 1031 denyMode = NFS_OPEN_SHARE_DENY_NONE; 1032#endif 1033 1034 if (!accessMode) { 1035 /* 1036 * No mode given to close? 1037 * Guess this is the final close. 1038 * We should unlock all locks and close all opens. 1039 */ 1040 uint32_t writers; 1041 mount_t mp = vnode_mount(vp); 1042 int force = (!mp || vfs_isforce(mp)); 1043 1044 writers = nfs_no_of_open_file_writers(np); 1045 nfs_release_open_state_for_node(np, force); 1046 if (writers) { 1047 lck_mtx_lock(&nmp->nm_lock); 1048 if (writers > nmp->nm_writers) { 1049 NP(np, "nfs_vnop_close: number of write opens for mount underrun. Node has %d" 1050 " opens for write. Mount has total of %d opens for write\n", 1051 writers, nmp->nm_writers); 1052 nmp->nm_writers = 0; 1053 } else { 1054 nmp->nm_writers -= writers; 1055 } 1056 lck_mtx_unlock(&nmp->nm_lock); 1057 } 1058 1059 return (error); 1060 } else if (fflag & FWRITE) { 1061 lck_mtx_lock(&nmp->nm_lock); 1062 if (nmp->nm_writers == 0) { 1063 NP(np, "nfs_vnop_close: removing open writer from mount, but mount has no files open for writing"); 1064 } else { 1065 nmp->nm_writers--; 1066 } 1067 lck_mtx_unlock(&nmp->nm_lock); 1068 } 1069 1070 1071 noop = nfs_open_owner_find(nmp, vfs_context_ucred(ctx), 0); 1072 if (!noop) { 1073 // printf("nfs_vnop_close: can't get open owner!\n"); 1074 return (EIO); 1075 } 1076 1077restart: 1078 error = nfs_mount_state_in_use_start(nmp, NULL); 1079 if (error) { 1080 nfs_open_owner_rele(noop); 1081 return (error); 1082 } 1083 1084 error = nfs_open_file_find(np, noop, &nofp, 0, 0, 0); 1085 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) { 1086 nfs_mount_state_in_use_end(nmp, 0); 1087 error = nfs4_reopen(nofp, NULL); 1088 nofp = NULL; 1089 if (!error) 1090 goto restart; 1091 } 1092 if (error) { 1093 NP(np, "nfs_vnop_close: no open file for owner, error %d, %d", error, kauth_cred_getuid(noop->noo_cred)); 1094 error = EBADF; 1095 goto out; 1096 } 1097 error = nfs_open_file_set_busy(nofp, NULL); 1098 if (error) { 1099 nofp = NULL; 1100 goto out; 1101 } 1102 1103 error = nfs_close(np, nofp, accessMode, denyMode, ctx); 1104 if (error) 1105 NP(np, "nfs_vnop_close: close error %d, %d", error, kauth_cred_getuid(noop->noo_cred)); 1106 1107out: 1108 if (nofp) 1109 nfs_open_file_clear_busy(nofp); 1110 if (nfs_mount_state_in_use_end(nmp, error)) { 1111 nofp = NULL; 1112 goto restart; 1113 } 1114 if (!error) 1115 error = error1; 1116 if (error) 1117 NP(np, "nfs_vnop_close: error %d, %d", error, kauth_cred_getuid(noop->noo_cred)); 1118 if (noop) 1119 nfs_open_owner_rele(noop); 1120 return (error); 1121} 1122 1123/* 1124 * nfs_close(): common function that does all the heavy lifting of file closure 1125 * 1126 * Takes an open file structure and a set of access/deny modes and figures out how 1127 * to update the open file structure (and the state on the server) appropriately. 1128 */ 1129int 1130nfs_close( 1131 nfsnode_t np, 1132 struct nfs_open_file *nofp, 1133 uint32_t accessMode, 1134 uint32_t denyMode, 1135 vfs_context_t ctx) 1136{ 1137 struct nfs_lock_owner *nlop; 1138 int error = 0, changed = 0, delegated = 0, closed = 0, downgrade = 0; 1139 uint32_t newAccessMode, newDenyMode; 1140 1141 /* warn if modes don't match current state */ 1142 if (((accessMode & nofp->nof_access) != accessMode) || ((denyMode & nofp->nof_deny) != denyMode)) 1143 NP(np, "nfs_close: mode mismatch %d %d, current %d %d, %d", 1144 accessMode, denyMode, nofp->nof_access, nofp->nof_deny, 1145 kauth_cred_getuid(nofp->nof_owner->noo_cred)); 1146 1147 /* 1148 * If we're closing a write-only open, we may not have a write-only count 1149 * if we also grabbed read access. So, check the read-write count. 1150 */ 1151 if (denyMode == NFS_OPEN_SHARE_DENY_NONE) { 1152 if ((accessMode == NFS_OPEN_SHARE_ACCESS_WRITE) && 1153 (nofp->nof_w == 0) && (nofp->nof_d_w == 0) && 1154 (nofp->nof_rw || nofp->nof_d_rw)) 1155 accessMode = NFS_OPEN_SHARE_ACCESS_BOTH; 1156 } else if (denyMode == NFS_OPEN_SHARE_DENY_WRITE) { 1157 if ((accessMode == NFS_OPEN_SHARE_ACCESS_WRITE) && 1158 (nofp->nof_w_dw == 0) && (nofp->nof_d_w_dw == 0) && 1159 (nofp->nof_rw_dw || nofp->nof_d_rw_dw)) 1160 accessMode = NFS_OPEN_SHARE_ACCESS_BOTH; 1161 } else { /* NFS_OPEN_SHARE_DENY_BOTH */ 1162 if ((accessMode == NFS_OPEN_SHARE_ACCESS_WRITE) && 1163 (nofp->nof_w_drw == 0) && (nofp->nof_d_w_drw == 0) && 1164 (nofp->nof_rw_drw || nofp->nof_d_rw_drw)) 1165 accessMode = NFS_OPEN_SHARE_ACCESS_BOTH; 1166 } 1167 1168 nfs_open_file_remove_open_find(nofp, accessMode, denyMode, &newAccessMode, &newDenyMode, &delegated); 1169 if ((newAccessMode != nofp->nof_access) || (newDenyMode != nofp->nof_deny)) 1170 changed = 1; 1171 else 1172 changed = 0; 1173 1174 if (NFSTONMP(np)->nm_vers < NFS_VER4) /* NFS v2/v3 closes simply need to remove the open. */ 1175 goto v3close; 1176 1177 if ((newAccessMode == 0) || (nofp->nof_opencnt == 1)) { 1178 /* 1179 * No more access after this close, so clean up and close it. 1180 * Don't send a close RPC if we're closing a delegated open. 1181 */ 1182 nfs_wait_bufs(np); 1183 closed = 1; 1184 if (!delegated && !(nofp->nof_flags & NFS_OPEN_FILE_LOST)) 1185 error = nfs4_close_rpc(np, nofp, vfs_context_thread(ctx), vfs_context_ucred(ctx), 0); 1186 if (error == NFSERR_LOCKS_HELD) { 1187 /* 1188 * Hmm... the server says we have locks we need to release first 1189 * Find the lock owner and try to unlock everything. 1190 */ 1191 nlop = nfs_lock_owner_find(np, vfs_context_proc(ctx), 0); 1192 if (nlop) { 1193 nfs4_unlock_rpc(np, nlop, F_WRLCK, 0, UINT64_MAX, 1194 0, vfs_context_thread(ctx), vfs_context_ucred(ctx)); 1195 nfs_lock_owner_rele(nlop); 1196 } 1197 error = nfs4_close_rpc(np, nofp, vfs_context_thread(ctx), vfs_context_ucred(ctx), 0); 1198 } 1199 } else if (changed) { 1200 /* 1201 * File is still open but with less access, so downgrade the open. 1202 * Don't send a downgrade RPC if we're closing a delegated open. 1203 */ 1204 if (!delegated && !(nofp->nof_flags & NFS_OPEN_FILE_LOST)) { 1205 downgrade = 1; 1206 /* 1207 * If we have delegated opens, we should probably claim them before sending 1208 * the downgrade because the server may not know the open we are downgrading to. 1209 */ 1210 if (nofp->nof_d_rw_drw || nofp->nof_d_w_drw || nofp->nof_d_r_drw || 1211 nofp->nof_d_rw_dw || nofp->nof_d_w_dw || nofp->nof_d_r_dw || 1212 nofp->nof_d_rw || nofp->nof_d_w || nofp->nof_d_r) 1213 nfs4_claim_delegated_state_for_open_file(nofp, 0); 1214 /* need to remove the open before sending the downgrade */ 1215 nfs_open_file_remove_open(nofp, accessMode, denyMode); 1216 error = nfs4_open_downgrade_rpc(np, nofp, ctx); 1217 if (error) /* Hmm.. that didn't work. Add the open back in. */ 1218 nfs_open_file_add_open(nofp, accessMode, denyMode, delegated); 1219 } 1220 } 1221 1222 if (error) { 1223 NP(np, "nfs_close: error %d, %d", error, kauth_cred_getuid(nofp->nof_owner->noo_cred)); 1224 return (error); 1225 } 1226 1227v3close: 1228 if (!downgrade) 1229 nfs_open_file_remove_open(nofp, accessMode, denyMode); 1230 1231 if (closed) { 1232 lck_mtx_lock(&nofp->nof_lock); 1233 if (nofp->nof_r || nofp->nof_d_r || nofp->nof_w || nofp->nof_d_w || nofp->nof_d_rw || 1234 (nofp->nof_rw && !((nofp->nof_flags & NFS_OPEN_FILE_CREATE) && !nofp->nof_creator && (nofp->nof_rw == 1))) || 1235 nofp->nof_r_dw || nofp->nof_d_r_dw || nofp->nof_w_dw || nofp->nof_d_w_dw || 1236 nofp->nof_rw_dw || nofp->nof_d_rw_dw || nofp->nof_r_drw || nofp->nof_d_r_drw || 1237 nofp->nof_w_drw || nofp->nof_d_w_drw || nofp->nof_rw_drw || nofp->nof_d_rw_drw) 1238 NP(np, "nfs_close: unexpected count: %u.%u %u.%u %u.%u dw %u.%u %u.%u %u.%u drw %u.%u %u.%u %u.%u flags 0x%x, %d", 1239 nofp->nof_r, nofp->nof_d_r, nofp->nof_w, nofp->nof_d_w, 1240 nofp->nof_rw, nofp->nof_d_rw, nofp->nof_r_dw, nofp->nof_d_r_dw, 1241 nofp->nof_w_dw, nofp->nof_d_w_dw, nofp->nof_rw_dw, nofp->nof_d_rw_dw, 1242 nofp->nof_r_drw, nofp->nof_d_r_drw, nofp->nof_w_drw, nofp->nof_d_w_drw, 1243 nofp->nof_rw_drw, nofp->nof_d_rw_drw, nofp->nof_flags, 1244 kauth_cred_getuid(nofp->nof_owner->noo_cred)); 1245 /* clear out all open info, just to be safe */ 1246 nofp->nof_access = nofp->nof_deny = 0; 1247 nofp->nof_mmap_access = nofp->nof_mmap_deny = 0; 1248 nofp->nof_r = nofp->nof_d_r = 0; 1249 nofp->nof_w = nofp->nof_d_w = 0; 1250 nofp->nof_rw = nofp->nof_d_rw = 0; 1251 nofp->nof_r_dw = nofp->nof_d_r_dw = 0; 1252 nofp->nof_w_dw = nofp->nof_d_w_dw = 0; 1253 nofp->nof_rw_dw = nofp->nof_d_rw_dw = 0; 1254 nofp->nof_r_drw = nofp->nof_d_r_drw = 0; 1255 nofp->nof_w_drw = nofp->nof_d_w_drw = 0; 1256 nofp->nof_rw_drw = nofp->nof_d_rw_drw = 0; 1257 nofp->nof_flags &= ~NFS_OPEN_FILE_CREATE; 1258 lck_mtx_unlock(&nofp->nof_lock); 1259 /* XXX we may potentially want to clean up idle/unused open file structures */ 1260 } 1261 if (nofp->nof_flags & NFS_OPEN_FILE_LOST) { 1262 error = EIO; 1263 NP(np, "nfs_close: LOST%s, %d", !nofp->nof_opencnt ? " (last)" : "", 1264 kauth_cred_getuid(nofp->nof_owner->noo_cred)); 1265 } 1266 1267 return (error); 1268} 1269 1270 1271int 1272nfs3_getattr_rpc( 1273 nfsnode_t np, 1274 mount_t mp, 1275 u_char *fhp, 1276 size_t fhsize, 1277 int flags, 1278 vfs_context_t ctx, 1279 struct nfs_vattr *nvap, 1280 u_int64_t *xidp) 1281{ 1282 struct nfsmount *nmp = mp ? VFSTONFS(mp) : NFSTONMP(np); 1283 int error = 0, status, nfsvers, rpcflags = 0; 1284 struct nfsm_chain nmreq, nmrep; 1285 1286 if (nfs_mount_gone(nmp)) 1287 return (ENXIO); 1288 nfsvers = nmp->nm_vers; 1289 1290 if (flags & NGA_MONITOR) /* vnode monitor requests should be soft */ 1291 rpcflags = R_RECOVER; 1292 1293 if (flags & NGA_SOFT) /* Return ETIMEDOUT if server not responding */ 1294 rpcflags |= R_SOFT; 1295 1296 nfsm_chain_null(&nmreq); 1297 nfsm_chain_null(&nmrep); 1298 1299 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers)); 1300 if (nfsvers != NFS_VER2) 1301 nfsm_chain_add_32(error, &nmreq, fhsize); 1302 nfsm_chain_add_opaque(error, &nmreq, fhp, fhsize); 1303 nfsm_chain_build_done(error, &nmreq); 1304 nfsmout_if(error); 1305 error = nfs_request2(np, mp, &nmreq, NFSPROC_GETATTR, 1306 vfs_context_thread(ctx), vfs_context_ucred(ctx), 1307 NULL, rpcflags, &nmrep, xidp, &status); 1308 if (!error) 1309 error = status; 1310 nfsmout_if(error); 1311 error = nfs_parsefattr(&nmrep, nfsvers, nvap); 1312nfsmout: 1313 nfsm_chain_cleanup(&nmreq); 1314 nfsm_chain_cleanup(&nmrep); 1315 return (error); 1316} 1317 1318/* 1319 * nfs_refresh_fh will attempt to update the file handle for the node. 1320 * 1321 * It only does this for symbolic links and regular files that are not currently opened. 1322 * 1323 * On Success returns 0 and the nodes file handle is updated, or ESTALE on failure. 1324 */ 1325int 1326nfs_refresh_fh(nfsnode_t np, vfs_context_t ctx) 1327{ 1328 vnode_t dvp, vp = NFSTOV(np); 1329 nfsnode_t dnp; 1330 const char *v_name = vnode_getname(vp); 1331 char *name; 1332 int namelen, fhsize, refreshed; 1333 int error, wanted = 0; 1334 uint8_t *fhp; 1335 struct timespec ts = {2, 0}; 1336 1337 NFS_VNOP_DBG("vnode is %d\n", vnode_vtype(vp)); 1338 1339 dvp = vnode_parent(vp); 1340 if ((vnode_vtype(vp) != VREG && vnode_vtype(vp) != VLNK) || 1341 v_name == NULL || *v_name == '\0' || dvp == NULL) { 1342 if (v_name != NULL) 1343 vnode_putname(v_name); 1344 return (ESTALE); 1345 } 1346 dnp = VTONFS(dvp); 1347 1348 namelen = strlen(v_name); 1349 MALLOC(name, char *, namelen + 1, M_TEMP, M_WAITOK); 1350 if (name == NULL) { 1351 vnode_putname(v_name); 1352 return (ESTALE); 1353 } 1354 bcopy(v_name, name, namelen+1); 1355 NFS_VNOP_DBG("Trying to refresh %s : %s\n", v_name, name); 1356 vnode_putname(v_name); 1357 1358 /* Allocate the maximum size file handle */ 1359 MALLOC(fhp, uint8_t *, NFS4_FHSIZE, M_TEMP, M_WAITOK); 1360 if (fhp == NULL) { 1361 FREE(name, M_TEMP); 1362 return (ESTALE); 1363 } 1364 1365 if ((error = nfs_node_lock(np))) { 1366 FREE(name, M_TEMP); 1367 FREE(fhp, M_TEMP); 1368 return (ESTALE); 1369 } 1370 1371 fhsize = np->n_fhsize; 1372 bcopy(np->n_fhp, fhp, fhsize); 1373 while (ISSET(np->n_flag, NREFRESH)) { 1374 SET(np->n_flag, NREFRESHWANT); 1375 NFS_VNOP_DBG("Waiting for refresh of %s\n", name); 1376 msleep(np, &np->n_lock, PZERO-1, "nfsrefreshwant", &ts); 1377 if ((error = nfs_sigintr(NFSTONMP(np), NULL, vfs_context_thread(ctx), 0))) 1378 break; 1379 } 1380 refreshed = error ? 0 : !NFS_CMPFH(np, fhp, fhsize); 1381 SET(np->n_flag, NREFRESH); 1382 nfs_node_unlock(np); 1383 1384 NFS_VNOP_DBG("error = %d, refreshed = %d\n", error, refreshed); 1385 if (error || refreshed) 1386 goto nfsmout; 1387 1388 /* Check that there are no open references for this file */ 1389 lck_mtx_lock(&np->n_openlock); 1390 if (np->n_openrefcnt || !TAILQ_EMPTY(&np->n_opens) || !TAILQ_EMPTY(&np->n_lock_owners)) { 1391 int cnt = 0; 1392 struct nfs_open_file *ofp; 1393 1394 TAILQ_FOREACH(ofp, &np->n_opens, nof_link) { 1395 cnt += ofp->nof_opencnt; 1396 } 1397 if (cnt) { 1398 lck_mtx_unlock(&np->n_openlock); 1399 NFS_VNOP_DBG("Can not refresh file handle for %s with open state\n", name); 1400 NFS_VNOP_DBG("\topenrefcnt = %d, opens = %d lock_owners = %d\n", 1401 np->n_openrefcnt, cnt, !TAILQ_EMPTY(&np->n_lock_owners)); 1402 error = ESTALE; 1403 goto nfsmout; 1404 } 1405 } 1406 lck_mtx_unlock(&np->n_openlock); 1407 /* 1408 * Since the FH is currently stale we should not be able to 1409 * establish any open state until the FH is refreshed. 1410 */ 1411 1412 error = nfs_node_lock(np); 1413 nfsmout_if(error); 1414 /* 1415 * Symlinks should never need invalidations and are holding 1416 * the one and only nfsbuf in an uncached acquired state 1417 * trying to do a readlink. So we will hang if we invalidate 1418 * in that case. Only in in the VREG case do we need to 1419 * invalidate. 1420 */ 1421 if (vnode_vtype(vp) == VREG) { 1422 np->n_flag &= ~NNEEDINVALIDATE; 1423 nfs_node_unlock(np); 1424 error = nfs_vinvalbuf(vp, V_IGNORE_WRITEERR, ctx, 1); 1425 if (error) 1426 NFS_VNOP_DBG("nfs_vinvalbuf returned %d\n", error); 1427 nfsmout_if(error); 1428 } else { 1429 nfs_node_unlock(np); 1430 } 1431 1432 NFS_VNOP_DBG("Looking up %s\n", name); 1433 error = nfs_lookitup(dnp, name, namelen, ctx, &np); 1434 if (error) 1435 NFS_VNOP_DBG("nfs_lookitup returned %d\n", error); 1436 1437nfsmout: 1438 nfs_node_lock_force(np); 1439 wanted = ISSET(np->n_flag, NREFRESHWANT); 1440 CLR(np->n_flag, NREFRESH|NREFRESHWANT); 1441 nfs_node_unlock(np); 1442 if (wanted) 1443 wakeup(np); 1444 1445 if (error == 0) 1446 NFS_VNOP_DBG("%s refreshed file handle\n", name); 1447 1448 FREE(name, M_TEMP); 1449 FREE(fhp, M_TEMP); 1450 1451 return (error ? ESTALE : 0); 1452} 1453 1454int 1455nfs_getattr(nfsnode_t np, struct nfs_vattr *nvap, vfs_context_t ctx, int flags) 1456{ 1457 int error; 1458 1459retry: 1460 error = nfs_getattr_internal(np, nvap, ctx, flags); 1461 if (error == ESTALE) { 1462 error = nfs_refresh_fh(np, ctx); 1463 if (!error) 1464 goto retry; 1465 } 1466 return (error); 1467} 1468 1469int 1470nfs_getattr_internal(nfsnode_t np, struct nfs_vattr *nvap, vfs_context_t ctx, int flags) 1471{ 1472 struct nfsmount *nmp; 1473 int error = 0, nfsvers, inprogset = 0, wanted = 0, avoidfloods; 1474 struct nfs_vattr nvattr; 1475 struct timespec ts = { 2, 0 }; 1476 u_int64_t xid; 1477 1478 FSDBG_TOP(513, np->n_size, np, np->n_vattr.nva_size, np->n_flag); 1479 1480 nmp = NFSTONMP(np); 1481 1482 if (nfs_mount_gone(nmp)) 1483 return (ENXIO); 1484 nfsvers = nmp->nm_vers; 1485 1486 if (!nvap) 1487 nvap = &nvattr; 1488 NVATTR_INIT(nvap); 1489 1490 /* Update local times for special files. */ 1491 if (np->n_flag & (NACC | NUPD)) { 1492 nfs_node_lock_force(np); 1493 np->n_flag |= NCHG; 1494 nfs_node_unlock(np); 1495 } 1496 /* Update size, if necessary */ 1497 if (ISSET(np->n_flag, NUPDATESIZE)) 1498 nfs_data_update_size(np, 0); 1499 1500 error = nfs_node_lock(np); 1501 nfsmout_if(error); 1502 if (!(flags & (NGA_UNCACHED|NGA_MONITOR)) || ((nfsvers >= NFS_VER4) && (np->n_openflags & N_DELEG_MASK))) { 1503 /* 1504 * Use the cache or wait for any getattr in progress if: 1505 * - it's a cached request, or 1506 * - we have a delegation, or 1507 * - the server isn't responding 1508 */ 1509 while (1) { 1510 error = nfs_getattrcache(np, nvap, flags); 1511 if (!error || (error != ENOENT)) { 1512 nfs_node_unlock(np); 1513 goto nfsmout; 1514 } 1515 error = 0; 1516 if (!ISSET(np->n_flag, NGETATTRINPROG)) 1517 break; 1518 if (flags & NGA_MONITOR) { 1519 /* no need to wait if a request is pending */ 1520 error = EINPROGRESS; 1521 nfs_node_unlock(np); 1522 goto nfsmout; 1523 } 1524 SET(np->n_flag, NGETATTRWANT); 1525 msleep(np, &np->n_lock, PZERO-1, "nfsgetattrwant", &ts); 1526 if ((error = nfs_sigintr(NFSTONMP(np), NULL, vfs_context_thread(ctx), 0))) { 1527 nfs_node_unlock(np); 1528 goto nfsmout; 1529 } 1530 } 1531 SET(np->n_flag, NGETATTRINPROG); 1532 inprogset = 1; 1533 } else if (!ISSET(np->n_flag, NGETATTRINPROG)) { 1534 SET(np->n_flag, NGETATTRINPROG); 1535 inprogset = 1; 1536 } else if (flags & NGA_MONITOR) { 1537 /* no need to make a request if one is pending */ 1538 error = EINPROGRESS; 1539 } 1540 nfs_node_unlock(np); 1541 1542 nmp = NFSTONMP(np); 1543 if (nfs_mount_gone(nmp)) 1544 error = ENXIO; 1545 if (error) 1546 goto nfsmout; 1547 1548 /* 1549 * Return cached attributes if they are valid, 1550 * if the server doesn't respond, and this is 1551 * some softened up style of mount. 1552 */ 1553 if (NATTRVALID(np) && nfs_use_cache(nmp)) 1554 flags |= NGA_SOFT; 1555 1556 /* 1557 * We might want to try to get both the attributes and access info by 1558 * making an ACCESS call and seeing if it returns updated attributes. 1559 * But don't bother if we aren't caching access info or if the 1560 * attributes returned wouldn't be cached. 1561 */ 1562 if (!(flags & NGA_ACL) && (nfsvers != NFS_VER2) && nfs_access_for_getattr && (nfs_access_cache_timeout > 0)) { 1563 if (nfs_attrcachetimeout(np) > 0) { 1564 /* OSAddAtomic(1, &nfsstats.accesscache_misses); */ 1565 u_int32_t access = NFS_ACCESS_ALL; 1566 int rpcflags = 0; 1567 1568 /* Return cached attrs if server doesn't respond */ 1569 if (flags & NGA_SOFT) 1570 rpcflags |= R_SOFT; 1571 1572 error = nmp->nm_funcs->nf_access_rpc(np, &access, rpcflags, ctx); 1573 1574 if (error == ETIMEDOUT) 1575 goto returncached; 1576 1577 if (error) 1578 goto nfsmout; 1579 nfs_node_lock_force(np); 1580 error = nfs_getattrcache(np, nvap, flags); 1581 nfs_node_unlock(np); 1582 if (!error || (error != ENOENT)) 1583 goto nfsmout; 1584 /* Well, that didn't work... just do a getattr... */ 1585 error = 0; 1586 } 1587 } 1588 1589 avoidfloods = 0; 1590 1591tryagain: 1592 error = nmp->nm_funcs->nf_getattr_rpc(np, NULL, np->n_fhp, np->n_fhsize, flags, ctx, nvap, &xid); 1593 if (!error) { 1594 nfs_node_lock_force(np); 1595 error = nfs_loadattrcache(np, nvap, &xid, 0); 1596 nfs_node_unlock(np); 1597 } 1598 1599 /* 1600 * If the server didn't respond, return cached attributes. 1601 */ 1602returncached: 1603 if ((flags & NGA_SOFT) && (error == ETIMEDOUT)) { 1604 nfs_node_lock_force(np); 1605 error = nfs_getattrcache(np, nvap, flags); 1606 if (!error || (error != ENOENT)) { 1607 nfs_node_unlock(np); 1608 goto nfsmout; 1609 } 1610 nfs_node_unlock(np); 1611 } 1612 nfsmout_if(error); 1613 1614 if (!xid) { /* out-of-order rpc - attributes were dropped */ 1615 FSDBG(513, -1, np, np->n_xid >> 32, np->n_xid); 1616 if (avoidfloods++ < 20) 1617 goto tryagain; 1618 /* avoidfloods>1 is bizarre. at 20 pull the plug */ 1619 /* just return the last attributes we got */ 1620 } 1621nfsmout: 1622 nfs_node_lock_force(np); 1623 if (inprogset) { 1624 wanted = ISSET(np->n_flag, NGETATTRWANT); 1625 CLR(np->n_flag, (NGETATTRINPROG | NGETATTRWANT)); 1626 } 1627 if (!error) { 1628 /* check if the node changed on us */ 1629 vnode_t vp = NFSTOV(np); 1630 enum vtype vtype = vnode_vtype(vp); 1631 if ((vtype == VDIR) && NFS_CHANGED_NC(nfsvers, np, nvap)) { 1632 FSDBG(513, -1, np, 0, np); 1633 np->n_flag &= ~NNEGNCENTRIES; 1634 cache_purge(vp); 1635 np->n_ncgen++; 1636 NFS_CHANGED_UPDATE_NC(nfsvers, np, nvap); 1637 NFS_VNOP_DBG("Purge directory 0x%llx\n", 1638 (uint64_t)VM_KERNEL_ADDRPERM(vp)); 1639 } 1640 if (NFS_CHANGED(nfsvers, np, nvap)) { 1641 FSDBG(513, -1, np, -1, np); 1642 if (vtype == VDIR) { 1643 NFS_VNOP_DBG("Invalidate directory 0x%llx\n", 1644 (uint64_t)VM_KERNEL_ADDRPERM(vp)); 1645 nfs_invaldir(np); 1646 } 1647 nfs_node_unlock(np); 1648 if (wanted) 1649 wakeup(np); 1650 error = nfs_vinvalbuf(vp, V_SAVE, ctx, 1); 1651 FSDBG(513, -1, np, -2, error); 1652 if (!error) { 1653 nfs_node_lock_force(np); 1654 NFS_CHANGED_UPDATE(nfsvers, np, nvap); 1655 nfs_node_unlock(np); 1656 } 1657 } else { 1658 nfs_node_unlock(np); 1659 if (wanted) 1660 wakeup(np); 1661 } 1662 } else { 1663 nfs_node_unlock(np); 1664 if (wanted) 1665 wakeup(np); 1666 } 1667 1668 if (nvap == &nvattr) { 1669 NVATTR_CLEANUP(nvap); 1670 } else if (!(flags & NGA_ACL)) { 1671 /* make sure we don't return an ACL if it wasn't asked for */ 1672 NFS_BITMAP_CLR(nvap->nva_bitmap, NFS_FATTR_ACL); 1673 if (nvap->nva_acl) { 1674 kauth_acl_free(nvap->nva_acl); 1675 nvap->nva_acl = NULL; 1676 } 1677 } 1678 FSDBG_BOT(513, np->n_size, error, np->n_vattr.nva_size, np->n_flag); 1679 return (error); 1680} 1681 1682/* 1683 * NFS getattr call from vfs. 1684 */ 1685 1686/* 1687 * The attributes we support over the wire. 1688 * We also get fsid but the vfs layer gets it out of the mount 1689 * structure after this calling us so there's no need to return it, 1690 * and Finder expects to call getattrlist just looking for the FSID 1691 * with out hanging on a non responsive server. 1692 */ 1693#define NFS3_SUPPORTED_VATTRS \ 1694 (VNODE_ATTR_va_rdev | \ 1695 VNODE_ATTR_va_nlink | \ 1696 VNODE_ATTR_va_data_size | \ 1697 VNODE_ATTR_va_data_alloc | \ 1698 VNODE_ATTR_va_uid | \ 1699 VNODE_ATTR_va_gid | \ 1700 VNODE_ATTR_va_mode | \ 1701 VNODE_ATTR_va_modify_time | \ 1702 VNODE_ATTR_va_change_time | \ 1703 VNODE_ATTR_va_access_time | \ 1704 VNODE_ATTR_va_fileid | \ 1705 VNODE_ATTR_va_type) 1706 1707int 1708nfs3_vnop_getattr( 1709 struct vnop_getattr_args /* { 1710 struct vnodeop_desc *a_desc; 1711 vnode_t a_vp; 1712 struct vnode_attr *a_vap; 1713 vfs_context_t a_context; 1714 } */ *ap) 1715{ 1716 int error; 1717 struct nfs_vattr nva; 1718 struct vnode_attr *vap = ap->a_vap; 1719 dev_t rdev; 1720 1721 /* 1722 * Lets don't go over the wire if we don't support any of the attributes. 1723 * Just fall through at the VFS layer and let it cons up what it needs. 1724 */ 1725 /* Return the io size no matter what, since we don't go over the wire for this */ 1726 VATTR_RETURN(vap, va_iosize, nfs_iosize); 1727 if ((vap->va_active & NFS3_SUPPORTED_VATTRS) == 0) 1728 return (0); 1729 1730 if (VATTR_IS_ACTIVE(ap->a_vap, va_name)) 1731 NFS_VNOP_DBG("Getting attrs for 0x%llx, vname is %s\n", 1732 (uint64_t)VM_KERNEL_ADDRPERM(ap->a_vp), 1733 ap->a_vp->v_name ? ap->a_vp->v_name : "empty"); 1734 error = nfs_getattr(VTONFS(ap->a_vp), &nva, ap->a_context, NGA_CACHED); 1735 if (error) 1736 return (error); 1737 1738 /* copy nva to *a_vap */ 1739 VATTR_RETURN(vap, va_type, nva.nva_type); 1740 VATTR_RETURN(vap, va_mode, nva.nva_mode); 1741 rdev = makedev(nva.nva_rawdev.specdata1, nva.nva_rawdev.specdata2); 1742 VATTR_RETURN(vap, va_rdev, rdev); 1743 VATTR_RETURN(vap, va_uid, nva.nva_uid); 1744 VATTR_RETURN(vap, va_gid, nva.nva_gid); 1745 VATTR_RETURN(vap, va_nlink, nva.nva_nlink); 1746 VATTR_RETURN(vap, va_fileid, nva.nva_fileid); 1747 VATTR_RETURN(vap, va_data_size, nva.nva_size); 1748 VATTR_RETURN(vap, va_data_alloc, nva.nva_bytes); 1749 vap->va_access_time.tv_sec = nva.nva_timesec[NFSTIME_ACCESS]; 1750 vap->va_access_time.tv_nsec = nva.nva_timensec[NFSTIME_ACCESS]; 1751 VATTR_SET_SUPPORTED(vap, va_access_time); 1752 vap->va_modify_time.tv_sec = nva.nva_timesec[NFSTIME_MODIFY]; 1753 vap->va_modify_time.tv_nsec = nva.nva_timensec[NFSTIME_MODIFY]; 1754 VATTR_SET_SUPPORTED(vap, va_modify_time); 1755 vap->va_change_time.tv_sec = nva.nva_timesec[NFSTIME_CHANGE]; 1756 vap->va_change_time.tv_nsec = nva.nva_timensec[NFSTIME_CHANGE]; 1757 VATTR_SET_SUPPORTED(vap, va_change_time); 1758 1759 // VATTR_RETURN(vap, va_encoding, 0xffff /* kTextEncodingUnknown */); 1760 return (error); 1761} 1762 1763/* 1764 * NFS setattr call. 1765 */ 1766int 1767nfs_vnop_setattr( 1768 struct vnop_setattr_args /* { 1769 struct vnodeop_desc *a_desc; 1770 vnode_t a_vp; 1771 struct vnode_attr *a_vap; 1772 vfs_context_t a_context; 1773 } */ *ap) 1774{ 1775 vfs_context_t ctx = ap->a_context; 1776 vnode_t vp = ap->a_vp; 1777 nfsnode_t np = VTONFS(vp); 1778 struct nfsmount *nmp; 1779 struct vnode_attr *vap = ap->a_vap; 1780 int error = 0; 1781 int biosize, nfsvers, namedattrs; 1782 u_quad_t origsize, vapsize; 1783 struct nfs_dulookup dul; 1784 nfsnode_t dnp = NULL; 1785 vnode_t dvp = NULL; 1786 const char *vname = NULL; 1787 struct nfs_open_owner *noop = NULL; 1788 struct nfs_open_file *nofp = NULL; 1789 1790 nmp = VTONMP(vp); 1791 if (nfs_mount_gone(nmp)) 1792 return (ENXIO); 1793 nfsvers = nmp->nm_vers; 1794 namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR); 1795 biosize = nmp->nm_biosize; 1796 1797 /* Disallow write attempts if the filesystem is mounted read-only. */ 1798 if (vnode_vfsisrdonly(vp)) 1799 return (EROFS); 1800 1801 origsize = np->n_size; 1802 if (VATTR_IS_ACTIVE(vap, va_data_size)) { 1803 switch (vnode_vtype(vp)) { 1804 case VDIR: 1805 return (EISDIR); 1806 case VCHR: 1807 case VBLK: 1808 case VSOCK: 1809 case VFIFO: 1810 if (!VATTR_IS_ACTIVE(vap, va_modify_time) && 1811 !VATTR_IS_ACTIVE(vap, va_access_time) && 1812 !VATTR_IS_ACTIVE(vap, va_mode) && 1813 !VATTR_IS_ACTIVE(vap, va_uid) && 1814 !VATTR_IS_ACTIVE(vap, va_gid)) { 1815 return (0); 1816 } 1817 VATTR_CLEAR_ACTIVE(vap, va_data_size); 1818 break; 1819 default: 1820 /* 1821 * Disallow write attempts if the filesystem is 1822 * mounted read-only. 1823 */ 1824 if (vnode_vfsisrdonly(vp)) 1825 return (EROFS); 1826 FSDBG_TOP(512, np->n_size, vap->va_data_size, 1827 np->n_vattr.nva_size, np->n_flag); 1828 /* clear NNEEDINVALIDATE, if set */ 1829 if ((error = nfs_node_lock(np))) 1830 return (error); 1831 if (np->n_flag & NNEEDINVALIDATE) 1832 np->n_flag &= ~NNEEDINVALIDATE; 1833 nfs_node_unlock(np); 1834 /* flush everything */ 1835 error = nfs_vinvalbuf(vp, (vap->va_data_size ? V_SAVE : 0) , ctx, 1); 1836 if (error) { 1837 NP(np, "nfs_setattr: nfs_vinvalbuf %d", error); 1838 FSDBG_BOT(512, np->n_size, vap->va_data_size, np->n_vattr.nva_size, -1); 1839 return (error); 1840 } 1841 if (nfsvers >= NFS_VER4) { 1842 /* setting file size requires having the file open for write access */ 1843 if (np->n_flag & NREVOKE) 1844 return (EIO); 1845 noop = nfs_open_owner_find(nmp, vfs_context_ucred(ctx), 1); 1846 if (!noop) 1847 return (ENOMEM); 1848restart: 1849 error = nfs_mount_state_in_use_start(nmp, vfs_context_thread(ctx)); 1850 if (error) 1851 return (error); 1852 if (np->n_flag & NREVOKE) { 1853 nfs_mount_state_in_use_end(nmp, 0); 1854 return (EIO); 1855 } 1856 error = nfs_open_file_find(np, noop, &nofp, 0, 0, 1); 1857 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_LOST)) 1858 error = EIO; 1859 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) { 1860 nfs_mount_state_in_use_end(nmp, 0); 1861 error = nfs4_reopen(nofp, vfs_context_thread(ctx)); 1862 nofp = NULL; 1863 if (!error) 1864 goto restart; 1865 } 1866 if (!error) 1867 error = nfs_open_file_set_busy(nofp, vfs_context_thread(ctx)); 1868 if (error) { 1869 nfs_open_owner_rele(noop); 1870 return (error); 1871 } 1872 if (!(nofp->nof_access & NFS_OPEN_SHARE_ACCESS_WRITE)) { 1873 /* we don't have the file open for write access, so open it */ 1874 error = nfs4_open(np, nofp, NFS_OPEN_SHARE_ACCESS_WRITE, NFS_OPEN_SHARE_DENY_NONE, ctx); 1875 if (!error) 1876 nofp->nof_flags |= NFS_OPEN_FILE_SETATTR; 1877 if (nfs_mount_state_error_should_restart(error)) { 1878 nfs_open_file_clear_busy(nofp); 1879 nofp = NULL; 1880 if (nfs_mount_state_in_use_end(nmp, error)) 1881 goto restart; 1882 } 1883 } 1884 } 1885 nfs_data_lock(np, NFS_DATA_LOCK_EXCLUSIVE); 1886 if (np->n_size > vap->va_data_size) { /* shrinking? */ 1887 daddr64_t obn, bn; 1888 int neweofoff, mustwrite; 1889 struct nfsbuf *bp; 1890 1891 obn = (np->n_size - 1) / biosize; 1892 bn = vap->va_data_size / biosize; 1893 for ( ; obn >= bn; obn--) { 1894 if (!nfs_buf_is_incore(np, obn)) 1895 continue; 1896 error = nfs_buf_get(np, obn, biosize, NULL, NBLK_READ, &bp); 1897 if (error) 1898 continue; 1899 if (obn != bn) { 1900 FSDBG(512, bp, bp->nb_flags, 0, obn); 1901 SET(bp->nb_flags, NB_INVAL); 1902 nfs_buf_release(bp, 1); 1903 continue; 1904 } 1905 mustwrite = 0; 1906 neweofoff = vap->va_data_size - NBOFF(bp); 1907 /* check for any dirty data before the new EOF */ 1908 if ((bp->nb_dirtyend > 0) && (bp->nb_dirtyoff < neweofoff)) { 1909 /* clip dirty range to EOF */ 1910 if (bp->nb_dirtyend > neweofoff) { 1911 bp->nb_dirtyend = neweofoff; 1912 if (bp->nb_dirtyoff >= bp->nb_dirtyend) 1913 bp->nb_dirtyoff = bp->nb_dirtyend = 0; 1914 } 1915 if ((bp->nb_dirtyend > 0) && (bp->nb_dirtyoff < neweofoff)) 1916 mustwrite++; 1917 } 1918 bp->nb_dirty &= (1 << round_page_32(neweofoff)/PAGE_SIZE) - 1; 1919 if (bp->nb_dirty) 1920 mustwrite++; 1921 if (!mustwrite) { 1922 FSDBG(512, bp, bp->nb_flags, 0, obn); 1923 SET(bp->nb_flags, NB_INVAL); 1924 nfs_buf_release(bp, 1); 1925 continue; 1926 } 1927 /* gotta write out dirty data before invalidating */ 1928 /* (NB_STABLE indicates that data writes should be FILESYNC) */ 1929 /* (NB_NOCACHE indicates buffer should be discarded) */ 1930 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL | NB_ASYNC | NB_READ)); 1931 SET(bp->nb_flags, NB_STABLE | NB_NOCACHE); 1932 if (!IS_VALID_CRED(bp->nb_wcred)) { 1933 kauth_cred_t cred = vfs_context_ucred(ctx); 1934 kauth_cred_ref(cred); 1935 bp->nb_wcred = cred; 1936 } 1937 error = nfs_buf_write(bp); 1938 // Note: bp has been released 1939 if (error) { 1940 FSDBG(512, bp, 0xd00dee, 0xbad, error); 1941 nfs_node_lock_force(np); 1942 np->n_error = error; 1943 np->n_flag |= NWRITEERR; 1944 /* 1945 * There was a write error and we need to 1946 * invalidate attrs and flush buffers in 1947 * order to sync up with the server. 1948 * (if this write was extending the file, 1949 * we may no longer know the correct size) 1950 */ 1951 NATTRINVALIDATE(np); 1952 nfs_node_unlock(np); 1953 nfs_data_unlock(np); 1954 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, ctx, 1); 1955 nfs_data_lock(np, NFS_DATA_LOCK_EXCLUSIVE); 1956 error = 0; 1957 } 1958 } 1959 } 1960 if (vap->va_data_size != np->n_size) 1961 ubc_setsize(vp, (off_t)vap->va_data_size); /* XXX error? */ 1962 origsize = np->n_size; 1963 np->n_size = np->n_vattr.nva_size = vap->va_data_size; 1964 nfs_node_lock_force(np); 1965 CLR(np->n_flag, NUPDATESIZE); 1966 nfs_node_unlock(np); 1967 FSDBG(512, np, np->n_size, np->n_vattr.nva_size, 0xf00d0001); 1968 } 1969 } else if (VATTR_IS_ACTIVE(vap, va_modify_time) || 1970 VATTR_IS_ACTIVE(vap, va_access_time) || 1971 (vap->va_vaflags & VA_UTIMES_NULL)) { 1972 if ((error = nfs_node_lock(np))) 1973 return (error); 1974 if ((np->n_flag & NMODIFIED) && (vnode_vtype(vp) == VREG)) { 1975 nfs_node_unlock(np); 1976 error = nfs_vinvalbuf(vp, V_SAVE, ctx, 1); 1977 if (error == EINTR) 1978 return (error); 1979 } else { 1980 nfs_node_unlock(np); 1981 } 1982 } 1983 if ((VATTR_IS_ACTIVE(vap, va_mode) || VATTR_IS_ACTIVE(vap, va_uid) || VATTR_IS_ACTIVE(vap, va_gid) || 1984 VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_uuuid) || VATTR_IS_ACTIVE(vap, va_guuid)) && 1985 !(error = nfs_node_lock(np))) { 1986 NACCESSINVALIDATE(np); 1987 nfs_node_unlock(np); 1988 if (!namedattrs) { 1989 dvp = vnode_getparent(vp); 1990 vname = vnode_getname(vp); 1991 dnp = (dvp && vname) ? VTONFS(dvp) : NULL; 1992 if (dnp) { 1993 error = nfs_node_set_busy(dnp, vfs_context_thread(ctx)); 1994 if (error) { 1995 dnp = NULL; 1996 error = 0; 1997 } 1998 } 1999 if (dnp) { 2000 nfs_dulookup_init(&dul, dnp, vname, strlen(vname), ctx); 2001 nfs_dulookup_start(&dul, dnp, ctx); 2002 } 2003 } 2004 } 2005 2006 if (!error) 2007 error = nmp->nm_funcs->nf_setattr_rpc(np, vap, ctx); 2008 2009 if (VATTR_IS_ACTIVE(vap, va_mode) || VATTR_IS_ACTIVE(vap, va_uid) || VATTR_IS_ACTIVE(vap, va_gid) || 2010 VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_uuuid) || VATTR_IS_ACTIVE(vap, va_guuid)) { 2011 if (!namedattrs) { 2012 if (dnp) { 2013 nfs_dulookup_finish(&dul, dnp, ctx); 2014 nfs_node_clear_busy(dnp); 2015 } 2016 if (dvp != NULLVP) 2017 vnode_put(dvp); 2018 if (vname != NULL) 2019 vnode_putname(vname); 2020 } 2021 } 2022 2023 FSDBG_BOT(512, np->n_size, vap->va_data_size, np->n_vattr.nva_size, error); 2024 if (VATTR_IS_ACTIVE(vap, va_data_size)) { 2025 if (error && (origsize != np->n_size) && 2026 ((nfsvers < NFS_VER4) || !nfs_mount_state_error_should_restart(error))) { 2027 /* make every effort to resync file size w/ server... */ 2028 /* (don't bother if we'll be restarting the operation) */ 2029 int err; /* preserve "error" for return */ 2030 np->n_size = np->n_vattr.nva_size = origsize; 2031 nfs_node_lock_force(np); 2032 CLR(np->n_flag, NUPDATESIZE); 2033 nfs_node_unlock(np); 2034 FSDBG(512, np, np->n_size, np->n_vattr.nva_size, 0xf00d0002); 2035 ubc_setsize(vp, (off_t)np->n_size); /* XXX check error */ 2036 vapsize = vap->va_data_size; 2037 vap->va_data_size = origsize; 2038 err = nmp->nm_funcs->nf_setattr_rpc(np, vap, ctx); 2039 if (err) 2040 NP(np, "nfs_vnop_setattr: nfs%d_setattr_rpc %d %d", nfsvers, error, err); 2041 vap->va_data_size = vapsize; 2042 } 2043 nfs_node_lock_force(np); 2044 /* 2045 * The size was just set. If the size is already marked for update, don't 2046 * trust the newsize (it may have been set while the setattr was in progress). 2047 * Clear the update flag and make sure we fetch new attributes so we are sure 2048 * we have the latest size. 2049 */ 2050 if (ISSET(np->n_flag, NUPDATESIZE)) { 2051 CLR(np->n_flag, NUPDATESIZE); 2052 NATTRINVALIDATE(np); 2053 nfs_node_unlock(np); 2054 nfs_getattr(np, NULL, ctx, NGA_UNCACHED); 2055 } else { 2056 nfs_node_unlock(np); 2057 } 2058 nfs_data_unlock(np); 2059 if (nfsvers >= NFS_VER4) { 2060 if (nofp) { 2061 /* don't close our setattr open if we'll be restarting... */ 2062 if (!nfs_mount_state_error_should_restart(error) && 2063 (nofp->nof_flags & NFS_OPEN_FILE_SETATTR)) { 2064 int err = nfs_close(np, nofp, NFS_OPEN_SHARE_ACCESS_WRITE, NFS_OPEN_SHARE_DENY_NONE, ctx); 2065 if (err) 2066 NP(np, "nfs_vnop_setattr: close error: %d", err); 2067 nofp->nof_flags &= ~NFS_OPEN_FILE_SETATTR; 2068 } 2069 nfs_open_file_clear_busy(nofp); 2070 nofp = NULL; 2071 } 2072 if (nfs_mount_state_in_use_end(nmp, error)) 2073 goto restart; 2074 nfs_open_owner_rele(noop); 2075 } 2076 } 2077 return (error); 2078} 2079 2080/* 2081 * Do an NFS setattr RPC. 2082 */ 2083int 2084nfs3_setattr_rpc( 2085 nfsnode_t np, 2086 struct vnode_attr *vap, 2087 vfs_context_t ctx) 2088{ 2089 struct nfsmount *nmp = NFSTONMP(np); 2090 int error = 0, lockerror = ENOENT, status, wccpostattr = 0, nfsvers; 2091 u_int64_t xid, nextxid; 2092 struct nfsm_chain nmreq, nmrep; 2093 2094 if (nfs_mount_gone(nmp)) 2095 return (ENXIO); 2096 nfsvers = nmp->nm_vers; 2097 2098 VATTR_SET_SUPPORTED(vap, va_mode); 2099 VATTR_SET_SUPPORTED(vap, va_uid); 2100 VATTR_SET_SUPPORTED(vap, va_gid); 2101 VATTR_SET_SUPPORTED(vap, va_data_size); 2102 VATTR_SET_SUPPORTED(vap, va_access_time); 2103 VATTR_SET_SUPPORTED(vap, va_modify_time); 2104 2105 if (VATTR_IS_ACTIVE(vap, va_flags)) { 2106 if (vap->va_flags) { /* we don't support setting flags */ 2107 if (vap->va_active & ~VNODE_ATTR_va_flags) 2108 return (EINVAL); /* return EINVAL if other attributes also set */ 2109 else 2110 return (ENOTSUP); /* return ENOTSUP for chflags(2) */ 2111 } 2112 /* no flags set, so we'll just ignore it */ 2113 if (!(vap->va_active & ~VNODE_ATTR_va_flags)) 2114 return (0); /* no (other) attributes to set, so nothing to do */ 2115 } 2116 2117 nfsm_chain_null(&nmreq); 2118 nfsm_chain_null(&nmrep); 2119 2120 nfsm_chain_build_alloc_init(error, &nmreq, 2121 NFSX_FH(nfsvers) + NFSX_SATTR(nfsvers)); 2122 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 2123 if (nfsvers == NFS_VER3) { 2124 if (VATTR_IS_ACTIVE(vap, va_mode)) { 2125 nfsm_chain_add_32(error, &nmreq, TRUE); 2126 nfsm_chain_add_32(error, &nmreq, vap->va_mode); 2127 } else { 2128 nfsm_chain_add_32(error, &nmreq, FALSE); 2129 } 2130 if (VATTR_IS_ACTIVE(vap, va_uid)) { 2131 nfsm_chain_add_32(error, &nmreq, TRUE); 2132 nfsm_chain_add_32(error, &nmreq, vap->va_uid); 2133 } else { 2134 nfsm_chain_add_32(error, &nmreq, FALSE); 2135 } 2136 if (VATTR_IS_ACTIVE(vap, va_gid)) { 2137 nfsm_chain_add_32(error, &nmreq, TRUE); 2138 nfsm_chain_add_32(error, &nmreq, vap->va_gid); 2139 } else { 2140 nfsm_chain_add_32(error, &nmreq, FALSE); 2141 } 2142 if (VATTR_IS_ACTIVE(vap, va_data_size)) { 2143 nfsm_chain_add_32(error, &nmreq, TRUE); 2144 nfsm_chain_add_64(error, &nmreq, vap->va_data_size); 2145 } else { 2146 nfsm_chain_add_32(error, &nmreq, FALSE); 2147 } 2148 if (vap->va_vaflags & VA_UTIMES_NULL) { 2149 nfsm_chain_add_32(error, &nmreq, NFS_TIME_SET_TO_SERVER); 2150 nfsm_chain_add_32(error, &nmreq, NFS_TIME_SET_TO_SERVER); 2151 } else { 2152 if (VATTR_IS_ACTIVE(vap, va_access_time)) { 2153 nfsm_chain_add_32(error, &nmreq, NFS_TIME_SET_TO_CLIENT); 2154 nfsm_chain_add_32(error, &nmreq, vap->va_access_time.tv_sec); 2155 nfsm_chain_add_32(error, &nmreq, vap->va_access_time.tv_nsec); 2156 } else { 2157 nfsm_chain_add_32(error, &nmreq, NFS_TIME_DONT_CHANGE); 2158 } 2159 if (VATTR_IS_ACTIVE(vap, va_modify_time)) { 2160 nfsm_chain_add_32(error, &nmreq, NFS_TIME_SET_TO_CLIENT); 2161 nfsm_chain_add_32(error, &nmreq, vap->va_modify_time.tv_sec); 2162 nfsm_chain_add_32(error, &nmreq, vap->va_modify_time.tv_nsec); 2163 } else { 2164 nfsm_chain_add_32(error, &nmreq, NFS_TIME_DONT_CHANGE); 2165 } 2166 } 2167 nfsm_chain_add_32(error, &nmreq, FALSE); 2168 } else { 2169 nfsm_chain_add_32(error, &nmreq, VATTR_IS_ACTIVE(vap, va_mode) ? 2170 vtonfsv2_mode(vnode_vtype(NFSTOV(np)), vap->va_mode) : -1); 2171 nfsm_chain_add_32(error, &nmreq, VATTR_IS_ACTIVE(vap, va_uid) ? 2172 vap->va_uid : (uint32_t)-1); 2173 nfsm_chain_add_32(error, &nmreq, VATTR_IS_ACTIVE(vap, va_gid) ? 2174 vap->va_gid : (uint32_t)-1); 2175 nfsm_chain_add_32(error, &nmreq, VATTR_IS_ACTIVE(vap, va_data_size) ? 2176 vap->va_data_size : (uint32_t)-1); 2177 if (VATTR_IS_ACTIVE(vap, va_access_time)) { 2178 nfsm_chain_add_32(error, &nmreq, vap->va_access_time.tv_sec); 2179 nfsm_chain_add_32(error, &nmreq, (vap->va_access_time.tv_nsec != -1) ? 2180 ((uint32_t)vap->va_access_time.tv_nsec / 1000) : 0xffffffff); 2181 } else { 2182 nfsm_chain_add_32(error, &nmreq, -1); 2183 nfsm_chain_add_32(error, &nmreq, -1); 2184 } 2185 if (VATTR_IS_ACTIVE(vap, va_modify_time)) { 2186 nfsm_chain_add_32(error, &nmreq, vap->va_modify_time.tv_sec); 2187 nfsm_chain_add_32(error, &nmreq, (vap->va_modify_time.tv_nsec != -1) ? 2188 ((uint32_t)vap->va_modify_time.tv_nsec / 1000) : 0xffffffff); 2189 } else { 2190 nfsm_chain_add_32(error, &nmreq, -1); 2191 nfsm_chain_add_32(error, &nmreq, -1); 2192 } 2193 } 2194 nfsm_chain_build_done(error, &nmreq); 2195 nfsmout_if(error); 2196 error = nfs_request(np, NULL, &nmreq, NFSPROC_SETATTR, ctx, NULL, &nmrep, &xid, &status); 2197 if ((lockerror = nfs_node_lock(np))) 2198 error = lockerror; 2199 if (nfsvers == NFS_VER3) { 2200 struct timespec premtime = { 0, 0 }; 2201 nfsm_chain_get_wcc_data(error, &nmrep, np, &premtime, &wccpostattr, &xid); 2202 nfsmout_if(error); 2203 /* if file hadn't changed, update cached mtime */ 2204 if (nfstimespeccmp(&np->n_mtime, &premtime, ==)) 2205 NFS_CHANGED_UPDATE(nfsvers, np, &np->n_vattr); 2206 /* if directory hadn't changed, update namecache mtime */ 2207 if ((vnode_vtype(NFSTOV(np)) == VDIR) && 2208 nfstimespeccmp(&np->n_ncmtime, &premtime, ==)) 2209 NFS_CHANGED_UPDATE_NC(nfsvers, np, &np->n_vattr); 2210 if (!wccpostattr) 2211 NATTRINVALIDATE(np); 2212 error = status; 2213 } else { 2214 if (!error) 2215 error = status; 2216 nfsm_chain_loadattr(error, &nmrep, np, nfsvers, &xid); 2217 } 2218 /* 2219 * We just changed the attributes and we want to make sure that we 2220 * see the latest attributes. Get the next XID. If it's not the 2221 * next XID after the SETATTR XID, then it's possible that another 2222 * RPC was in flight at the same time and it might put stale attributes 2223 * in the cache. In that case, we invalidate the attributes and set 2224 * the attribute cache XID to guarantee that newer attributes will 2225 * get loaded next. 2226 */ 2227 nextxid = 0; 2228 nfs_get_xid(&nextxid); 2229 if (nextxid != (xid + 1)) { 2230 np->n_xid = nextxid; 2231 NATTRINVALIDATE(np); 2232 } 2233nfsmout: 2234 if (!lockerror) 2235 nfs_node_unlock(np); 2236 nfsm_chain_cleanup(&nmreq); 2237 nfsm_chain_cleanup(&nmrep); 2238 return (error); 2239} 2240 2241/* 2242 * NFS lookup call, one step at a time... 2243 * First look in cache 2244 * If not found, unlock the directory nfsnode and do the RPC 2245 */ 2246int 2247nfs_vnop_lookup( 2248 struct vnop_lookup_args /* { 2249 struct vnodeop_desc *a_desc; 2250 vnode_t a_dvp; 2251 vnode_t *a_vpp; 2252 struct componentname *a_cnp; 2253 vfs_context_t a_context; 2254 } */ *ap) 2255{ 2256 vfs_context_t ctx = ap->a_context; 2257 struct componentname *cnp = ap->a_cnp; 2258 vnode_t dvp = ap->a_dvp; 2259 vnode_t *vpp = ap->a_vpp; 2260 int flags = cnp->cn_flags; 2261 vnode_t newvp; 2262 nfsnode_t dnp, np; 2263 struct nfsmount *nmp; 2264 mount_t mp; 2265 int nfsvers, error, busyerror = ENOENT, isdot, isdotdot, negnamecache; 2266 u_int64_t xid; 2267 struct nfs_vattr nvattr; 2268 int ngflags; 2269 struct vnop_access_args naa; 2270 fhandle_t fh; 2271 struct nfsreq rq, *req = &rq; 2272 2273 *vpp = NULLVP; 2274 2275 dnp = VTONFS(dvp); 2276 NVATTR_INIT(&nvattr); 2277 2278 mp = vnode_mount(dvp); 2279 nmp = VFSTONFS(mp); 2280 if (nfs_mount_gone(nmp)) { 2281 error = ENXIO; 2282 goto error_return; 2283 } 2284 nfsvers = nmp->nm_vers; 2285 negnamecache = !NMFLAG(nmp, NONEGNAMECACHE); 2286 2287 if ((error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx)))) 2288 goto error_return; 2289 /* nfs_getattr() will check changed and purge caches */ 2290 if ((error = nfs_getattr(dnp, NULL, ctx, NGA_CACHED))) 2291 goto error_return; 2292 2293 error = cache_lookup(dvp, vpp, cnp); 2294 switch (error) { 2295 case ENOENT: 2296 /* negative cache entry */ 2297 goto error_return; 2298 case 0: 2299 /* cache miss */ 2300 if ((nfsvers > NFS_VER2) && NMFLAG(nmp, RDIRPLUS)) { 2301 /* if rdirplus, try dir buf cache lookup */ 2302 error = nfs_dir_buf_cache_lookup(dnp, &np, cnp, ctx, 0); 2303 if (!error && np) { 2304 /* dir buf cache hit */ 2305 *vpp = NFSTOV(np); 2306 error = -1; 2307 } 2308 } 2309 if (error != -1) /* cache miss */ 2310 break; 2311 /* FALLTHROUGH */ 2312 case -1: 2313 /* cache hit, not really an error */ 2314 OSAddAtomic64(1, &nfsstats.lookupcache_hits); 2315 2316 nfs_node_clear_busy(dnp); 2317 busyerror = ENOENT; 2318 2319 /* check for directory access */ 2320 naa.a_desc = &vnop_access_desc; 2321 naa.a_vp = dvp; 2322 naa.a_action = KAUTH_VNODE_SEARCH; 2323 naa.a_context = ctx; 2324 2325 /* compute actual success/failure based on accessibility */ 2326 error = nfs_vnop_access(&naa); 2327 /* FALLTHROUGH */ 2328 default: 2329 /* unexpected error from cache_lookup */ 2330 goto error_return; 2331 } 2332 2333 /* skip lookup, if we know who we are: "." or ".." */ 2334 isdot = isdotdot = 0; 2335 if (cnp->cn_nameptr[0] == '.') { 2336 if (cnp->cn_namelen == 1) 2337 isdot = 1; 2338 if ((cnp->cn_namelen == 2) && (cnp->cn_nameptr[1] == '.')) 2339 isdotdot = 1; 2340 } 2341 if (isdotdot || isdot) { 2342 fh.fh_len = 0; 2343 goto found; 2344 } 2345 if ((nfsvers >= NFS_VER4) && (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER)) { 2346 /* we should never be looking things up in a trigger directory, return nothing */ 2347 error = ENOENT; 2348 goto error_return; 2349 } 2350 2351 /* do we know this name is too long? */ 2352 nmp = VTONMP(dvp); 2353 if (nfs_mount_gone(nmp)) { 2354 error = ENXIO; 2355 goto error_return; 2356 } 2357 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME) && 2358 (cnp->cn_namelen > (int)nmp->nm_fsattr.nfsa_maxname)) { 2359 error = ENAMETOOLONG; 2360 goto error_return; 2361 } 2362 2363 error = 0; 2364 newvp = NULLVP; 2365 2366 OSAddAtomic64(1, &nfsstats.lookupcache_misses); 2367 2368 error = nmp->nm_funcs->nf_lookup_rpc_async(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, &req); 2369 nfsmout_if(error); 2370 error = nmp->nm_funcs->nf_lookup_rpc_async_finish(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, req, &xid, &fh, &nvattr); 2371 nfsmout_if(error); 2372 2373 /* is the file handle the same as this directory's file handle? */ 2374 isdot = NFS_CMPFH(dnp, fh.fh_data, fh.fh_len); 2375 2376found: 2377 if (flags & ISLASTCN) { 2378 switch (cnp->cn_nameiop) { 2379 case DELETE: 2380 cnp->cn_flags &= ~MAKEENTRY; 2381 break; 2382 case RENAME: 2383 cnp->cn_flags &= ~MAKEENTRY; 2384 if (isdot) { 2385 error = EISDIR; 2386 goto error_return; 2387 } 2388 break; 2389 } 2390 } 2391 2392 if (isdotdot) { 2393 newvp = vnode_getparent(dvp); 2394 if (!newvp) { 2395 error = ENOENT; 2396 goto error_return; 2397 } 2398 } else if (isdot) { 2399 error = vnode_get(dvp); 2400 if (error) 2401 goto error_return; 2402 newvp = dvp; 2403 nfs_node_lock_force(dnp); 2404 if (fh.fh_len && (dnp->n_xid <= xid)) 2405 nfs_loadattrcache(dnp, &nvattr, &xid, 0); 2406 nfs_node_unlock(dnp); 2407 } else { 2408 ngflags = (cnp->cn_flags & MAKEENTRY) ? NG_MAKEENTRY : 0; 2409 error = nfs_nget(mp, dnp, cnp, fh.fh_data, fh.fh_len, &nvattr, &xid, rq.r_auth, ngflags, &np); 2410 if (error) 2411 goto error_return; 2412 newvp = NFSTOV(np); 2413 nfs_node_unlock(np); 2414 } 2415 *vpp = newvp; 2416 2417nfsmout: 2418 if (error) { 2419 if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) && 2420 (flags & ISLASTCN) && (error == ENOENT)) { 2421 if (vnode_mount(dvp) && vnode_vfsisrdonly(dvp)) 2422 error = EROFS; 2423 else 2424 error = EJUSTRETURN; 2425 } 2426 } 2427 if ((error == ENOENT) && (cnp->cn_flags & MAKEENTRY) && 2428 (cnp->cn_nameiop != CREATE) && negnamecache) { 2429 /* add a negative entry in the name cache */ 2430 nfs_node_lock_force(dnp); 2431 cache_enter(dvp, NULL, cnp); 2432 dnp->n_flag |= NNEGNCENTRIES; 2433 nfs_node_unlock(dnp); 2434 } 2435error_return: 2436 NVATTR_CLEANUP(&nvattr); 2437 if (!busyerror) 2438 nfs_node_clear_busy(dnp); 2439 if (error && *vpp) { 2440 vnode_put(*vpp); 2441 *vpp = NULLVP; 2442 } 2443 return (error); 2444} 2445 2446int nfs_readlink_nocache = DEFAULT_READLINK_NOCACHE; 2447 2448/* 2449 * NFS readlink call 2450 */ 2451int 2452nfs_vnop_readlink( 2453 struct vnop_readlink_args /* { 2454 struct vnodeop_desc *a_desc; 2455 vnode_t a_vp; 2456 struct uio *a_uio; 2457 vfs_context_t a_context; 2458 } */ *ap) 2459{ 2460 vfs_context_t ctx = ap->a_context; 2461 nfsnode_t np = VTONFS(ap->a_vp); 2462 struct nfsmount *nmp; 2463 int error = 0, nfsvers; 2464 uint32_t buflen; 2465 uio_t uio = ap->a_uio; 2466 struct nfsbuf *bp = NULL; 2467 struct timespec ts; 2468 int timeo; 2469 2470 if (vnode_vtype(ap->a_vp) != VLNK) 2471 return (EPERM); 2472 2473 if (uio_resid(uio) == 0) 2474 return (0); 2475 if (uio_offset(uio) < 0) 2476 return (EINVAL); 2477 2478 nmp = VTONMP(ap->a_vp); 2479 if (nfs_mount_gone(nmp)) 2480 return (ENXIO); 2481 nfsvers = nmp->nm_vers; 2482 2483 2484 /* nfs_getattr() will check changed and purge caches */ 2485 if ((error = nfs_getattr(np, NULL, ctx, nfs_readlink_nocache ? NGA_UNCACHED : NGA_CACHED))) { 2486 FSDBG(531, np, 0xd1e0001, 0, error); 2487 return (error); 2488 } 2489 2490 if (nfs_readlink_nocache) { 2491 timeo = nfs_attrcachetimeout(np); 2492 nanouptime(&ts); 2493 } 2494 2495retry: 2496 OSAddAtomic64(1, &nfsstats.biocache_readlinks); 2497 error = nfs_buf_get(np, 0, NFS_MAXPATHLEN, vfs_context_thread(ctx), NBLK_META, &bp); 2498 if (error) { 2499 FSDBG(531, np, 0xd1e0002, 0, error); 2500 return (error); 2501 } 2502 2503 if (nfs_readlink_nocache) { 2504 NFS_VNOP_DBG("timeo = %d ts.tv_sec = %ld need refresh = %d cached = %d\n", timeo, ts.tv_sec, 2505 (np->n_rltim.tv_sec + timeo) < ts.tv_sec || nfs_readlink_nocache > 1, 2506 ISSET(bp->nb_flags, NB_CACHE) == NB_CACHE); 2507 /* n_rltim is synchronized by the associated nfs buf */ 2508 if (ISSET(bp->nb_flags, NB_CACHE) && ((nfs_readlink_nocache > 1) || ((np->n_rltim.tv_sec + timeo) < ts.tv_sec))) { 2509 SET(bp->nb_flags, NB_INVAL); 2510 nfs_buf_release(bp, 0); 2511 goto retry; 2512 } 2513 } 2514 if (!ISSET(bp->nb_flags, NB_CACHE)) { 2515readagain: 2516 OSAddAtomic64(1, &nfsstats.readlink_bios); 2517 buflen = bp->nb_bufsize; 2518 error = nmp->nm_funcs->nf_readlink_rpc(np, bp->nb_data, &buflen, ctx); 2519 if (error) { 2520 if (error == ESTALE) { 2521 NFS_VNOP_DBG("Stale FH from readlink rpc\n"); 2522 error = nfs_refresh_fh(np, ctx); 2523 if (error == 0) 2524 goto readagain; 2525 } 2526 SET(bp->nb_flags, NB_ERROR); 2527 bp->nb_error = error; 2528 NFS_VNOP_DBG("readlink failed %d\n", error); 2529 } else { 2530 bp->nb_validoff = 0; 2531 bp->nb_validend = buflen; 2532 np->n_rltim = ts; 2533 NFS_VNOP_DBG("readlink of %.*s\n", bp->nb_validend, (char *)bp->nb_data); 2534 } 2535 } else { 2536 NFS_VNOP_DBG("got cached link of %.*s\n", bp->nb_validend, (char *)bp->nb_data); 2537 } 2538 2539 if (!error && (bp->nb_validend > 0)) 2540 error = uiomove(bp->nb_data, bp->nb_validend, uio); 2541 FSDBG(531, np, bp->nb_validend, 0, error); 2542 nfs_buf_release(bp, 1); 2543 return (error); 2544} 2545 2546/* 2547 * Do a readlink RPC. 2548 */ 2549int 2550nfs3_readlink_rpc(nfsnode_t np, char *buf, uint32_t *buflenp, vfs_context_t ctx) 2551{ 2552 struct nfsmount *nmp; 2553 int error = 0, lockerror = ENOENT, nfsvers, status; 2554 uint32_t len; 2555 u_int64_t xid; 2556 struct nfsm_chain nmreq, nmrep; 2557 2558 nmp = NFSTONMP(np); 2559 if (nfs_mount_gone(nmp)) 2560 return (ENXIO); 2561 nfsvers = nmp->nm_vers; 2562 nfsm_chain_null(&nmreq); 2563 nfsm_chain_null(&nmrep); 2564 2565 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers)); 2566 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 2567 nfsm_chain_build_done(error, &nmreq); 2568 nfsmout_if(error); 2569 error = nfs_request(np, NULL, &nmreq, NFSPROC_READLINK, ctx, NULL, &nmrep, &xid, &status); 2570 if ((lockerror = nfs_node_lock(np))) 2571 error = lockerror; 2572 if (nfsvers == NFS_VER3) 2573 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 2574 if (!error) 2575 error = status; 2576 nfsm_chain_get_32(error, &nmrep, len); 2577 nfsmout_if(error); 2578 if ((nfsvers == NFS_VER2) && (len > *buflenp)) { 2579 error = EBADRPC; 2580 goto nfsmout; 2581 } 2582 if (len >= *buflenp) { 2583 if (np->n_size && (np->n_size < *buflenp)) 2584 len = np->n_size; 2585 else 2586 len = *buflenp - 1; 2587 } 2588 nfsm_chain_get_opaque(error, &nmrep, len, buf); 2589 if (!error) 2590 *buflenp = len; 2591nfsmout: 2592 if (!lockerror) 2593 nfs_node_unlock(np); 2594 nfsm_chain_cleanup(&nmreq); 2595 nfsm_chain_cleanup(&nmrep); 2596 return (error); 2597} 2598 2599/* 2600 * NFS read RPC call 2601 * Ditto above 2602 */ 2603int 2604nfs_read_rpc(nfsnode_t np, uio_t uio, vfs_context_t ctx) 2605{ 2606 struct nfsmount *nmp; 2607 int error = 0, nfsvers, eof = 0; 2608 size_t nmrsize, len, retlen; 2609 user_ssize_t tsiz; 2610 off_t txoffset; 2611 struct nfsreq rq, *req = &rq; 2612 uint32_t stategenid = 0, restart = 0; 2613 2614 FSDBG_TOP(536, np, uio_offset(uio), uio_resid(uio), 0); 2615 nmp = NFSTONMP(np); 2616 if (nfs_mount_gone(nmp)) 2617 return (ENXIO); 2618 nfsvers = nmp->nm_vers; 2619 nmrsize = nmp->nm_rsize; 2620 2621 txoffset = uio_offset(uio); 2622 tsiz = uio_resid(uio); 2623 if ((nfsvers == NFS_VER2) && ((uint64_t)(txoffset + tsiz) > 0xffffffffULL)) { 2624 FSDBG_BOT(536, np, uio_offset(uio), uio_resid(uio), EFBIG); 2625 return (EFBIG); 2626 } 2627 2628 while (tsiz > 0) { 2629 len = retlen = (tsiz > (user_ssize_t)nmrsize) ? nmrsize : (size_t)tsiz; 2630 FSDBG(536, np, txoffset, len, 0); 2631 if (np->n_flag & NREVOKE) { 2632 error = EIO; 2633 break; 2634 } 2635 if (nmp->nm_vers >= NFS_VER4) 2636 stategenid = nmp->nm_stategenid; 2637 error = nmp->nm_funcs->nf_read_rpc_async(np, txoffset, len, 2638 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, &req); 2639 if (!error) 2640 error = nmp->nm_funcs->nf_read_rpc_async_finish(np, req, uio, &retlen, &eof); 2641 if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error) && 2642 (++restart <= nfs_mount_state_max_restarts(nmp))) { /* guard against no progress */ 2643 lck_mtx_lock(&nmp->nm_lock); 2644 if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) { 2645 NP(np, "nfs_read_rpc: error %d, initiating recovery", error); 2646 nfs_need_recover(nmp, error); 2647 } 2648 lck_mtx_unlock(&nmp->nm_lock); 2649 if (np->n_flag & NREVOKE) { 2650 error = EIO; 2651 } else { 2652 if (error == NFSERR_GRACE) 2653 tsleep(&nmp->nm_state, (PZERO-1), "nfsgrace", 2*hz); 2654 if (!(error = nfs_mount_state_wait_for_recovery(nmp))) 2655 continue; 2656 } 2657 } 2658 if (error) 2659 break; 2660 txoffset += retlen; 2661 tsiz -= retlen; 2662 if (nfsvers != NFS_VER2) { 2663 if (eof || (retlen == 0)) 2664 tsiz = 0; 2665 } else if (retlen < len) 2666 tsiz = 0; 2667 } 2668 2669 FSDBG_BOT(536, np, eof, uio_resid(uio), error); 2670 return (error); 2671} 2672 2673int 2674nfs3_read_rpc_async( 2675 nfsnode_t np, 2676 off_t offset, 2677 size_t len, 2678 thread_t thd, 2679 kauth_cred_t cred, 2680 struct nfsreq_cbinfo *cb, 2681 struct nfsreq **reqp) 2682{ 2683 struct nfsmount *nmp; 2684 int error = 0, nfsvers; 2685 struct nfsm_chain nmreq; 2686 2687 nmp = NFSTONMP(np); 2688 if (nfs_mount_gone(nmp)) 2689 return (ENXIO); 2690 nfsvers = nmp->nm_vers; 2691 2692 nfsm_chain_null(&nmreq); 2693 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers) + 3 * NFSX_UNSIGNED); 2694 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 2695 if (nfsvers == NFS_VER3) { 2696 nfsm_chain_add_64(error, &nmreq, offset); 2697 nfsm_chain_add_32(error, &nmreq, len); 2698 } else { 2699 nfsm_chain_add_32(error, &nmreq, offset); 2700 nfsm_chain_add_32(error, &nmreq, len); 2701 nfsm_chain_add_32(error, &nmreq, 0); 2702 } 2703 nfsm_chain_build_done(error, &nmreq); 2704 nfsmout_if(error); 2705 error = nfs_request_async(np, NULL, &nmreq, NFSPROC_READ, thd, cred, NULL, 0, cb, reqp); 2706nfsmout: 2707 nfsm_chain_cleanup(&nmreq); 2708 return (error); 2709} 2710 2711int 2712nfs3_read_rpc_async_finish( 2713 nfsnode_t np, 2714 struct nfsreq *req, 2715 uio_t uio, 2716 size_t *lenp, 2717 int *eofp) 2718{ 2719 int error = 0, lockerror, nfsvers, status, eof = 0; 2720 size_t retlen = 0; 2721 uint64_t xid; 2722 struct nfsmount *nmp; 2723 struct nfsm_chain nmrep; 2724 2725 nmp = NFSTONMP(np); 2726 if (nfs_mount_gone(nmp)) { 2727 nfs_request_async_cancel(req); 2728 return (ENXIO); 2729 } 2730 nfsvers = nmp->nm_vers; 2731 2732 nfsm_chain_null(&nmrep); 2733 2734 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 2735 if (error == EINPROGRESS) /* async request restarted */ 2736 return (error); 2737 2738 if ((lockerror = nfs_node_lock(np))) 2739 error = lockerror; 2740 if (nfsvers == NFS_VER3) 2741 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 2742 if (!error) 2743 error = status; 2744 if (nfsvers == NFS_VER3) { 2745 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); 2746 nfsm_chain_get_32(error, &nmrep, eof); 2747 } else { 2748 nfsm_chain_loadattr(error, &nmrep, np, nfsvers, &xid); 2749 } 2750 if (!lockerror) 2751 nfs_node_unlock(np); 2752 nfsm_chain_get_32(error, &nmrep, retlen); 2753 if ((nfsvers == NFS_VER2) && (retlen > *lenp)) 2754 error = EBADRPC; 2755 nfsmout_if(error); 2756 error = nfsm_chain_get_uio(&nmrep, MIN(retlen, *lenp), uio); 2757 if (eofp) { 2758 if (nfsvers == NFS_VER3) { 2759 if (!eof && !retlen) 2760 eof = 1; 2761 } else if (retlen < *lenp) { 2762 eof = 1; 2763 } 2764 *eofp = eof; 2765 } 2766 *lenp = MIN(retlen, *lenp); 2767nfsmout: 2768 nfsm_chain_cleanup(&nmrep); 2769 return (error); 2770} 2771 2772/* 2773 * NFS write call 2774 */ 2775int 2776nfs_vnop_write( 2777 struct vnop_write_args /* { 2778 struct vnodeop_desc *a_desc; 2779 vnode_t a_vp; 2780 struct uio *a_uio; 2781 int a_ioflag; 2782 vfs_context_t a_context; 2783 } */ *ap) 2784{ 2785 vfs_context_t ctx = ap->a_context; 2786 uio_t uio = ap->a_uio; 2787 vnode_t vp = ap->a_vp; 2788 nfsnode_t np = VTONFS(vp); 2789 int ioflag = ap->a_ioflag; 2790 struct nfsbuf *bp; 2791 struct nfsmount *nmp = VTONMP(vp); 2792 daddr64_t lbn; 2793 int biosize; 2794 int n, on, error = 0; 2795 off_t boff, start, end; 2796 uio_t auio; 2797 char auio_buf [ UIO_SIZEOF(1) ]; 2798 thread_t thd; 2799 kauth_cred_t cred; 2800 2801 FSDBG_TOP(515, np, uio_offset(uio), uio_resid(uio), ioflag); 2802 2803 if (vnode_vtype(vp) != VREG) { 2804 FSDBG_BOT(515, np, uio_offset(uio), uio_resid(uio), EIO); 2805 return (EIO); 2806 } 2807 2808 thd = vfs_context_thread(ctx); 2809 cred = vfs_context_ucred(ctx); 2810 2811 nfs_data_lock(np, NFS_DATA_LOCK_SHARED); 2812 2813 if ((error = nfs_node_lock(np))) { 2814 nfs_data_unlock(np); 2815 FSDBG_BOT(515, np, uio_offset(uio), uio_resid(uio), error); 2816 return (error); 2817 } 2818 np->n_wrbusy++; 2819 2820 if (np->n_flag & NWRITEERR) { 2821 error = np->n_error; 2822 np->n_flag &= ~NWRITEERR; 2823 } 2824 if (np->n_flag & NNEEDINVALIDATE) { 2825 np->n_flag &= ~NNEEDINVALIDATE; 2826 nfs_node_unlock(np); 2827 nfs_data_unlock(np); 2828 nfs_vinvalbuf(vp, V_SAVE|V_IGNORE_WRITEERR, ctx, 1); 2829 nfs_data_lock(np, NFS_DATA_LOCK_SHARED); 2830 } else { 2831 nfs_node_unlock(np); 2832 } 2833 if (error) 2834 goto out; 2835 2836 biosize = nmp->nm_biosize; 2837 2838 if (ioflag & (IO_APPEND | IO_SYNC)) { 2839 nfs_node_lock_force(np); 2840 if (np->n_flag & NMODIFIED) { 2841 NATTRINVALIDATE(np); 2842 nfs_node_unlock(np); 2843 nfs_data_unlock(np); 2844 error = nfs_vinvalbuf(vp, V_SAVE, ctx, 1); 2845 nfs_data_lock(np, NFS_DATA_LOCK_SHARED); 2846 if (error) { 2847 FSDBG(515, np, uio_offset(uio), 0x10bad01, error); 2848 goto out; 2849 } 2850 } else { 2851 nfs_node_unlock(np); 2852 } 2853 if (ioflag & IO_APPEND) { 2854 nfs_data_unlock(np); 2855 /* nfs_getattr() will check changed and purge caches */ 2856 error = nfs_getattr(np, NULL, ctx, NGA_UNCACHED); 2857 /* we'll be extending the file, so take the data lock exclusive */ 2858 nfs_data_lock(np, NFS_DATA_LOCK_EXCLUSIVE); 2859 if (error) { 2860 FSDBG(515, np, uio_offset(uio), 0x10bad02, error); 2861 goto out; 2862 } 2863 uio_setoffset(uio, np->n_size); 2864 } 2865 } 2866 if (uio_offset(uio) < 0) { 2867 error = EINVAL; 2868 FSDBG_BOT(515, np, uio_offset(uio), 0xbad0ff, error); 2869 goto out; 2870 } 2871 if (uio_resid(uio) == 0) 2872 goto out; 2873 2874 if (((uio_offset(uio) + uio_resid(uio)) > (off_t)np->n_size) && !(ioflag & IO_APPEND)) { 2875 /* 2876 * It looks like we'll be extending the file, so take the data lock exclusive. 2877 */ 2878 nfs_data_unlock(np); 2879 nfs_data_lock(np, NFS_DATA_LOCK_EXCLUSIVE); 2880 2881 /* 2882 * Also, if the write begins after the previous EOF buffer, make sure to zero 2883 * and validate the new bytes in that buffer. 2884 */ 2885 struct nfsbuf *eofbp = NULL; 2886 daddr64_t eofbn = np->n_size / biosize; 2887 int eofoff = np->n_size % biosize; 2888 lbn = uio_offset(uio) / biosize; 2889 2890 if (eofoff && (eofbn < lbn)) { 2891 if ((error = nfs_buf_get(np, eofbn, biosize, thd, NBLK_WRITE|NBLK_ONLYVALID, &eofbp))) 2892 goto out; 2893 np->n_size += (biosize - eofoff); 2894 nfs_node_lock_force(np); 2895 CLR(np->n_flag, NUPDATESIZE); 2896 np->n_flag |= NMODIFIED; 2897 nfs_node_unlock(np); 2898 FSDBG(516, np, np->n_size, np->n_vattr.nva_size, 0xf00d0001); 2899 ubc_setsize(vp, (off_t)np->n_size); /* XXX errors */ 2900 if (eofbp) { 2901 /* 2902 * For the old last page, don't zero bytes if there 2903 * are invalid bytes in that page (i.e. the page isn't 2904 * currently valid). 2905 * For pages after the old last page, zero them and 2906 * mark them as valid. 2907 */ 2908 char *d; 2909 int i; 2910 if (ioflag & IO_NOCACHE) 2911 SET(eofbp->nb_flags, NB_NOCACHE); 2912 NFS_BUF_MAP(eofbp); 2913 FSDBG(516, eofbp, eofoff, biosize - eofoff, 0xe0fff01e); 2914 d = eofbp->nb_data; 2915 i = eofoff/PAGE_SIZE; 2916 while (eofoff < biosize) { 2917 int poff = eofoff & PAGE_MASK; 2918 if (!poff || NBPGVALID(eofbp,i)) { 2919 bzero(d + eofoff, PAGE_SIZE - poff); 2920 NBPGVALID_SET(eofbp, i); 2921 } 2922 eofoff += PAGE_SIZE - poff; 2923 i++; 2924 } 2925 nfs_buf_release(eofbp, 1); 2926 } 2927 } 2928 } 2929 2930 do { 2931 OSAddAtomic64(1, &nfsstats.biocache_writes); 2932 lbn = uio_offset(uio) / biosize; 2933 on = uio_offset(uio) % biosize; 2934 n = biosize - on; 2935 if (uio_resid(uio) < n) 2936 n = uio_resid(uio); 2937again: 2938 /* 2939 * Get a cache block for writing. The range to be written is 2940 * (off..off+n) within the block. We ensure that the block 2941 * either has no dirty region or that the given range is 2942 * contiguous with the existing dirty region. 2943 */ 2944 error = nfs_buf_get(np, lbn, biosize, thd, NBLK_WRITE, &bp); 2945 if (error) 2946 goto out; 2947 /* map the block because we know we're going to write to it */ 2948 NFS_BUF_MAP(bp); 2949 2950 if (ioflag & IO_NOCACHE) 2951 SET(bp->nb_flags, NB_NOCACHE); 2952 2953 if (!IS_VALID_CRED(bp->nb_wcred)) { 2954 kauth_cred_ref(cred); 2955 bp->nb_wcred = cred; 2956 } 2957 2958 /* 2959 * If there's already a dirty range AND dirty pages in this block we 2960 * need to send a commit AND write the dirty pages before continuing. 2961 * 2962 * If there's already a dirty range OR dirty pages in this block 2963 * and the new write range is not contiguous with the existing range, 2964 * then force the buffer to be written out now. 2965 * (We used to just extend the dirty range to cover the valid, 2966 * but unwritten, data in between also. But writing ranges 2967 * of data that weren't actually written by an application 2968 * risks overwriting some other client's data with stale data 2969 * that's just masquerading as new written data.) 2970 */ 2971 if (bp->nb_dirtyend > 0) { 2972 if (on > bp->nb_dirtyend || (on + n) < bp->nb_dirtyoff || bp->nb_dirty) { 2973 FSDBG(515, np, uio_offset(uio), bp, 0xd15c001); 2974 /* write/commit buffer "synchronously" */ 2975 /* (NB_STABLE indicates that data writes should be FILESYNC) */ 2976 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL)); 2977 SET(bp->nb_flags, (NB_ASYNC | NB_STABLE)); 2978 error = nfs_buf_write(bp); 2979 if (error) 2980 goto out; 2981 goto again; 2982 } 2983 } else if (bp->nb_dirty) { 2984 int firstpg, lastpg; 2985 u_int32_t pagemask; 2986 /* calculate write range pagemask */ 2987 firstpg = on/PAGE_SIZE; 2988 lastpg = (on+n-1)/PAGE_SIZE; 2989 pagemask = ((1 << (lastpg+1)) - 1) & ~((1 << firstpg) - 1); 2990 /* check if there are dirty pages outside the write range */ 2991 if (bp->nb_dirty & ~pagemask) { 2992 FSDBG(515, np, uio_offset(uio), bp, 0xd15c002); 2993 /* write/commit buffer "synchronously" */ 2994 /* (NB_STABLE indicates that data writes should be FILESYNC) */ 2995 CLR(bp->nb_flags, (NB_DONE | NB_ERROR | NB_INVAL)); 2996 SET(bp->nb_flags, (NB_ASYNC | NB_STABLE)); 2997 error = nfs_buf_write(bp); 2998 if (error) 2999 goto out; 3000 goto again; 3001 } 3002 /* if the first or last pages are already dirty */ 3003 /* make sure that the dirty range encompasses those pages */ 3004 if (NBPGDIRTY(bp,firstpg) || NBPGDIRTY(bp,lastpg)) { 3005 FSDBG(515, np, uio_offset(uio), bp, 0xd15c003); 3006 bp->nb_dirtyoff = min(on, firstpg * PAGE_SIZE); 3007 if (NBPGDIRTY(bp,lastpg)) { 3008 bp->nb_dirtyend = (lastpg+1) * PAGE_SIZE; 3009 /* clip to EOF */ 3010 if (NBOFF(bp) + bp->nb_dirtyend > (off_t)np->n_size) { 3011 bp->nb_dirtyend = np->n_size - NBOFF(bp); 3012 if (bp->nb_dirtyoff >= bp->nb_dirtyend) 3013 bp->nb_dirtyoff = bp->nb_dirtyend = 0; 3014 } 3015 } else 3016 bp->nb_dirtyend = on+n; 3017 } 3018 } 3019 3020 /* 3021 * Are we extending the size of the file with this write? 3022 * If so, update file size now that we have the block. 3023 * If there was a partial buf at the old eof, validate 3024 * and zero the new bytes. 3025 */ 3026 if ((uio_offset(uio) + n) > (off_t)np->n_size) { 3027 daddr64_t eofbn = np->n_size / biosize; 3028 int neweofoff = (uio_offset(uio) + n) % biosize; 3029 3030 FSDBG(515, 0xb1ffa000, uio_offset(uio) + n, eofoff, neweofoff); 3031 3032 /* if we're extending within the same last block */ 3033 /* and the block is flagged as being cached... */ 3034 if ((lbn == eofbn) && ISSET(bp->nb_flags, NB_CACHE)) { 3035 /* ...check that all pages in buffer are valid */ 3036 int endpg = ((neweofoff ? neweofoff : biosize) - 1)/PAGE_SIZE; 3037 u_int32_t pagemask; 3038 /* pagemask only has to extend to last page being written to */ 3039 pagemask = (1 << (endpg+1)) - 1; 3040 FSDBG(515, 0xb1ffa001, bp->nb_valid, pagemask, 0); 3041 if ((bp->nb_valid & pagemask) != pagemask) { 3042 /* zerofill any hole */ 3043 if (on > bp->nb_validend) { 3044 int i; 3045 for (i=bp->nb_validend/PAGE_SIZE; i <= (on - 1)/PAGE_SIZE; i++) 3046 NBPGVALID_SET(bp, i); 3047 NFS_BUF_MAP(bp); 3048 FSDBG(516, bp, bp->nb_validend, on - bp->nb_validend, 0xf01e); 3049 bzero((char *)bp->nb_data + bp->nb_validend, 3050 on - bp->nb_validend); 3051 } 3052 /* zerofill any trailing data in the last page */ 3053 if (neweofoff) { 3054 NFS_BUF_MAP(bp); 3055 FSDBG(516, bp, neweofoff, PAGE_SIZE - (neweofoff & PAGE_MASK), 0xe0f); 3056 bzero((char *)bp->nb_data + neweofoff, 3057 PAGE_SIZE - (neweofoff & PAGE_MASK)); 3058 } 3059 } 3060 } 3061 np->n_size = uio_offset(uio) + n; 3062 nfs_node_lock_force(np); 3063 CLR(np->n_flag, NUPDATESIZE); 3064 np->n_flag |= NMODIFIED; 3065 nfs_node_unlock(np); 3066 FSDBG(516, np, np->n_size, np->n_vattr.nva_size, 0xf00d0001); 3067 ubc_setsize(vp, (off_t)np->n_size); /* XXX errors */ 3068 } 3069 /* 3070 * If dirtyend exceeds file size, chop it down. This should 3071 * not occur unless there is a race. 3072 */ 3073 if (NBOFF(bp) + bp->nb_dirtyend > (off_t)np->n_size) { 3074 bp->nb_dirtyend = np->n_size - NBOFF(bp); 3075 if (bp->nb_dirtyoff >= bp->nb_dirtyend) 3076 bp->nb_dirtyoff = bp->nb_dirtyend = 0; 3077 } 3078 /* 3079 * UBC doesn't handle partial pages, so we need to make sure 3080 * that any pages left in the page cache are completely valid. 3081 * 3082 * Writes that are smaller than a block are delayed if they 3083 * don't extend to the end of the block. 3084 * 3085 * If the block isn't (completely) cached, we may need to read 3086 * in some parts of pages that aren't covered by the write. 3087 * If the write offset (on) isn't page aligned, we'll need to 3088 * read the start of the first page being written to. Likewise, 3089 * if the offset of the end of the write (on+n) isn't page aligned, 3090 * we'll need to read the end of the last page being written to. 3091 * 3092 * Notes: 3093 * We don't want to read anything we're just going to write over. 3094 * We don't want to read anything we're just going drop when the 3095 * I/O is complete (i.e. don't do reads for NOCACHE requests). 3096 * We don't want to issue multiple I/Os if we don't have to 3097 * (because they're synchronous rpcs). 3098 * We don't want to read anything we already have modified in the 3099 * page cache. 3100 */ 3101 if (!ISSET(bp->nb_flags, NB_CACHE) && (n < biosize)) { 3102 int firstpg, lastpg, dirtypg; 3103 int firstpgoff, lastpgoff; 3104 start = end = -1; 3105 firstpg = on/PAGE_SIZE; 3106 firstpgoff = on & PAGE_MASK; 3107 lastpg = (on+n-1)/PAGE_SIZE; 3108 lastpgoff = (on+n) & PAGE_MASK; 3109 if (firstpgoff && !NBPGVALID(bp,firstpg)) { 3110 /* need to read start of first page */ 3111 start = firstpg * PAGE_SIZE; 3112 end = start + firstpgoff; 3113 } 3114 if (lastpgoff && !NBPGVALID(bp,lastpg)) { 3115 /* need to read end of last page */ 3116 if (start < 0) 3117 start = (lastpg * PAGE_SIZE) + lastpgoff; 3118 end = (lastpg + 1) * PAGE_SIZE; 3119 } 3120 if (ISSET(bp->nb_flags, NB_NOCACHE)) { 3121 /* 3122 * For nocache writes, if there is any partial page at the 3123 * start or end of the write range, then we do the write 3124 * synchronously to make sure that we can drop the data 3125 * from the cache as soon as the WRITE finishes. Normally, 3126 * we would do an unstable write and not drop the data until 3127 * it was committed. But doing that here would risk allowing 3128 * invalid data to be read from the cache between the WRITE 3129 * and the COMMIT. 3130 * (NB_STABLE indicates that data writes should be FILESYNC) 3131 */ 3132 if (end > start) 3133 SET(bp->nb_flags, NB_STABLE); 3134 goto skipread; 3135 } 3136 if (end > start) { 3137 /* need to read the data in range: start...end-1 */ 3138 3139 /* first, check for dirty pages in between */ 3140 /* if there are, we'll have to do two reads because */ 3141 /* we don't want to overwrite the dirty pages. */ 3142 for (dirtypg=start/PAGE_SIZE; dirtypg <= (end-1)/PAGE_SIZE; dirtypg++) 3143 if (NBPGDIRTY(bp,dirtypg)) 3144 break; 3145 3146 /* if start is at beginning of page, try */ 3147 /* to get any preceeding pages as well. */ 3148 if (!(start & PAGE_MASK)) { 3149 /* stop at next dirty/valid page or start of block */ 3150 for (; start > 0; start-=PAGE_SIZE) 3151 if (NBPGVALID(bp,((start-1)/PAGE_SIZE))) 3152 break; 3153 } 3154 3155 NFS_BUF_MAP(bp); 3156 /* setup uio for read(s) */ 3157 boff = NBOFF(bp); 3158 auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, 3159 &auio_buf, sizeof(auio_buf)); 3160 3161 if (dirtypg <= (end-1)/PAGE_SIZE) { 3162 /* there's a dirty page in the way, so just do two reads */ 3163 /* we'll read the preceding data here */ 3164 uio_reset(auio, boff + start, UIO_SYSSPACE, UIO_READ); 3165 uio_addiov(auio, CAST_USER_ADDR_T(bp->nb_data + start), on - start); 3166 error = nfs_read_rpc(np, auio, ctx); 3167 if (error) { 3168 /* couldn't read the data, so treat buffer as synchronous NOCACHE */ 3169 SET(bp->nb_flags, (NB_NOCACHE|NB_STABLE)); 3170 goto skipread; 3171 } 3172 if (uio_resid(auio) > 0) { 3173 FSDBG(516, bp, (caddr_t)uio_curriovbase(auio) - bp->nb_data, uio_resid(auio), 0xd00dee01); 3174 bzero(CAST_DOWN(caddr_t, uio_curriovbase(auio)), uio_resid(auio)); 3175 } 3176 if (!error) { 3177 /* update validoff/validend if necessary */ 3178 if ((bp->nb_validoff < 0) || (bp->nb_validoff > start)) 3179 bp->nb_validoff = start; 3180 if ((bp->nb_validend < 0) || (bp->nb_validend < on)) 3181 bp->nb_validend = on; 3182 if ((off_t)np->n_size > boff + bp->nb_validend) 3183 bp->nb_validend = min(np->n_size - (boff + start), biosize); 3184 /* validate any pages before the write offset */ 3185 for (; start < on/PAGE_SIZE; start+=PAGE_SIZE) 3186 NBPGVALID_SET(bp, start/PAGE_SIZE); 3187 } 3188 /* adjust start to read any trailing data */ 3189 start = on+n; 3190 } 3191 3192 /* if end is at end of page, try to */ 3193 /* get any following pages as well. */ 3194 if (!(end & PAGE_MASK)) { 3195 /* stop at next valid page or end of block */ 3196 for (; end < biosize; end+=PAGE_SIZE) 3197 if (NBPGVALID(bp,end/PAGE_SIZE)) 3198 break; 3199 } 3200 3201 if (((boff+start) >= (off_t)np->n_size) || 3202 ((start >= on) && ((boff + on + n) >= (off_t)np->n_size))) { 3203 /* 3204 * Either this entire read is beyond the current EOF 3205 * or the range that we won't be modifying (on+n...end) 3206 * is all beyond the current EOF. 3207 * No need to make a trip across the network to 3208 * read nothing. So, just zero the buffer instead. 3209 */ 3210 FSDBG(516, bp, start, end - start, 0xd00dee00); 3211 bzero(bp->nb_data + start, end - start); 3212 error = 0; 3213 } else { 3214 /* now we'll read the (rest of the) data */ 3215 uio_reset(auio, boff + start, UIO_SYSSPACE, UIO_READ); 3216 uio_addiov(auio, CAST_USER_ADDR_T(bp->nb_data + start), end - start); 3217 error = nfs_read_rpc(np, auio, ctx); 3218 if (error) { 3219 /* couldn't read the data, so treat buffer as synchronous NOCACHE */ 3220 SET(bp->nb_flags, (NB_NOCACHE|NB_STABLE)); 3221 goto skipread; 3222 } 3223 if (uio_resid(auio) > 0) { 3224 FSDBG(516, bp, (caddr_t)uio_curriovbase(auio) - bp->nb_data, uio_resid(auio), 0xd00dee02); 3225 bzero(CAST_DOWN(caddr_t, uio_curriovbase(auio)), uio_resid(auio)); 3226 } 3227 } 3228 if (!error) { 3229 /* update validoff/validend if necessary */ 3230 if ((bp->nb_validoff < 0) || (bp->nb_validoff > start)) 3231 bp->nb_validoff = start; 3232 if ((bp->nb_validend < 0) || (bp->nb_validend < end)) 3233 bp->nb_validend = end; 3234 if ((off_t)np->n_size > boff + bp->nb_validend) 3235 bp->nb_validend = min(np->n_size - (boff + start), biosize); 3236 /* validate any pages before the write offset's page */ 3237 for (; start < (off_t)trunc_page_32(on); start+=PAGE_SIZE) 3238 NBPGVALID_SET(bp, start/PAGE_SIZE); 3239 /* validate any pages after the range of pages being written to */ 3240 for (; (end - 1) > (off_t)round_page_32(on+n-1); end-=PAGE_SIZE) 3241 NBPGVALID_SET(bp, (end-1)/PAGE_SIZE); 3242 } 3243 /* Note: pages being written to will be validated when written */ 3244 } 3245 } 3246skipread: 3247 3248 if (ISSET(bp->nb_flags, NB_ERROR)) { 3249 error = bp->nb_error; 3250 nfs_buf_release(bp, 1); 3251 goto out; 3252 } 3253 3254 nfs_node_lock_force(np); 3255 np->n_flag |= NMODIFIED; 3256 nfs_node_unlock(np); 3257 3258 NFS_BUF_MAP(bp); 3259 error = uiomove((char *)bp->nb_data + on, n, uio); 3260 if (error) { 3261 SET(bp->nb_flags, NB_ERROR); 3262 nfs_buf_release(bp, 1); 3263 goto out; 3264 } 3265 3266 /* validate any pages written to */ 3267 start = on & ~PAGE_MASK; 3268 for (; start < on+n; start += PAGE_SIZE) { 3269 NBPGVALID_SET(bp, start/PAGE_SIZE); 3270 /* 3271 * This may seem a little weird, but we don't actually set the 3272 * dirty bits for writes. This is because we keep the dirty range 3273 * in the nb_dirtyoff/nb_dirtyend fields. Also, particularly for 3274 * delayed writes, when we give the pages back to the VM we don't 3275 * want to keep them marked dirty, because when we later write the 3276 * buffer we won't be able to tell which pages were written dirty 3277 * and which pages were mmapped and dirtied. 3278 */ 3279 } 3280 if (bp->nb_dirtyend > 0) { 3281 bp->nb_dirtyoff = min(on, bp->nb_dirtyoff); 3282 bp->nb_dirtyend = max((on + n), bp->nb_dirtyend); 3283 } else { 3284 bp->nb_dirtyoff = on; 3285 bp->nb_dirtyend = on + n; 3286 } 3287 if (bp->nb_validend <= 0 || bp->nb_validend < bp->nb_dirtyoff || 3288 bp->nb_validoff > bp->nb_dirtyend) { 3289 bp->nb_validoff = bp->nb_dirtyoff; 3290 bp->nb_validend = bp->nb_dirtyend; 3291 } else { 3292 bp->nb_validoff = min(bp->nb_validoff, bp->nb_dirtyoff); 3293 bp->nb_validend = max(bp->nb_validend, bp->nb_dirtyend); 3294 } 3295 if (!ISSET(bp->nb_flags, NB_CACHE)) 3296 nfs_buf_normalize_valid_range(np, bp); 3297 3298 /* 3299 * Since this block is being modified, it must be written 3300 * again and not just committed. 3301 */ 3302 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) { 3303 nfs_node_lock_force(np); 3304 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) { 3305 np->n_needcommitcnt--; 3306 CHECK_NEEDCOMMITCNT(np); 3307 } 3308 CLR(bp->nb_flags, NB_NEEDCOMMIT); 3309 nfs_node_unlock(np); 3310 } 3311 3312 if (ioflag & IO_SYNC) { 3313 error = nfs_buf_write(bp); 3314 if (error) 3315 goto out; 3316 } else if (((n + on) == biosize) || (ioflag & IO_APPEND) || 3317 (ioflag & IO_NOCACHE) || ISSET(bp->nb_flags, NB_NOCACHE)) { 3318 SET(bp->nb_flags, NB_ASYNC); 3319 error = nfs_buf_write(bp); 3320 if (error) 3321 goto out; 3322 } else { 3323 /* If the block wasn't already delayed: charge for the write */ 3324 if (!ISSET(bp->nb_flags, NB_DELWRI)) { 3325 proc_t p = vfs_context_proc(ctx); 3326 if (p && p->p_stats) 3327 OSIncrementAtomicLong(&p->p_stats->p_ru.ru_oublock); 3328 } 3329 nfs_buf_write_delayed(bp); 3330 } 3331 if (np->n_needcommitcnt >= NFS_A_LOT_OF_NEEDCOMMITS) 3332 nfs_flushcommits(np, 1); 3333 3334 } while (uio_resid(uio) > 0 && n > 0); 3335 3336out: 3337 nfs_node_lock_force(np); 3338 np->n_wrbusy--; 3339 nfs_node_unlock(np); 3340 nfs_data_unlock(np); 3341 FSDBG_BOT(515, np, uio_offset(uio), uio_resid(uio), error); 3342 return (error); 3343} 3344 3345 3346/* 3347 * NFS write call 3348 */ 3349int 3350nfs_write_rpc( 3351 nfsnode_t np, 3352 uio_t uio, 3353 vfs_context_t ctx, 3354 int *iomodep, 3355 uint64_t *wverfp) 3356{ 3357 return nfs_write_rpc2(np, uio, vfs_context_thread(ctx), vfs_context_ucred(ctx), iomodep, wverfp); 3358} 3359 3360int 3361nfs_write_rpc2( 3362 nfsnode_t np, 3363 uio_t uio, 3364 thread_t thd, 3365 kauth_cred_t cred, 3366 int *iomodep, 3367 uint64_t *wverfp) 3368{ 3369 struct nfsmount *nmp; 3370 int error = 0, nfsvers; 3371 int wverfset, commit, committed; 3372 uint64_t wverf = 0, wverf2; 3373 size_t nmwsize, totalsize, tsiz, len, rlen; 3374 struct nfsreq rq, *req = &rq; 3375 uint32_t stategenid = 0, vrestart = 0, restart = 0; 3376 uio_t uio_save = NULL; 3377 3378#if DIAGNOSTIC 3379 /* XXX limitation based on need to back up uio on short write */ 3380 if (uio_iovcnt(uio) != 1) 3381 panic("nfs3_write_rpc: iovcnt > 1"); 3382#endif 3383 FSDBG_TOP(537, np, uio_offset(uio), uio_resid(uio), *iomodep); 3384 nmp = NFSTONMP(np); 3385 if (nfs_mount_gone(nmp)) 3386 return (ENXIO); 3387 nfsvers = nmp->nm_vers; 3388 nmwsize = nmp->nm_wsize; 3389 3390 wverfset = 0; 3391 committed = NFS_WRITE_FILESYNC; 3392 3393 totalsize = tsiz = uio_resid(uio); 3394 if ((nfsvers == NFS_VER2) && ((uint64_t)(uio_offset(uio) + tsiz) > 0xffffffffULL)) { 3395 FSDBG_BOT(537, np, uio_offset(uio), uio_resid(uio), EFBIG); 3396 return (EFBIG); 3397 } 3398 3399 uio_save = uio_duplicate(uio); 3400 if (uio_save == NULL) { 3401 return (EIO); 3402 } 3403 3404 while (tsiz > 0) { 3405 len = (tsiz > nmwsize) ? nmwsize : tsiz; 3406 FSDBG(537, np, uio_offset(uio), len, 0); 3407 if (np->n_flag & NREVOKE) { 3408 error = EIO; 3409 break; 3410 } 3411 if (nmp->nm_vers >= NFS_VER4) 3412 stategenid = nmp->nm_stategenid; 3413 error = nmp->nm_funcs->nf_write_rpc_async(np, uio, len, thd, cred, *iomodep, NULL, &req); 3414 if (!error) 3415 error = nmp->nm_funcs->nf_write_rpc_async_finish(np, req, &commit, &rlen, &wverf2); 3416 nmp = NFSTONMP(np); 3417 if (nfs_mount_gone(nmp)) 3418 error = ENXIO; 3419 if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error) && 3420 (++restart <= nfs_mount_state_max_restarts(nmp))) { /* guard against no progress */ 3421 lck_mtx_lock(&nmp->nm_lock); 3422 if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) { 3423 NP(np, "nfs_write_rpc: error %d, initiating recovery", error); 3424 nfs_need_recover(nmp, error); 3425 } 3426 lck_mtx_unlock(&nmp->nm_lock); 3427 if (np->n_flag & NREVOKE) { 3428 error = EIO; 3429 } else { 3430 if (error == NFSERR_GRACE) 3431 tsleep(&nmp->nm_state, (PZERO-1), "nfsgrace", 2*hz); 3432 if (!(error = nfs_mount_state_wait_for_recovery(nmp))) 3433 continue; 3434 } 3435 } 3436 if (error) 3437 break; 3438 if (nfsvers == NFS_VER2) { 3439 tsiz -= len; 3440 continue; 3441 } 3442 3443 /* check for a short write */ 3444 if (rlen < len) { 3445 /* Reset the uio to reflect the actual transfer */ 3446 *uio = *uio_save; 3447 uio_update(uio, totalsize - (tsiz - rlen)); 3448 len = rlen; 3449 } 3450 3451 /* return lowest commit level returned */ 3452 if (commit < committed) 3453 committed = commit; 3454 3455 tsiz -= len; 3456 3457 /* check write verifier */ 3458 if (!wverfset) { 3459 wverf = wverf2; 3460 wverfset = 1; 3461 } else if (wverf != wverf2) { 3462 /* verifier changed, so we need to restart all the writes */ 3463 if (++vrestart > 100) { 3464 /* give up after too many restarts */ 3465 error = EIO; 3466 break; 3467 } 3468 *uio = *uio_save; // Reset the uio back to the start 3469 committed = NFS_WRITE_FILESYNC; 3470 wverfset = 0; 3471 tsiz = totalsize; 3472 } 3473 } 3474 if (uio_save) 3475 uio_free(uio_save); 3476 if (wverfset && wverfp) 3477 *wverfp = wverf; 3478 *iomodep = committed; 3479 if (error) 3480 uio_setresid(uio, tsiz); 3481 FSDBG_BOT(537, np, committed, uio_resid(uio), error); 3482 return (error); 3483} 3484 3485int 3486nfs3_write_rpc_async( 3487 nfsnode_t np, 3488 uio_t uio, 3489 size_t len, 3490 thread_t thd, 3491 kauth_cred_t cred, 3492 int iomode, 3493 struct nfsreq_cbinfo *cb, 3494 struct nfsreq **reqp) 3495{ 3496 struct nfsmount *nmp; 3497 mount_t mp; 3498 int error = 0, nfsvers; 3499 struct nfsm_chain nmreq; 3500 3501 nmp = NFSTONMP(np); 3502 if (nfs_mount_gone(nmp)) 3503 return (ENXIO); 3504 nfsvers = nmp->nm_vers; 3505 3506 /* for async mounts, don't bother sending sync write requests */ 3507 if ((iomode != NFS_WRITE_UNSTABLE) && nfs_allow_async && 3508 ((mp = NFSTOMP(np))) && (vfs_flags(mp) & MNT_ASYNC)) 3509 iomode = NFS_WRITE_UNSTABLE; 3510 3511 nfsm_chain_null(&nmreq); 3512 nfsm_chain_build_alloc_init(error, &nmreq, 3513 NFSX_FH(nfsvers) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 3514 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 3515 if (nfsvers == NFS_VER3) { 3516 nfsm_chain_add_64(error, &nmreq, uio_offset(uio)); 3517 nfsm_chain_add_32(error, &nmreq, len); 3518 nfsm_chain_add_32(error, &nmreq, iomode); 3519 } else { 3520 nfsm_chain_add_32(error, &nmreq, 0); 3521 nfsm_chain_add_32(error, &nmreq, uio_offset(uio)); 3522 nfsm_chain_add_32(error, &nmreq, 0); 3523 } 3524 nfsm_chain_add_32(error, &nmreq, len); 3525 nfsmout_if(error); 3526 error = nfsm_chain_add_uio(&nmreq, uio, len); 3527 nfsm_chain_build_done(error, &nmreq); 3528 nfsmout_if(error); 3529 error = nfs_request_async(np, NULL, &nmreq, NFSPROC_WRITE, thd, cred, NULL, 0, cb, reqp); 3530nfsmout: 3531 nfsm_chain_cleanup(&nmreq); 3532 return (error); 3533} 3534 3535int 3536nfs3_write_rpc_async_finish( 3537 nfsnode_t np, 3538 struct nfsreq *req, 3539 int *iomodep, 3540 size_t *rlenp, 3541 uint64_t *wverfp) 3542{ 3543 struct nfsmount *nmp; 3544 int error = 0, lockerror = ENOENT, nfsvers, status; 3545 int updatemtime = 0, wccpostattr = 0, rlen, committed = NFS_WRITE_FILESYNC; 3546 u_int64_t xid, wverf; 3547 mount_t mp; 3548 struct nfsm_chain nmrep; 3549 3550 nmp = NFSTONMP(np); 3551 if (nfs_mount_gone(nmp)) { 3552 nfs_request_async_cancel(req); 3553 return (ENXIO); 3554 } 3555 nfsvers = nmp->nm_vers; 3556 3557 nfsm_chain_null(&nmrep); 3558 3559 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 3560 if (error == EINPROGRESS) /* async request restarted */ 3561 return (error); 3562 nmp = NFSTONMP(np); 3563 if (nfs_mount_gone(nmp)) 3564 error = ENXIO; 3565 if (!error && (lockerror = nfs_node_lock(np))) 3566 error = lockerror; 3567 if (nfsvers == NFS_VER3) { 3568 struct timespec premtime = { 0, 0 }; 3569 nfsm_chain_get_wcc_data(error, &nmrep, np, &premtime, &wccpostattr, &xid); 3570 if (nfstimespeccmp(&np->n_mtime, &premtime, ==)) 3571 updatemtime = 1; 3572 if (!error) 3573 error = status; 3574 nfsm_chain_get_32(error, &nmrep, rlen); 3575 nfsmout_if(error); 3576 *rlenp = rlen; 3577 if (rlen <= 0) 3578 error = NFSERR_IO; 3579 nfsm_chain_get_32(error, &nmrep, committed); 3580 nfsm_chain_get_64(error, &nmrep, wverf); 3581 nfsmout_if(error); 3582 if (wverfp) 3583 *wverfp = wverf; 3584 lck_mtx_lock(&nmp->nm_lock); 3585 if (!(nmp->nm_state & NFSSTA_HASWRITEVERF)) { 3586 nmp->nm_verf = wverf; 3587 nmp->nm_state |= NFSSTA_HASWRITEVERF; 3588 } else if (nmp->nm_verf != wverf) { 3589 nmp->nm_verf = wverf; 3590 } 3591 lck_mtx_unlock(&nmp->nm_lock); 3592 } else { 3593 if (!error) 3594 error = status; 3595 nfsm_chain_loadattr(error, &nmrep, np, nfsvers, &xid); 3596 nfsmout_if(error); 3597 } 3598 if (updatemtime) 3599 NFS_CHANGED_UPDATE(nfsvers, np, &np->n_vattr); 3600nfsmout: 3601 if (!lockerror) 3602 nfs_node_unlock(np); 3603 nfsm_chain_cleanup(&nmrep); 3604 if ((committed != NFS_WRITE_FILESYNC) && nfs_allow_async && 3605 ((mp = NFSTOMP(np))) && (vfs_flags(mp) & MNT_ASYNC)) 3606 committed = NFS_WRITE_FILESYNC; 3607 *iomodep = committed; 3608 return (error); 3609} 3610 3611/* 3612 * NFS mknod vnode op 3613 * 3614 * For NFS v2 this is a kludge. Use a create RPC but with the IFMT bits of the 3615 * mode set to specify the file type and the size field for rdev. 3616 */ 3617int 3618nfs3_vnop_mknod( 3619 struct vnop_mknod_args /* { 3620 struct vnodeop_desc *a_desc; 3621 vnode_t a_dvp; 3622 vnode_t *a_vpp; 3623 struct componentname *a_cnp; 3624 struct vnode_attr *a_vap; 3625 vfs_context_t a_context; 3626 } */ *ap) 3627{ 3628 vnode_t dvp = ap->a_dvp; 3629 vnode_t *vpp = ap->a_vpp; 3630 struct componentname *cnp = ap->a_cnp; 3631 struct vnode_attr *vap = ap->a_vap; 3632 vfs_context_t ctx = ap->a_context; 3633 vnode_t newvp = NULL; 3634 nfsnode_t np = NULL; 3635 struct nfsmount *nmp; 3636 nfsnode_t dnp = VTONFS(dvp); 3637 struct nfs_vattr nvattr; 3638 fhandle_t fh; 3639 int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0; 3640 struct timespec premtime = { 0, 0 }; 3641 u_int32_t rdev; 3642 u_int64_t xid = 0, dxid; 3643 int nfsvers, gotuid, gotgid; 3644 struct nfsm_chain nmreq, nmrep; 3645 struct nfsreq rq, *req = &rq; 3646 3647 nmp = VTONMP(dvp); 3648 if (nfs_mount_gone(nmp)) 3649 return (ENXIO); 3650 nfsvers = nmp->nm_vers; 3651 3652 if (!VATTR_IS_ACTIVE(vap, va_type)) 3653 return (EINVAL); 3654 if (vap->va_type == VCHR || vap->va_type == VBLK) { 3655 if (!VATTR_IS_ACTIVE(vap, va_rdev)) 3656 return (EINVAL); 3657 rdev = vap->va_rdev; 3658 } else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 3659 rdev = 0xffffffff; 3660 else { 3661 return (ENOTSUP); 3662 } 3663 if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) 3664 return (ENAMETOOLONG); 3665 3666 nfs_avoid_needless_id_setting_on_create(dnp, vap, ctx); 3667 3668 VATTR_SET_SUPPORTED(vap, va_mode); 3669 VATTR_SET_SUPPORTED(vap, va_uid); 3670 VATTR_SET_SUPPORTED(vap, va_gid); 3671 VATTR_SET_SUPPORTED(vap, va_data_size); 3672 VATTR_SET_SUPPORTED(vap, va_access_time); 3673 VATTR_SET_SUPPORTED(vap, va_modify_time); 3674 gotuid = VATTR_IS_ACTIVE(vap, va_uid); 3675 gotgid = VATTR_IS_ACTIVE(vap, va_gid); 3676 3677 nfsm_chain_null(&nmreq); 3678 nfsm_chain_null(&nmrep); 3679 3680 nfsm_chain_build_alloc_init(error, &nmreq, 3681 NFSX_FH(nfsvers) + 4 * NFSX_UNSIGNED + 3682 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(nfsvers)); 3683 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 3684 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 3685 if (nfsvers == NFS_VER3) { 3686 nfsm_chain_add_32(error, &nmreq, vtonfs_type(vap->va_type, nfsvers)); 3687 nfsm_chain_add_v3sattr(error, &nmreq, vap); 3688 if (vap->va_type == VCHR || vap->va_type == VBLK) { 3689 nfsm_chain_add_32(error, &nmreq, major(vap->va_rdev)); 3690 nfsm_chain_add_32(error, &nmreq, minor(vap->va_rdev)); 3691 } 3692 } else { 3693 nfsm_chain_add_v2sattr(error, &nmreq, vap, rdev); 3694 } 3695 nfsm_chain_build_done(error, &nmreq); 3696 if (!error) 3697 error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx)); 3698 nfsmout_if(error); 3699 3700 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_MKNOD, 3701 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req); 3702 if (!error) 3703 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 3704 3705 if ((lockerror = nfs_node_lock(dnp))) 3706 error = lockerror; 3707 /* XXX no EEXIST kludge here? */ 3708 dxid = xid; 3709 if (!error && !status) { 3710 if (dnp->n_flag & NNEGNCENTRIES) { 3711 dnp->n_flag &= ~NNEGNCENTRIES; 3712 cache_purge_negatives(dvp); 3713 } 3714 error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr); 3715 } 3716 if (nfsvers == NFS_VER3) 3717 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid); 3718 if (!error) 3719 error = status; 3720nfsmout: 3721 nfsm_chain_cleanup(&nmreq); 3722 nfsm_chain_cleanup(&nmrep); 3723 3724 if (!lockerror) { 3725 dnp->n_flag |= NMODIFIED; 3726 /* if directory hadn't changed, update namecache mtime */ 3727 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 3728 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 3729 nfs_node_unlock(dnp); 3730 /* nfs_getattr() will check changed and purge caches */ 3731 nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED); 3732 } 3733 3734 if (!error && fh.fh_len) 3735 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, &nvattr, &xid, rq.r_auth, NG_MAKEENTRY, &np); 3736 if (!error && !np) 3737 error = nfs_lookitup(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, &np); 3738 if (!error && np) 3739 newvp = NFSTOV(np); 3740 if (!busyerror) 3741 nfs_node_clear_busy(dnp); 3742 3743 if (!error && (gotuid || gotgid) && 3744 (!newvp || nfs_getattrcache(np, &nvattr, 0) || 3745 (gotuid && (nvattr.nva_uid != vap->va_uid)) || 3746 (gotgid && (nvattr.nva_gid != vap->va_gid)))) { 3747 /* clear ID bits if server didn't use them (or we can't tell) */ 3748 VATTR_CLEAR_SUPPORTED(vap, va_uid); 3749 VATTR_CLEAR_SUPPORTED(vap, va_gid); 3750 } 3751 if (error) { 3752 if (newvp) { 3753 nfs_node_unlock(np); 3754 vnode_put(newvp); 3755 } 3756 } else { 3757 *vpp = newvp; 3758 nfs_node_unlock(np); 3759 } 3760 return (error); 3761} 3762 3763static uint32_t create_verf; 3764/* 3765 * NFS file create call 3766 */ 3767int 3768nfs3_vnop_create( 3769 struct vnop_create_args /* { 3770 struct vnodeop_desc *a_desc; 3771 vnode_t a_dvp; 3772 vnode_t *a_vpp; 3773 struct componentname *a_cnp; 3774 struct vnode_attr *a_vap; 3775 vfs_context_t a_context; 3776 } */ *ap) 3777{ 3778 vfs_context_t ctx = ap->a_context; 3779 vnode_t dvp = ap->a_dvp; 3780 struct vnode_attr *vap = ap->a_vap; 3781 struct componentname *cnp = ap->a_cnp; 3782 struct nfs_vattr nvattr; 3783 fhandle_t fh; 3784 nfsnode_t np = NULL; 3785 struct nfsmount *nmp; 3786 nfsnode_t dnp = VTONFS(dvp); 3787 vnode_t newvp = NULL; 3788 int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0, fmode = 0; 3789 struct timespec premtime = { 0, 0 }; 3790 int nfsvers, gotuid, gotgid; 3791 u_int64_t xid, dxid; 3792 uint32_t val; 3793 struct nfsm_chain nmreq, nmrep; 3794 struct nfsreq rq, *req = &rq; 3795 struct nfs_dulookup dul; 3796 3797 nmp = VTONMP(dvp); 3798 if (nfs_mount_gone(nmp)) 3799 return (ENXIO); 3800 nfsvers = nmp->nm_vers; 3801 3802 if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) 3803 return (ENAMETOOLONG); 3804 3805 nfs_avoid_needless_id_setting_on_create(dnp, vap, ctx); 3806 3807 VATTR_SET_SUPPORTED(vap, va_mode); 3808 VATTR_SET_SUPPORTED(vap, va_uid); 3809 VATTR_SET_SUPPORTED(vap, va_gid); 3810 VATTR_SET_SUPPORTED(vap, va_data_size); 3811 VATTR_SET_SUPPORTED(vap, va_access_time); 3812 VATTR_SET_SUPPORTED(vap, va_modify_time); 3813 gotuid = VATTR_IS_ACTIVE(vap, va_uid); 3814 gotgid = VATTR_IS_ACTIVE(vap, va_gid); 3815 3816 if (vap->va_vaflags & VA_EXCLUSIVE) { 3817 fmode |= O_EXCL; 3818 if (!VATTR_IS_ACTIVE(vap, va_access_time) || !VATTR_IS_ACTIVE(vap, va_modify_time)) 3819 vap->va_vaflags |= VA_UTIMES_NULL; 3820 } 3821 3822again: 3823 error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx)); 3824 nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx); 3825 3826 nfsm_chain_null(&nmreq); 3827 nfsm_chain_null(&nmrep); 3828 3829 nfsm_chain_build_alloc_init(error, &nmreq, 3830 NFSX_FH(nfsvers) + 2 * NFSX_UNSIGNED + 3831 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(nfsvers)); 3832 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 3833 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 3834 if (nfsvers == NFS_VER3) { 3835 if (fmode & O_EXCL) { 3836 nfsm_chain_add_32(error, &nmreq, NFS_CREATE_EXCLUSIVE); 3837 lck_rw_lock_shared(in_ifaddr_rwlock); 3838 if (!TAILQ_EMPTY(&in_ifaddrhead)) 3839 val = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 3840 else 3841 val = create_verf; 3842 lck_rw_done(in_ifaddr_rwlock); 3843 nfsm_chain_add_32(error, &nmreq, val); 3844 ++create_verf; 3845 nfsm_chain_add_32(error, &nmreq, create_verf); 3846 } else { 3847 nfsm_chain_add_32(error, &nmreq, NFS_CREATE_UNCHECKED); 3848 nfsm_chain_add_v3sattr(error, &nmreq, vap); 3849 } 3850 } else { 3851 nfsm_chain_add_v2sattr(error, &nmreq, vap, 0); 3852 } 3853 nfsm_chain_build_done(error, &nmreq); 3854 nfsmout_if(error); 3855 3856 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_CREATE, 3857 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req); 3858 if (!error) { 3859 nfs_dulookup_start(&dul, dnp, ctx); 3860 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 3861 } 3862 3863 if ((lockerror = nfs_node_lock(dnp))) 3864 error = lockerror; 3865 dxid = xid; 3866 if (!error && !status) { 3867 if (dnp->n_flag & NNEGNCENTRIES) { 3868 dnp->n_flag &= ~NNEGNCENTRIES; 3869 cache_purge_negatives(dvp); 3870 } 3871 error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr); 3872 } 3873 if (nfsvers == NFS_VER3) 3874 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid); 3875 if (!error) 3876 error = status; 3877nfsmout: 3878 nfsm_chain_cleanup(&nmreq); 3879 nfsm_chain_cleanup(&nmrep); 3880 3881 if (!lockerror) { 3882 dnp->n_flag |= NMODIFIED; 3883 /* if directory hadn't changed, update namecache mtime */ 3884 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 3885 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 3886 nfs_node_unlock(dnp); 3887 /* nfs_getattr() will check changed and purge caches */ 3888 nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED); 3889 } 3890 3891 if (!error && fh.fh_len) 3892 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, &nvattr, &xid, rq.r_auth, NG_MAKEENTRY, &np); 3893 if (!error && !np) 3894 error = nfs_lookitup(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, &np); 3895 if (!error && np) 3896 newvp = NFSTOV(np); 3897 3898 nfs_dulookup_finish(&dul, dnp, ctx); 3899 if (!busyerror) 3900 nfs_node_clear_busy(dnp); 3901 3902 if (error) { 3903 if ((nfsvers == NFS_VER3) && (fmode & O_EXCL) && (error == NFSERR_NOTSUPP)) { 3904 fmode &= ~O_EXCL; 3905 goto again; 3906 } 3907 if (newvp) { 3908 nfs_node_unlock(np); 3909 vnode_put(newvp); 3910 } 3911 } else if ((nfsvers == NFS_VER3) && (fmode & O_EXCL)) { 3912 nfs_node_unlock(np); 3913 error = nfs3_setattr_rpc(np, vap, ctx); 3914 if (error && (gotuid || gotgid)) { 3915 /* it's possible the server didn't like our attempt to set IDs. */ 3916 /* so, let's try it again without those */ 3917 VATTR_CLEAR_ACTIVE(vap, va_uid); 3918 VATTR_CLEAR_ACTIVE(vap, va_gid); 3919 error = nfs3_setattr_rpc(np, vap, ctx); 3920 } 3921 if (error) 3922 vnode_put(newvp); 3923 else 3924 nfs_node_lock_force(np); 3925 } 3926 if (!error) 3927 *ap->a_vpp = newvp; 3928 if (!error && (gotuid || gotgid) && 3929 (!newvp || nfs_getattrcache(np, &nvattr, 0) || 3930 (gotuid && (nvattr.nva_uid != vap->va_uid)) || 3931 (gotgid && (nvattr.nva_gid != vap->va_gid)))) { 3932 /* clear ID bits if server didn't use them (or we can't tell) */ 3933 VATTR_CLEAR_SUPPORTED(vap, va_uid); 3934 VATTR_CLEAR_SUPPORTED(vap, va_gid); 3935 } 3936 if (!error) 3937 nfs_node_unlock(np); 3938 return (error); 3939} 3940 3941/* 3942 * NFS file remove call 3943 * To try and make NFS semantics closer to UFS semantics, a file that has 3944 * other processes using the vnode is renamed instead of removed and then 3945 * removed later on the last close. 3946 * - If vnode_isinuse() 3947 * If a rename is not already in the works 3948 * call nfs_sillyrename() to set it up 3949 * else 3950 * do the remove RPC 3951 */ 3952int 3953nfs_vnop_remove( 3954 struct vnop_remove_args /* { 3955 struct vnodeop_desc *a_desc; 3956 vnode_t a_dvp; 3957 vnode_t a_vp; 3958 struct componentname *a_cnp; 3959 int a_flags; 3960 vfs_context_t a_context; 3961 } */ *ap) 3962{ 3963 vfs_context_t ctx = ap->a_context; 3964 vnode_t vp = ap->a_vp; 3965 vnode_t dvp = ap->a_dvp; 3966 struct componentname *cnp = ap->a_cnp; 3967 nfsnode_t dnp = VTONFS(dvp); 3968 nfsnode_t np = VTONFS(vp); 3969 int error = 0, nfsvers, namedattrs, inuse, gotattr = 0, flushed = 0, setsize = 0; 3970 struct nfs_vattr nvattr; 3971 struct nfsmount *nmp; 3972 struct nfs_dulookup dul; 3973 3974 /* XXX prevent removing a sillyrenamed file? */ 3975 3976 nmp = NFSTONMP(dnp); 3977 if (nfs_mount_gone(nmp)) 3978 return (ENXIO); 3979 nfsvers = nmp->nm_vers; 3980 namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR); 3981 3982again_relock: 3983 error = nfs_node_set_busy2(dnp, np, vfs_context_thread(ctx)); 3984 if (error) 3985 return (error); 3986 3987 /* lock the node while we remove the file */ 3988 lck_mtx_lock(nfs_node_hash_mutex); 3989 while (np->n_hflag & NHLOCKED) { 3990 np->n_hflag |= NHLOCKWANT; 3991 msleep(np, nfs_node_hash_mutex, PINOD, "nfs_remove", NULL); 3992 } 3993 np->n_hflag |= NHLOCKED; 3994 lck_mtx_unlock(nfs_node_hash_mutex); 3995 3996 if (!namedattrs) 3997 nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx); 3998again: 3999 inuse = vnode_isinuse(vp, 0); 4000 if ((ap->a_flags & VNODE_REMOVE_NODELETEBUSY) && inuse) { 4001 /* Caller requested Carbon delete semantics, but file is busy */ 4002 error = EBUSY; 4003 goto out; 4004 } 4005 if (inuse && !gotattr) { 4006 if (nfs_getattr(np, &nvattr, ctx, NGA_CACHED)) 4007 nvattr.nva_nlink = 1; 4008 gotattr = 1; 4009 goto again; 4010 } 4011 if (!inuse || (np->n_sillyrename && (nvattr.nva_nlink > 1))) { 4012 4013 if (!inuse && !flushed) { /* flush all the buffers first */ 4014 /* unlock the node */ 4015 lck_mtx_lock(nfs_node_hash_mutex); 4016 np->n_hflag &= ~NHLOCKED; 4017 if (np->n_hflag & NHLOCKWANT) { 4018 np->n_hflag &= ~NHLOCKWANT; 4019 wakeup(np); 4020 } 4021 lck_mtx_unlock(nfs_node_hash_mutex); 4022 nfs_node_clear_busy2(dnp, np); 4023 error = nfs_vinvalbuf(vp, V_SAVE, ctx, 1); 4024 FSDBG(260, np, np->n_size, np->n_vattr.nva_size, 0xf00d0011); 4025 flushed = 1; 4026 if (error == EINTR) { 4027 nfs_node_lock_force(np); 4028 NATTRINVALIDATE(np); 4029 nfs_node_unlock(np); 4030 return (error); 4031 } 4032 if (!namedattrs) 4033 nfs_dulookup_finish(&dul, dnp, ctx); 4034 goto again_relock; 4035 } 4036 4037 if ((nmp->nm_vers >= NFS_VER4) && (np->n_openflags & N_DELEG_MASK)) 4038 nfs4_delegation_return(np, 0, vfs_context_thread(ctx), vfs_context_ucred(ctx)); 4039 4040 /* 4041 * Purge the name cache so that the chance of a lookup for 4042 * the name succeeding while the remove is in progress is 4043 * minimized. 4044 */ 4045 nfs_name_cache_purge(dnp, np, cnp, ctx); 4046 4047 if (!namedattrs) 4048 nfs_dulookup_start(&dul, dnp, ctx); 4049 4050 /* Do the rpc */ 4051 error = nmp->nm_funcs->nf_remove_rpc(dnp, cnp->cn_nameptr, cnp->cn_namelen, 4052 vfs_context_thread(ctx), vfs_context_ucred(ctx)); 4053 4054 /* 4055 * Kludge City: If the first reply to the remove rpc is lost.. 4056 * the reply to the retransmitted request will be ENOENT 4057 * since the file was in fact removed 4058 * Therefore, we cheat and return success. 4059 */ 4060 if (error == ENOENT) 4061 error = 0; 4062 4063 if (!error && !inuse && !np->n_sillyrename) { 4064 /* 4065 * removal succeeded, it's not in use, and not silly renamed so 4066 * remove nfsnode from hash now so we can't accidentally find it 4067 * again if another object gets created with the same filehandle 4068 * before this vnode gets reclaimed 4069 */ 4070 lck_mtx_lock(nfs_node_hash_mutex); 4071 if (np->n_hflag & NHHASHED) { 4072 LIST_REMOVE(np, n_hash); 4073 np->n_hflag &= ~NHHASHED; 4074 FSDBG(266, 0, np, np->n_flag, 0xb1eb1e); 4075 } 4076 lck_mtx_unlock(nfs_node_hash_mutex); 4077 /* clear flags now: won't get nfs_vnop_inactive for recycled vnode */ 4078 /* clear all flags other than these */ 4079 nfs_node_lock_force(np); 4080 np->n_flag &= (NMODIFIED); 4081 NATTRINVALIDATE(np); 4082 nfs_node_unlock(np); 4083 vnode_recycle(vp); 4084 setsize = 1; 4085 } else { 4086 nfs_node_lock_force(np); 4087 NATTRINVALIDATE(np); 4088 nfs_node_unlock(np); 4089 } 4090 } else if (!np->n_sillyrename) { 4091 if (!namedattrs) 4092 nfs_dulookup_start(&dul, dnp, ctx); 4093 error = nfs_sillyrename(dnp, np, cnp, ctx); 4094 nfs_node_lock_force(np); 4095 NATTRINVALIDATE(np); 4096 nfs_node_unlock(np); 4097 } else { 4098 nfs_node_lock_force(np); 4099 NATTRINVALIDATE(np); 4100 nfs_node_unlock(np); 4101 if (!namedattrs) 4102 nfs_dulookup_start(&dul, dnp, ctx); 4103 } 4104 4105 /* nfs_getattr() will check changed and purge caches */ 4106 nfs_getattr(dnp, NULL, ctx, NGA_CACHED); 4107 if (!namedattrs) 4108 nfs_dulookup_finish(&dul, dnp, ctx); 4109out: 4110 /* unlock the node */ 4111 lck_mtx_lock(nfs_node_hash_mutex); 4112 np->n_hflag &= ~NHLOCKED; 4113 if (np->n_hflag & NHLOCKWANT) { 4114 np->n_hflag &= ~NHLOCKWANT; 4115 wakeup(np); 4116 } 4117 lck_mtx_unlock(nfs_node_hash_mutex); 4118 nfs_node_clear_busy2(dnp, np); 4119 if (setsize) 4120 ubc_setsize(vp, 0); 4121 return (error); 4122} 4123 4124/* 4125 * NFS silly-renamed file removal function called from nfs_vnop_inactive 4126 */ 4127int 4128nfs_removeit(struct nfs_sillyrename *nsp) 4129{ 4130 struct nfsmount *nmp = NFSTONMP(nsp->nsr_dnp); 4131 if (nfs_mount_gone(nmp)) 4132 return (ENXIO); 4133 return nmp->nm_funcs->nf_remove_rpc(nsp->nsr_dnp, nsp->nsr_name, nsp->nsr_namlen, NULL, nsp->nsr_cred); 4134} 4135 4136/* 4137 * NFS remove rpc, called from nfs_remove() and nfs_removeit(). 4138 */ 4139int 4140nfs3_remove_rpc( 4141 nfsnode_t dnp, 4142 char *name, 4143 int namelen, 4144 thread_t thd, 4145 kauth_cred_t cred) 4146{ 4147 int error = 0, lockerror = ENOENT, status, wccpostattr = 0; 4148 struct timespec premtime = { 0, 0 }; 4149 struct nfsmount *nmp; 4150 int nfsvers; 4151 u_int64_t xid; 4152 struct nfsm_chain nmreq, nmrep; 4153 4154 nmp = NFSTONMP(dnp); 4155 if (nfs_mount_gone(nmp)) 4156 return (ENXIO); 4157 nfsvers = nmp->nm_vers; 4158 if ((nfsvers == NFS_VER2) && (namelen > NFS_MAXNAMLEN)) 4159 return (ENAMETOOLONG); 4160 4161 nfsm_chain_null(&nmreq); 4162 nfsm_chain_null(&nmrep); 4163 4164 nfsm_chain_build_alloc_init(error, &nmreq, 4165 NFSX_FH(nfsvers) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 4166 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 4167 nfsm_chain_add_name(error, &nmreq, name, namelen, nmp); 4168 nfsm_chain_build_done(error, &nmreq); 4169 nfsmout_if(error); 4170 4171 error = nfs_request2(dnp, NULL, &nmreq, NFSPROC_REMOVE, thd, cred, NULL, 0, &nmrep, &xid, &status); 4172 4173 if ((lockerror = nfs_node_lock(dnp))) 4174 error = lockerror; 4175 if (nfsvers == NFS_VER3) 4176 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &xid); 4177 nfsmout_if(error); 4178 dnp->n_flag |= NMODIFIED; 4179 /* if directory hadn't changed, update namecache mtime */ 4180 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 4181 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 4182 if (!wccpostattr) 4183 NATTRINVALIDATE(dnp); 4184 if (!error) 4185 error = status; 4186nfsmout: 4187 if (!lockerror) 4188 nfs_node_unlock(dnp); 4189 nfsm_chain_cleanup(&nmreq); 4190 nfsm_chain_cleanup(&nmrep); 4191 return (error); 4192} 4193 4194/* 4195 * NFS file rename call 4196 */ 4197int 4198nfs_vnop_rename( 4199 struct vnop_rename_args /* { 4200 struct vnodeop_desc *a_desc; 4201 vnode_t a_fdvp; 4202 vnode_t a_fvp; 4203 struct componentname *a_fcnp; 4204 vnode_t a_tdvp; 4205 vnode_t a_tvp; 4206 struct componentname *a_tcnp; 4207 vfs_context_t a_context; 4208 } */ *ap) 4209{ 4210 vfs_context_t ctx = ap->a_context; 4211 vnode_t fdvp = ap->a_fdvp; 4212 vnode_t fvp = ap->a_fvp; 4213 vnode_t tdvp = ap->a_tdvp; 4214 vnode_t tvp = ap->a_tvp; 4215 nfsnode_t fdnp, fnp, tdnp, tnp; 4216 struct componentname *tcnp = ap->a_tcnp; 4217 struct componentname *fcnp = ap->a_fcnp; 4218 int error, nfsvers, inuse=0, tvprecycle=0, locked=0; 4219 mount_t fmp, tdmp, tmp; 4220 struct nfs_vattr nvattr; 4221 struct nfsmount *nmp; 4222 4223 fdnp = VTONFS(fdvp); 4224 fnp = VTONFS(fvp); 4225 tdnp = VTONFS(tdvp); 4226 tnp = tvp ? VTONFS(tvp) : NULL; 4227 4228 nmp = NFSTONMP(fdnp); 4229 if (nfs_mount_gone(nmp)) 4230 return (ENXIO); 4231 nfsvers = nmp->nm_vers; 4232 4233 error = nfs_node_set_busy4(fdnp, fnp, tdnp, tnp, vfs_context_thread(ctx)); 4234 if (error) 4235 return (error); 4236 4237 if (tvp && (tvp != fvp)) { 4238 /* lock the node while we rename over the existing file */ 4239 lck_mtx_lock(nfs_node_hash_mutex); 4240 while (tnp->n_hflag & NHLOCKED) { 4241 tnp->n_hflag |= NHLOCKWANT; 4242 msleep(tnp, nfs_node_hash_mutex, PINOD, "nfs_rename", NULL); 4243 } 4244 tnp->n_hflag |= NHLOCKED; 4245 lck_mtx_unlock(nfs_node_hash_mutex); 4246 locked = 1; 4247 } 4248 4249 /* Check for cross-device rename */ 4250 fmp = vnode_mount(fvp); 4251 tmp = tvp ? vnode_mount(tvp) : NULL; 4252 tdmp = vnode_mount(tdvp); 4253 if ((fmp != tdmp) || (tvp && (fmp != tmp))) { 4254 error = EXDEV; 4255 goto out; 4256 } 4257 4258 /* XXX prevent renaming from/over a sillyrenamed file? */ 4259 4260 /* 4261 * If the tvp exists and is in use, sillyrename it before doing the 4262 * rename of the new file over it. 4263 * XXX Can't sillyrename a directory. 4264 * Don't sillyrename if source and target are same vnode (hard 4265 * links or case-variants) 4266 */ 4267 if (tvp && (tvp != fvp)) 4268 inuse = vnode_isinuse(tvp, 0); 4269 if (inuse && !tnp->n_sillyrename && (vnode_vtype(tvp) != VDIR)) { 4270 error = nfs_sillyrename(tdnp, tnp, tcnp, ctx); 4271 if (error) { 4272 /* sillyrename failed. Instead of pressing on, return error */ 4273 goto out; /* should not be ENOENT. */ 4274 } else { 4275 /* sillyrename succeeded.*/ 4276 tvp = NULL; 4277 } 4278 } else if (tvp && (nmp->nm_vers >= NFS_VER4) && (tnp->n_openflags & N_DELEG_MASK)) { 4279 nfs4_delegation_return(tnp, 0, vfs_context_thread(ctx), vfs_context_ucred(ctx)); 4280 } 4281 4282 error = nmp->nm_funcs->nf_rename_rpc(fdnp, fcnp->cn_nameptr, fcnp->cn_namelen, 4283 tdnp, tcnp->cn_nameptr, tcnp->cn_namelen, ctx); 4284 4285 /* 4286 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 4287 */ 4288 if (error == ENOENT) 4289 error = 0; 4290 4291 if (tvp && (tvp != fvp) && !tnp->n_sillyrename) { 4292 nfs_node_lock_force(tnp); 4293 tvprecycle = (!error && !vnode_isinuse(tvp, 0) && 4294 (nfs_getattrcache(tnp, &nvattr, 0) || (nvattr.nva_nlink == 1))); 4295 nfs_node_unlock(tnp); 4296 lck_mtx_lock(nfs_node_hash_mutex); 4297 if (tvprecycle && (tnp->n_hflag & NHHASHED)) { 4298 /* 4299 * remove nfsnode from hash now so we can't accidentally find it 4300 * again if another object gets created with the same filehandle 4301 * before this vnode gets reclaimed 4302 */ 4303 LIST_REMOVE(tnp, n_hash); 4304 tnp->n_hflag &= ~NHHASHED; 4305 FSDBG(266, 0, tnp, tnp->n_flag, 0xb1eb1e); 4306 } 4307 lck_mtx_unlock(nfs_node_hash_mutex); 4308 } 4309 4310 /* purge the old name cache entries and enter the new one */ 4311 nfs_name_cache_purge(fdnp, fnp, fcnp, ctx); 4312 if (tvp) { 4313 nfs_name_cache_purge(tdnp, tnp, tcnp, ctx); 4314 if (tvprecycle) { 4315 /* clear flags now: won't get nfs_vnop_inactive for recycled vnode */ 4316 /* clear all flags other than these */ 4317 nfs_node_lock_force(tnp); 4318 tnp->n_flag &= (NMODIFIED); 4319 nfs_node_unlock(tnp); 4320 vnode_recycle(tvp); 4321 } 4322 } 4323 if (!error) { 4324 nfs_node_lock_force(tdnp); 4325 if (tdnp->n_flag & NNEGNCENTRIES) { 4326 tdnp->n_flag &= ~NNEGNCENTRIES; 4327 cache_purge_negatives(tdvp); 4328 } 4329 nfs_node_unlock(tdnp); 4330 nfs_node_lock_force(fnp); 4331 cache_enter(tdvp, fvp, tcnp); 4332 if (tdvp != fdvp) { /* update parent pointer */ 4333 if (fnp->n_parent && !vnode_get(fnp->n_parent)) { 4334 /* remove ref from old parent */ 4335 vnode_rele(fnp->n_parent); 4336 vnode_put(fnp->n_parent); 4337 } 4338 fnp->n_parent = tdvp; 4339 if (tdvp && !vnode_get(tdvp)) { 4340 /* add ref to new parent */ 4341 vnode_ref(tdvp); 4342 vnode_put(tdvp); 4343 } else { 4344 fnp->n_parent = NULL; 4345 } 4346 } 4347 nfs_node_unlock(fnp); 4348 } 4349out: 4350 /* nfs_getattr() will check changed and purge caches */ 4351 nfs_getattr(fdnp, NULL, ctx, NGA_CACHED); 4352 nfs_getattr(tdnp, NULL, ctx, NGA_CACHED); 4353 if (locked) { 4354 /* unlock node */ 4355 lck_mtx_lock(nfs_node_hash_mutex); 4356 tnp->n_hflag &= ~NHLOCKED; 4357 if (tnp->n_hflag & NHLOCKWANT) { 4358 tnp->n_hflag &= ~NHLOCKWANT; 4359 wakeup(tnp); 4360 } 4361 lck_mtx_unlock(nfs_node_hash_mutex); 4362 } 4363 nfs_node_clear_busy4(fdnp, fnp, tdnp, tnp); 4364 return (error); 4365} 4366 4367/* 4368 * Do an NFS rename rpc. Called from nfs_vnop_rename() and nfs_sillyrename(). 4369 */ 4370int 4371nfs3_rename_rpc( 4372 nfsnode_t fdnp, 4373 char *fnameptr, 4374 int fnamelen, 4375 nfsnode_t tdnp, 4376 char *tnameptr, 4377 int tnamelen, 4378 vfs_context_t ctx) 4379{ 4380 int error = 0, lockerror = ENOENT, status, fwccpostattr = 0, twccpostattr = 0; 4381 struct timespec fpremtime = { 0, 0 }, tpremtime = { 0, 0 }; 4382 struct nfsmount *nmp; 4383 int nfsvers; 4384 u_int64_t xid, txid; 4385 struct nfsm_chain nmreq, nmrep; 4386 4387 nmp = NFSTONMP(fdnp); 4388 if (nfs_mount_gone(nmp)) 4389 return (ENXIO); 4390 nfsvers = nmp->nm_vers; 4391 if ((nfsvers == NFS_VER2) && 4392 ((fnamelen > NFS_MAXNAMLEN) || (tnamelen > NFS_MAXNAMLEN))) 4393 return (ENAMETOOLONG); 4394 4395 nfsm_chain_null(&nmreq); 4396 nfsm_chain_null(&nmrep); 4397 4398 nfsm_chain_build_alloc_init(error, &nmreq, 4399 (NFSX_FH(nfsvers) + NFSX_UNSIGNED) * 2 + 4400 nfsm_rndup(fnamelen) + nfsm_rndup(tnamelen)); 4401 nfsm_chain_add_fh(error, &nmreq, nfsvers, fdnp->n_fhp, fdnp->n_fhsize); 4402 nfsm_chain_add_name(error, &nmreq, fnameptr, fnamelen, nmp); 4403 nfsm_chain_add_fh(error, &nmreq, nfsvers, tdnp->n_fhp, tdnp->n_fhsize); 4404 nfsm_chain_add_name(error, &nmreq, tnameptr, tnamelen, nmp); 4405 nfsm_chain_build_done(error, &nmreq); 4406 nfsmout_if(error); 4407 4408 error = nfs_request(fdnp, NULL, &nmreq, NFSPROC_RENAME, ctx, NULL, &nmrep, &xid, &status); 4409 4410 if ((lockerror = nfs_node_lock2(fdnp, tdnp))) 4411 error = lockerror; 4412 if (nfsvers == NFS_VER3) { 4413 txid = xid; 4414 nfsm_chain_get_wcc_data(error, &nmrep, fdnp, &fpremtime, &fwccpostattr, &xid); 4415 nfsm_chain_get_wcc_data(error, &nmrep, tdnp, &tpremtime, &twccpostattr, &txid); 4416 } 4417 if (!error) 4418 error = status; 4419nfsmout: 4420 nfsm_chain_cleanup(&nmreq); 4421 nfsm_chain_cleanup(&nmrep); 4422 if (!lockerror) { 4423 fdnp->n_flag |= NMODIFIED; 4424 /* if directory hadn't changed, update namecache mtime */ 4425 if (nfstimespeccmp(&fdnp->n_ncmtime, &fpremtime, ==)) 4426 NFS_CHANGED_UPDATE_NC(nfsvers, fdnp, &fdnp->n_vattr); 4427 if (!fwccpostattr) 4428 NATTRINVALIDATE(fdnp); 4429 tdnp->n_flag |= NMODIFIED; 4430 /* if directory hadn't changed, update namecache mtime */ 4431 if (nfstimespeccmp(&tdnp->n_ncmtime, &tpremtime, ==)) 4432 NFS_CHANGED_UPDATE_NC(nfsvers, tdnp, &tdnp->n_vattr); 4433 if (!twccpostattr) 4434 NATTRINVALIDATE(tdnp); 4435 nfs_node_unlock2(fdnp, tdnp); 4436 } 4437 return (error); 4438} 4439 4440/* 4441 * NFS hard link create call 4442 */ 4443int 4444nfs3_vnop_link( 4445 struct vnop_link_args /* { 4446 struct vnodeop_desc *a_desc; 4447 vnode_t a_vp; 4448 vnode_t a_tdvp; 4449 struct componentname *a_cnp; 4450 vfs_context_t a_context; 4451 } */ *ap) 4452{ 4453 vfs_context_t ctx = ap->a_context; 4454 vnode_t vp = ap->a_vp; 4455 vnode_t tdvp = ap->a_tdvp; 4456 struct componentname *cnp = ap->a_cnp; 4457 int error = 0, lockerror = ENOENT, status, wccpostattr = 0, attrflag = 0; 4458 struct timespec premtime = { 0, 0 }; 4459 struct nfsmount *nmp; 4460 nfsnode_t np = VTONFS(vp); 4461 nfsnode_t tdnp = VTONFS(tdvp); 4462 int nfsvers; 4463 u_int64_t xid, txid; 4464 struct nfsm_chain nmreq, nmrep; 4465 4466 if (vnode_mount(vp) != vnode_mount(tdvp)) 4467 return (EXDEV); 4468 4469 nmp = VTONMP(vp); 4470 if (nfs_mount_gone(nmp)) 4471 return (ENXIO); 4472 nfsvers = nmp->nm_vers; 4473 if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) 4474 return (ENAMETOOLONG); 4475 4476 /* 4477 * Push all writes to the server, so that the attribute cache 4478 * doesn't get "out of sync" with the server. 4479 * XXX There should be a better way! 4480 */ 4481 nfs_flush(np, MNT_WAIT, vfs_context_thread(ctx), V_IGNORE_WRITEERR); 4482 4483 error = nfs_node_set_busy2(tdnp, np, vfs_context_thread(ctx)); 4484 if (error) 4485 return (error); 4486 4487 nfsm_chain_null(&nmreq); 4488 nfsm_chain_null(&nmrep); 4489 4490 nfsm_chain_build_alloc_init(error, &nmreq, 4491 NFSX_FH(nfsvers)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 4492 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 4493 nfsm_chain_add_fh(error, &nmreq, nfsvers, tdnp->n_fhp, tdnp->n_fhsize); 4494 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 4495 nfsm_chain_build_done(error, &nmreq); 4496 nfsmout_if(error); 4497 error = nfs_request(np, NULL, &nmreq, NFSPROC_LINK, ctx, NULL, &nmrep, &xid, &status); 4498 4499 if ((lockerror = nfs_node_lock2(tdnp, np))) { 4500 error = lockerror; 4501 goto nfsmout; 4502 } 4503 if (nfsvers == NFS_VER3) { 4504 txid = xid; 4505 nfsm_chain_postop_attr_update_flag(error, &nmrep, np, attrflag, &xid); 4506 nfsm_chain_get_wcc_data(error, &nmrep, tdnp, &premtime, &wccpostattr, &txid); 4507 } 4508 if (!error) 4509 error = status; 4510nfsmout: 4511 nfsm_chain_cleanup(&nmreq); 4512 nfsm_chain_cleanup(&nmrep); 4513 if (!lockerror) { 4514 if (!attrflag) 4515 NATTRINVALIDATE(np); 4516 tdnp->n_flag |= NMODIFIED; 4517 /* if directory hadn't changed, update namecache mtime */ 4518 if (nfstimespeccmp(&tdnp->n_ncmtime, &premtime, ==)) 4519 NFS_CHANGED_UPDATE_NC(nfsvers, tdnp, &tdnp->n_vattr); 4520 if (!wccpostattr) 4521 NATTRINVALIDATE(tdnp); 4522 if (!error && (tdnp->n_flag & NNEGNCENTRIES)) { 4523 tdnp->n_flag &= ~NNEGNCENTRIES; 4524 cache_purge_negatives(tdvp); 4525 } 4526 nfs_node_unlock2(tdnp, np); 4527 } 4528 nfs_node_clear_busy2(tdnp, np); 4529 /* 4530 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 4531 */ 4532 if (error == EEXIST) 4533 error = 0; 4534 return (error); 4535} 4536 4537/* 4538 * NFS symbolic link create call 4539 */ 4540int 4541nfs3_vnop_symlink( 4542 struct vnop_symlink_args /* { 4543 struct vnodeop_desc *a_desc; 4544 vnode_t a_dvp; 4545 vnode_t *a_vpp; 4546 struct componentname *a_cnp; 4547 struct vnode_attr *a_vap; 4548 char *a_target; 4549 vfs_context_t a_context; 4550 } */ *ap) 4551{ 4552 vfs_context_t ctx = ap->a_context; 4553 vnode_t dvp = ap->a_dvp; 4554 struct vnode_attr *vap = ap->a_vap; 4555 struct componentname *cnp = ap->a_cnp; 4556 struct nfs_vattr nvattr; 4557 fhandle_t fh; 4558 int slen, error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0; 4559 struct timespec premtime = { 0, 0 }; 4560 vnode_t newvp = NULL; 4561 int nfsvers, gotuid, gotgid; 4562 u_int64_t xid = 0, dxid; 4563 nfsnode_t np = NULL; 4564 nfsnode_t dnp = VTONFS(dvp); 4565 struct nfsmount *nmp; 4566 struct nfsm_chain nmreq, nmrep; 4567 struct nfsreq rq, *req = &rq; 4568 struct nfs_dulookup dul; 4569 4570 nmp = VTONMP(dvp); 4571 if (nfs_mount_gone(nmp)) 4572 return (ENXIO); 4573 nfsvers = nmp->nm_vers; 4574 4575 slen = strlen(ap->a_target); 4576 if ((nfsvers == NFS_VER2) && 4577 ((cnp->cn_namelen > NFS_MAXNAMLEN) || (slen > NFS_MAXPATHLEN))) 4578 return (ENAMETOOLONG); 4579 4580 nfs_avoid_needless_id_setting_on_create(dnp, vap, ctx); 4581 4582 VATTR_SET_SUPPORTED(vap, va_mode); 4583 VATTR_SET_SUPPORTED(vap, va_uid); 4584 VATTR_SET_SUPPORTED(vap, va_gid); 4585 VATTR_SET_SUPPORTED(vap, va_data_size); 4586 VATTR_SET_SUPPORTED(vap, va_access_time); 4587 VATTR_SET_SUPPORTED(vap, va_modify_time); 4588 gotuid = VATTR_IS_ACTIVE(vap, va_uid); 4589 gotgid = VATTR_IS_ACTIVE(vap, va_gid); 4590 4591 error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx)); 4592 nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx); 4593 4594 nfsm_chain_null(&nmreq); 4595 nfsm_chain_null(&nmrep); 4596 4597 nfsm_chain_build_alloc_init(error, &nmreq, 4598 NFSX_FH(nfsvers) + 2 * NFSX_UNSIGNED + 4599 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(nfsvers)); 4600 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 4601 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 4602 if (nfsvers == NFS_VER3) 4603 nfsm_chain_add_v3sattr(error, &nmreq, vap); 4604 nfsm_chain_add_name(error, &nmreq, ap->a_target, slen, nmp); 4605 if (nfsvers == NFS_VER2) 4606 nfsm_chain_add_v2sattr(error, &nmreq, vap, -1); 4607 nfsm_chain_build_done(error, &nmreq); 4608 nfsmout_if(error); 4609 4610 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_SYMLINK, 4611 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req); 4612 if (!error) { 4613 nfs_dulookup_start(&dul, dnp, ctx); 4614 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 4615 } 4616 4617 if ((lockerror = nfs_node_lock(dnp))) 4618 error = lockerror; 4619 dxid = xid; 4620 if (!error && !status) { 4621 if (dnp->n_flag & NNEGNCENTRIES) { 4622 dnp->n_flag &= ~NNEGNCENTRIES; 4623 cache_purge_negatives(dvp); 4624 } 4625 if (nfsvers == NFS_VER3) 4626 error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr); 4627 else 4628 fh.fh_len = 0; 4629 } 4630 if (nfsvers == NFS_VER3) 4631 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid); 4632 if (!error) 4633 error = status; 4634nfsmout: 4635 nfsm_chain_cleanup(&nmreq); 4636 nfsm_chain_cleanup(&nmrep); 4637 4638 if (!lockerror) { 4639 dnp->n_flag |= NMODIFIED; 4640 /* if directory hadn't changed, update namecache mtime */ 4641 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 4642 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 4643 nfs_node_unlock(dnp); 4644 /* nfs_getattr() will check changed and purge caches */ 4645 nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED); 4646 } 4647 4648 if (!error && fh.fh_len) 4649 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, &nvattr, &xid, rq.r_auth, NG_MAKEENTRY, &np); 4650 if (!error && np) 4651 newvp = NFSTOV(np); 4652 4653 nfs_dulookup_finish(&dul, dnp, ctx); 4654 4655 /* 4656 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 4657 * if we can succeed in looking up the symlink. 4658 */ 4659 if ((error == EEXIST) || (!error && !newvp)) { 4660 if (newvp) { 4661 nfs_node_unlock(np); 4662 vnode_put(newvp); 4663 newvp = NULL; 4664 } 4665 error = nfs_lookitup(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, &np); 4666 if (!error) { 4667 newvp = NFSTOV(np); 4668 if (vnode_vtype(newvp) != VLNK) 4669 error = EEXIST; 4670 } 4671 } 4672 if (!busyerror) 4673 nfs_node_clear_busy(dnp); 4674 if (!error && (gotuid || gotgid) && 4675 (!newvp || nfs_getattrcache(np, &nvattr, 0) || 4676 (gotuid && (nvattr.nva_uid != vap->va_uid)) || 4677 (gotgid && (nvattr.nva_gid != vap->va_gid)))) { 4678 /* clear ID bits if server didn't use them (or we can't tell) */ 4679 VATTR_CLEAR_SUPPORTED(vap, va_uid); 4680 VATTR_CLEAR_SUPPORTED(vap, va_gid); 4681 } 4682 if (error) { 4683 if (newvp) { 4684 nfs_node_unlock(np); 4685 vnode_put(newvp); 4686 } 4687 } else { 4688 nfs_node_unlock(np); 4689 *ap->a_vpp = newvp; 4690 } 4691 return (error); 4692} 4693 4694/* 4695 * NFS make dir call 4696 */ 4697int 4698nfs3_vnop_mkdir( 4699 struct vnop_mkdir_args /* { 4700 struct vnodeop_desc *a_desc; 4701 vnode_t a_dvp; 4702 vnode_t *a_vpp; 4703 struct componentname *a_cnp; 4704 struct vnode_attr *a_vap; 4705 vfs_context_t a_context; 4706 } */ *ap) 4707{ 4708 vfs_context_t ctx = ap->a_context; 4709 vnode_t dvp = ap->a_dvp; 4710 struct vnode_attr *vap = ap->a_vap; 4711 struct componentname *cnp = ap->a_cnp; 4712 struct nfs_vattr nvattr; 4713 nfsnode_t np = NULL; 4714 struct nfsmount *nmp; 4715 nfsnode_t dnp = VTONFS(dvp); 4716 vnode_t newvp = NULL; 4717 int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0; 4718 struct timespec premtime = { 0, 0 }; 4719 int nfsvers, gotuid, gotgid; 4720 u_int64_t xid= 0, dxid; 4721 fhandle_t fh; 4722 struct nfsm_chain nmreq, nmrep; 4723 struct nfsreq rq, *req = &rq; 4724 struct nfs_dulookup dul; 4725 4726 nmp = VTONMP(dvp); 4727 if (nfs_mount_gone(nmp)) 4728 return (ENXIO); 4729 nfsvers = nmp->nm_vers; 4730 if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) 4731 return (ENAMETOOLONG); 4732 4733 nfs_avoid_needless_id_setting_on_create(dnp, vap, ctx); 4734 4735 VATTR_SET_SUPPORTED(vap, va_mode); 4736 VATTR_SET_SUPPORTED(vap, va_uid); 4737 VATTR_SET_SUPPORTED(vap, va_gid); 4738 VATTR_SET_SUPPORTED(vap, va_data_size); 4739 VATTR_SET_SUPPORTED(vap, va_access_time); 4740 VATTR_SET_SUPPORTED(vap, va_modify_time); 4741 gotuid = VATTR_IS_ACTIVE(vap, va_uid); 4742 gotgid = VATTR_IS_ACTIVE(vap, va_gid); 4743 4744 error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx)); 4745 nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx); 4746 4747 nfsm_chain_null(&nmreq); 4748 nfsm_chain_null(&nmrep); 4749 4750 nfsm_chain_build_alloc_init(error, &nmreq, 4751 NFSX_FH(nfsvers) + NFSX_UNSIGNED + 4752 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(nfsvers)); 4753 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 4754 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 4755 if (nfsvers == NFS_VER3) 4756 nfsm_chain_add_v3sattr(error, &nmreq, vap); 4757 else 4758 nfsm_chain_add_v2sattr(error, &nmreq, vap, -1); 4759 nfsm_chain_build_done(error, &nmreq); 4760 nfsmout_if(error); 4761 4762 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_MKDIR, 4763 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req); 4764 if (!error) { 4765 nfs_dulookup_start(&dul, dnp, ctx); 4766 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 4767 } 4768 4769 if ((lockerror = nfs_node_lock(dnp))) 4770 error = lockerror; 4771 dxid = xid; 4772 if (!error && !status) { 4773 if (dnp->n_flag & NNEGNCENTRIES) { 4774 dnp->n_flag &= ~NNEGNCENTRIES; 4775 cache_purge_negatives(dvp); 4776 } 4777 error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr); 4778 } 4779 if (nfsvers == NFS_VER3) 4780 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid); 4781 if (!error) 4782 error = status; 4783nfsmout: 4784 nfsm_chain_cleanup(&nmreq); 4785 nfsm_chain_cleanup(&nmrep); 4786 4787 if (!lockerror) { 4788 dnp->n_flag |= NMODIFIED; 4789 /* if directory hadn't changed, update namecache mtime */ 4790 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 4791 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 4792 nfs_node_unlock(dnp); 4793 /* nfs_getattr() will check changed and purge caches */ 4794 nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED); 4795 } 4796 4797 if (!error && fh.fh_len) 4798 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, &nvattr, &xid, rq.r_auth, NG_MAKEENTRY, &np); 4799 if (!error && np) 4800 newvp = NFSTOV(np); 4801 4802 nfs_dulookup_finish(&dul, dnp, ctx); 4803 4804 /* 4805 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 4806 * if we can succeed in looking up the directory. 4807 */ 4808 if ((error == EEXIST) || (!error && !newvp)) { 4809 if (newvp) { 4810 nfs_node_unlock(np); 4811 vnode_put(newvp); 4812 newvp = NULL; 4813 } 4814 error = nfs_lookitup(dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx, &np); 4815 if (!error) { 4816 newvp = NFSTOV(np); 4817 if (vnode_vtype(newvp) != VDIR) 4818 error = EEXIST; 4819 } 4820 } 4821 if (!busyerror) 4822 nfs_node_clear_busy(dnp); 4823 if (!error && (gotuid || gotgid) && 4824 (!newvp || nfs_getattrcache(np, &nvattr, 0) || 4825 (gotuid && (nvattr.nva_uid != vap->va_uid)) || 4826 (gotgid && (nvattr.nva_gid != vap->va_gid)))) { 4827 /* clear ID bits if server didn't use them (or we can't tell) */ 4828 VATTR_CLEAR_SUPPORTED(vap, va_uid); 4829 VATTR_CLEAR_SUPPORTED(vap, va_gid); 4830 } 4831 if (error) { 4832 if (newvp) { 4833 nfs_node_unlock(np); 4834 vnode_put(newvp); 4835 } 4836 } else { 4837 nfs_node_unlock(np); 4838 *ap->a_vpp = newvp; 4839 } 4840 return (error); 4841} 4842 4843/* 4844 * NFS remove directory call 4845 */ 4846int 4847nfs3_vnop_rmdir( 4848 struct vnop_rmdir_args /* { 4849 struct vnodeop_desc *a_desc; 4850 vnode_t a_dvp; 4851 vnode_t a_vp; 4852 struct componentname *a_cnp; 4853 vfs_context_t a_context; 4854 } */ *ap) 4855{ 4856 vfs_context_t ctx = ap->a_context; 4857 vnode_t vp = ap->a_vp; 4858 vnode_t dvp = ap->a_dvp; 4859 struct componentname *cnp = ap->a_cnp; 4860 int error = 0, lockerror = ENOENT, status, wccpostattr = 0; 4861 struct timespec premtime = { 0, 0 }; 4862 struct nfsmount *nmp; 4863 nfsnode_t np = VTONFS(vp); 4864 nfsnode_t dnp = VTONFS(dvp); 4865 int nfsvers; 4866 u_int64_t xid; 4867 struct nfsm_chain nmreq, nmrep; 4868 struct nfsreq rq, *req = &rq; 4869 struct nfs_dulookup dul; 4870 4871 nmp = VTONMP(vp); 4872 if (nfs_mount_gone(nmp)) 4873 return (ENXIO); 4874 nfsvers = nmp->nm_vers; 4875 if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) 4876 return (ENAMETOOLONG); 4877 4878 if ((error = nfs_node_set_busy2(dnp, np, vfs_context_thread(ctx)))) 4879 return (error); 4880 4881 nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx); 4882 4883 nfsm_chain_null(&nmreq); 4884 nfsm_chain_null(&nmrep); 4885 4886 nfsm_chain_build_alloc_init(error, &nmreq, 4887 NFSX_FH(nfsvers) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 4888 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 4889 nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp); 4890 nfsm_chain_build_done(error, &nmreq); 4891 nfsmout_if(error); 4892 4893 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_RMDIR, 4894 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req); 4895 if (!error) { 4896 nfs_dulookup_start(&dul, dnp, ctx); 4897 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 4898 } 4899 4900 if ((lockerror = nfs_node_lock(dnp))) 4901 error = lockerror; 4902 if (nfsvers == NFS_VER3) 4903 nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &xid); 4904 if (!error) 4905 error = status; 4906nfsmout: 4907 nfsm_chain_cleanup(&nmreq); 4908 nfsm_chain_cleanup(&nmrep); 4909 4910 if (!lockerror) { 4911 dnp->n_flag |= NMODIFIED; 4912 /* if directory hadn't changed, update namecache mtime */ 4913 if (nfstimespeccmp(&dnp->n_ncmtime, &premtime, ==)) 4914 NFS_CHANGED_UPDATE_NC(nfsvers, dnp, &dnp->n_vattr); 4915 nfs_node_unlock(dnp); 4916 nfs_name_cache_purge(dnp, np, cnp, ctx); 4917 /* nfs_getattr() will check changed and purge caches */ 4918 nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED); 4919 } 4920 nfs_dulookup_finish(&dul, dnp, ctx); 4921 nfs_node_clear_busy2(dnp, np); 4922 4923 /* 4924 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 4925 */ 4926 if (error == ENOENT) 4927 error = 0; 4928 if (!error) { 4929 /* 4930 * remove nfsnode from hash now so we can't accidentally find it 4931 * again if another object gets created with the same filehandle 4932 * before this vnode gets reclaimed 4933 */ 4934 lck_mtx_lock(nfs_node_hash_mutex); 4935 if (np->n_hflag & NHHASHED) { 4936 LIST_REMOVE(np, n_hash); 4937 np->n_hflag &= ~NHHASHED; 4938 FSDBG(266, 0, np, np->n_flag, 0xb1eb1e); 4939 } 4940 lck_mtx_unlock(nfs_node_hash_mutex); 4941 } 4942 return (error); 4943} 4944 4945/* 4946 * NFS readdir call 4947 * 4948 * The incoming "offset" is a directory cookie indicating where in the 4949 * directory entries should be read from. A zero cookie means start at 4950 * the beginning of the directory. Any other cookie will be a cookie 4951 * returned from the server. 4952 * 4953 * Using that cookie, determine which buffer (and where in that buffer) 4954 * to start returning entries from. Buffer logical block numbers are 4955 * the cookies they start at. If a buffer is found that is not full, 4956 * call into the bio/RPC code to fill it. The RPC code will probably 4957 * fill several buffers (dropping the first, requiring a re-get). 4958 * 4959 * When done copying entries to the buffer, set the offset to the current 4960 * entry's cookie and enter that cookie in the cookie cache. 4961 * 4962 * Note: because the getdirentries(2) API returns a long-typed offset, 4963 * the incoming offset is a potentially truncated cookie (ptc). 4964 * The cookie matching code is aware of this and will fall back to 4965 * matching only 32 bits of the cookie. 4966 */ 4967int 4968nfs_vnop_readdir( 4969 struct vnop_readdir_args /* { 4970 struct vnodeop_desc *a_desc; 4971 vnode_t a_vp; 4972 struct uio *a_uio; 4973 int a_flags; 4974 int *a_eofflag; 4975 int *a_numdirent; 4976 vfs_context_t a_context; 4977 } */ *ap) 4978{ 4979 vfs_context_t ctx = ap->a_context; 4980 vnode_t dvp = ap->a_vp; 4981 nfsnode_t dnp = VTONFS(dvp); 4982 struct nfsmount *nmp; 4983 uio_t uio = ap->a_uio; 4984 int error, nfsvers, extended, numdirent, bigcookies, ptc, done; 4985 uint16_t i, iptc, rlen, nlen; 4986 uint64_t cookie, nextcookie, lbn = 0; 4987 struct nfsbuf *bp = NULL; 4988 struct nfs_dir_buf_header *ndbhp; 4989 struct direntry *dp, *dpptc; 4990 struct dirent dent; 4991 char *cp = NULL; 4992 thread_t thd; 4993 4994 nmp = VTONMP(dvp); 4995 if (nfs_mount_gone(nmp)) 4996 return (ENXIO); 4997 nfsvers = nmp->nm_vers; 4998 bigcookies = (nmp->nm_state & NFSSTA_BIGCOOKIES); 4999 extended = (ap->a_flags & VNODE_READDIR_EXTENDED); 5000 5001 if (vnode_vtype(dvp) != VDIR) 5002 return (EPERM); 5003 5004 if (ap->a_eofflag) 5005 *ap->a_eofflag = 0; 5006 5007 if (uio_resid(uio) == 0) 5008 return (0); 5009 5010 if ((nfsvers >= NFS_VER4) && (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER)) { 5011 /* trigger directories should never be read, return nothing */ 5012 return (0); 5013 } 5014 5015 thd = vfs_context_thread(ctx); 5016 numdirent = done = 0; 5017 nextcookie = uio_offset(uio); 5018 ptc = bigcookies && NFS_DIR_COOKIE_POTENTIALLY_TRUNCATED(nextcookie); 5019 5020 if ((error = nfs_node_lock(dnp))) 5021 goto out; 5022 5023 if (dnp->n_flag & NNEEDINVALIDATE) { 5024 dnp->n_flag &= ~NNEEDINVALIDATE; 5025 nfs_invaldir(dnp); 5026 nfs_node_unlock(dnp); 5027 error = nfs_vinvalbuf(dvp, 0, ctx, 1); 5028 if (!error) 5029 error = nfs_node_lock(dnp); 5030 if (error) 5031 goto out; 5032 } 5033 5034 /* 5035 * check for need to invalidate when (re)starting at beginning 5036 */ 5037 if (!nextcookie) { 5038 if (dnp->n_flag & NMODIFIED) { 5039 nfs_invaldir(dnp); 5040 nfs_node_unlock(dnp); 5041 if ((error = nfs_vinvalbuf(dvp, 0, ctx, 1))) 5042 goto out; 5043 } else { 5044 nfs_node_unlock(dnp); 5045 } 5046 /* nfs_getattr() will check changed and purge caches */ 5047 if ((error = nfs_getattr(dnp, NULL, ctx, NGA_UNCACHED))) 5048 goto out; 5049 } else { 5050 nfs_node_unlock(dnp); 5051 } 5052 5053 error = nfs_dir_cookie_to_lbn(dnp, nextcookie, &ptc, &lbn); 5054 if (error) { 5055 if (error < 0) { /* just hit EOF cookie */ 5056 done = 1; 5057 error = 0; 5058 } 5059 if (ap->a_eofflag) 5060 *ap->a_eofflag = 1; 5061 } 5062 5063 while (!error && !done) { 5064 OSAddAtomic64(1, &nfsstats.biocache_readdirs); 5065 cookie = nextcookie; 5066getbuffer: 5067 error = nfs_buf_get(dnp, lbn, NFS_DIRBLKSIZ, thd, NBLK_READ, &bp); 5068 if (error) 5069 goto out; 5070 ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5071 if (!ISSET(bp->nb_flags, NB_CACHE) || !ISSET(ndbhp->ndbh_flags, NDB_FULL)) { 5072 if (!ISSET(bp->nb_flags, NB_CACHE)) { /* initialize the buffer */ 5073 ndbhp->ndbh_flags = 0; 5074 ndbhp->ndbh_count = 0; 5075 ndbhp->ndbh_entry_end = sizeof(*ndbhp); 5076 ndbhp->ndbh_ncgen = dnp->n_ncgen; 5077 } 5078 error = nfs_buf_readdir(bp, ctx); 5079 if (error == NFSERR_DIRBUFDROPPED) 5080 goto getbuffer; 5081 if (error) 5082 nfs_buf_release(bp, 1); 5083 if (error && (error != ENXIO) && (error != ETIMEDOUT) && (error != EINTR) && (error != ERESTART)) { 5084 if (!nfs_node_lock(dnp)) { 5085 nfs_invaldir(dnp); 5086 nfs_node_unlock(dnp); 5087 } 5088 nfs_vinvalbuf(dvp, 0, ctx, 1); 5089 if (error == NFSERR_BAD_COOKIE) 5090 error = ENOENT; 5091 } 5092 if (error) 5093 goto out; 5094 } 5095 5096 /* find next entry to return */ 5097 dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); 5098 i = 0; 5099 if ((lbn != cookie) && !(ptc && NFS_DIR_COOKIE_SAME32(lbn, cookie))) { 5100 dpptc = NULL; 5101 iptc = 0; 5102 for (; (i < ndbhp->ndbh_count) && (cookie != dp->d_seekoff); i++) { 5103 if (ptc && !dpptc && NFS_DIR_COOKIE_SAME32(cookie, dp->d_seekoff)) { 5104 iptc = i; 5105 dpptc = dp; 5106 } 5107 nextcookie = dp->d_seekoff; 5108 dp = NFS_DIRENTRY_NEXT(dp); 5109 } 5110 if ((i == ndbhp->ndbh_count) && dpptc) { 5111 i = iptc; 5112 dp = dpptc; 5113 } 5114 if (i < ndbhp->ndbh_count) { 5115 nextcookie = dp->d_seekoff; 5116 dp = NFS_DIRENTRY_NEXT(dp); 5117 i++; 5118 } 5119 } 5120 ptc = 0; /* only have to deal with ptc on first cookie */ 5121 5122 /* return as many entries as we can */ 5123 for (; i < ndbhp->ndbh_count; i++) { 5124 if (extended) { 5125 rlen = dp->d_reclen; 5126 cp = (char*)dp; 5127 } else { 5128 if (!cp) { 5129 cp = (char*)&dent; 5130 bzero(cp, sizeof(dent)); 5131 } 5132 if (dp->d_namlen > (sizeof(dent.d_name) - 1)) 5133 nlen = sizeof(dent.d_name) - 1; 5134 else 5135 nlen = dp->d_namlen; 5136 rlen = NFS_DIRENT_LEN(nlen); 5137 dent.d_reclen = rlen; 5138 dent.d_ino = dp->d_ino; 5139 dent.d_type = dp->d_type; 5140 dent.d_namlen = nlen; 5141 strlcpy(dent.d_name, dp->d_name, nlen + 1); 5142 } 5143 /* check that the record fits */ 5144 if (rlen > uio_resid(uio)) { 5145 done = 1; 5146 break; 5147 } 5148 if ((error = uiomove(cp, rlen, uio))) 5149 break; 5150 numdirent++; 5151 nextcookie = dp->d_seekoff; 5152 dp = NFS_DIRENTRY_NEXT(dp); 5153 } 5154 5155 if (i == ndbhp->ndbh_count) { 5156 /* hit end of buffer, move to next buffer */ 5157 lbn = nextcookie; 5158 /* if we also hit EOF, we're done */ 5159 if (ISSET(ndbhp->ndbh_flags, NDB_EOF)) { 5160 done = 1; 5161 if (ap->a_eofflag) 5162 *ap->a_eofflag = 1; 5163 } 5164 } 5165 if (!error) 5166 uio_setoffset(uio, nextcookie); 5167 if (!error && !done && (nextcookie == cookie)) { 5168 printf("nfs readdir cookie didn't change 0x%llx, %d/%d\n", cookie, i, ndbhp->ndbh_count); 5169 error = EIO; 5170 } 5171 nfs_buf_release(bp, 1); 5172 } 5173 5174 if (!error) 5175 nfs_dir_cookie_cache(dnp, nextcookie, lbn); 5176 5177 if (ap->a_numdirent) 5178 *ap->a_numdirent = numdirent; 5179out: 5180 return (error); 5181} 5182 5183 5184/* 5185 * Invalidate cached directory information, except for the actual directory 5186 * blocks (which are invalidated separately). 5187 */ 5188void 5189nfs_invaldir(nfsnode_t dnp) 5190{ 5191 if (vnode_vtype(NFSTOV(dnp)) != VDIR) 5192 return; 5193 dnp->n_eofcookie = 0; 5194 dnp->n_cookieverf = 0; 5195 if (!dnp->n_cookiecache) 5196 return; 5197 dnp->n_cookiecache->free = 0; 5198 dnp->n_cookiecache->mru = -1; 5199 memset(dnp->n_cookiecache->next, -1, NFSNUMCOOKIES); 5200} 5201 5202/* 5203 * calculate how much space is available for additional directory entries. 5204 */ 5205uint32_t 5206nfs_dir_buf_freespace(struct nfsbuf *bp, int rdirplus) 5207{ 5208 struct nfs_dir_buf_header *ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5209 uint32_t space; 5210 5211 if (!ndbhp) 5212 return (0); 5213 space = bp->nb_bufsize - ndbhp->ndbh_entry_end; 5214 if (rdirplus) 5215 space -= ndbhp->ndbh_count * sizeof(struct nfs_vattr); 5216 return (space); 5217} 5218 5219/* 5220 * add/update a cookie->lbn entry in the directory cookie cache 5221 */ 5222void 5223nfs_dir_cookie_cache(nfsnode_t dnp, uint64_t cookie, uint64_t lbn) 5224{ 5225 struct nfsdmap *ndcc; 5226 int8_t i, prev; 5227 5228 if (!cookie) 5229 return; 5230 5231 if (nfs_node_lock(dnp)) 5232 return; 5233 5234 if (cookie == dnp->n_eofcookie) { /* EOF cookie */ 5235 nfs_node_unlock(dnp); 5236 return; 5237 } 5238 5239 ndcc = dnp->n_cookiecache; 5240 if (!ndcc) { 5241 /* allocate the cookie cache structure */ 5242 MALLOC_ZONE(dnp->n_cookiecache, struct nfsdmap *, 5243 sizeof(struct nfsdmap), M_NFSDIROFF, M_WAITOK); 5244 if (!dnp->n_cookiecache) { 5245 nfs_node_unlock(dnp); 5246 return; 5247 } 5248 ndcc = dnp->n_cookiecache; 5249 ndcc->free = 0; 5250 ndcc->mru = -1; 5251 memset(ndcc->next, -1, NFSNUMCOOKIES); 5252 } 5253 5254 /* 5255 * Search the list for this cookie. 5256 * Keep track of previous and last entries. 5257 */ 5258 prev = -1; 5259 i = ndcc->mru; 5260 while ((i != -1) && (cookie != ndcc->cookies[i].key)) { 5261 if (ndcc->next[i] == -1) /* stop on last entry so we can reuse */ 5262 break; 5263 prev = i; 5264 i = ndcc->next[i]; 5265 } 5266 if ((i != -1) && (cookie == ndcc->cookies[i].key)) { 5267 /* found it, remove from list */ 5268 if (prev != -1) 5269 ndcc->next[prev] = ndcc->next[i]; 5270 else 5271 ndcc->mru = ndcc->next[i]; 5272 } else { 5273 /* not found, use next free entry or reuse last entry */ 5274 if (ndcc->free != NFSNUMCOOKIES) 5275 i = ndcc->free++; 5276 else 5277 ndcc->next[prev] = -1; 5278 ndcc->cookies[i].key = cookie; 5279 ndcc->cookies[i].lbn = lbn; 5280 } 5281 /* insert cookie at head of MRU list */ 5282 ndcc->next[i] = ndcc->mru; 5283 ndcc->mru = i; 5284 nfs_node_unlock(dnp); 5285} 5286 5287/* 5288 * Try to map the given directory cookie to a directory buffer (return lbn). 5289 * If we have a possibly truncated cookie (ptc), check for 32-bit matches too. 5290 */ 5291int 5292nfs_dir_cookie_to_lbn(nfsnode_t dnp, uint64_t cookie, int *ptc, uint64_t *lbnp) 5293{ 5294 struct nfsdmap *ndcc = dnp->n_cookiecache; 5295 int8_t eofptc, found; 5296 int i, iptc; 5297 struct nfsmount *nmp; 5298 struct nfsbuf *bp, *lastbp; 5299 struct nfsbuflists blist; 5300 struct direntry *dp, *dpptc; 5301 struct nfs_dir_buf_header *ndbhp; 5302 5303 if (!cookie) { /* initial cookie */ 5304 *lbnp = 0; 5305 *ptc = 0; 5306 return (0); 5307 } 5308 5309 if (nfs_node_lock(dnp)) 5310 return (ENOENT); 5311 5312 if (cookie == dnp->n_eofcookie) { /* EOF cookie */ 5313 nfs_node_unlock(dnp); 5314 OSAddAtomic64(1, &nfsstats.direofcache_hits); 5315 *ptc = 0; 5316 return (-1); 5317 } 5318 /* note if cookie is a 32-bit match with the EOF cookie */ 5319 eofptc = *ptc ? NFS_DIR_COOKIE_SAME32(cookie, dnp->n_eofcookie) : 0; 5320 iptc = -1; 5321 5322 /* search the list for the cookie */ 5323 for (i = ndcc ? ndcc->mru : -1; i >= 0; i = ndcc->next[i]) { 5324 if (ndcc->cookies[i].key == cookie) { 5325 /* found a match for this cookie */ 5326 *lbnp = ndcc->cookies[i].lbn; 5327 nfs_node_unlock(dnp); 5328 OSAddAtomic64(1, &nfsstats.direofcache_hits); 5329 *ptc = 0; 5330 return (0); 5331 } 5332 /* check for 32-bit match */ 5333 if (*ptc && (iptc == -1) && NFS_DIR_COOKIE_SAME32(ndcc->cookies[i].key, cookie)) 5334 iptc = i; 5335 } 5336 /* exact match not found */ 5337 if (eofptc) { 5338 /* but 32-bit match hit the EOF cookie */ 5339 nfs_node_unlock(dnp); 5340 OSAddAtomic64(1, &nfsstats.direofcache_hits); 5341 return (-1); 5342 } 5343 if (iptc >= 0) { 5344 /* but 32-bit match got a hit */ 5345 *lbnp = ndcc->cookies[iptc].lbn; 5346 nfs_node_unlock(dnp); 5347 OSAddAtomic64(1, &nfsstats.direofcache_hits); 5348 return (0); 5349 } 5350 nfs_node_unlock(dnp); 5351 5352 /* 5353 * No match found in the cookie cache... hmm... 5354 * Let's search the directory's buffers for the cookie. 5355 */ 5356 nmp = NFSTONMP(dnp); 5357 if (nfs_mount_gone(nmp)) 5358 return (ENXIO); 5359 dpptc = NULL; 5360 found = 0; 5361 5362 lck_mtx_lock(nfs_buf_mutex); 5363 /* 5364 * Scan the list of buffers, keeping them in order. 5365 * Note that itercomplete inserts each of the remaining buffers 5366 * into the head of list (thus reversing the elements). So, we 5367 * make sure to iterate through all buffers, inserting them after 5368 * each other, to keep them in order. 5369 * Also note: the LIST_INSERT_AFTER(lastbp) is only safe because 5370 * we don't drop nfs_buf_mutex. 5371 */ 5372 if (!nfs_buf_iterprepare(dnp, &blist, NBI_CLEAN)) { 5373 lastbp = NULL; 5374 while ((bp = LIST_FIRST(&blist))) { 5375 LIST_REMOVE(bp, nb_vnbufs); 5376 if (!lastbp) 5377 LIST_INSERT_HEAD(&dnp->n_cleanblkhd, bp, nb_vnbufs); 5378 else 5379 LIST_INSERT_AFTER(lastbp, bp, nb_vnbufs); 5380 lastbp = bp; 5381 if (found) 5382 continue; 5383 nfs_buf_refget(bp); 5384 if (nfs_buf_acquire(bp, NBAC_NOWAIT, 0, 0)) { 5385 /* just skip this buffer */ 5386 nfs_buf_refrele(bp); 5387 continue; 5388 } 5389 nfs_buf_refrele(bp); 5390 5391 /* scan the buffer for the cookie */ 5392 ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5393 dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); 5394 dpptc = NULL; 5395 for (i=0; (i < ndbhp->ndbh_count) && (cookie != dp->d_seekoff); i++) { 5396 if (*ptc && !dpptc && NFS_DIR_COOKIE_SAME32(cookie, dp->d_seekoff)) { 5397 dpptc = dp; 5398 iptc = i; 5399 } 5400 dp = NFS_DIRENTRY_NEXT(dp); 5401 } 5402 if ((i == ndbhp->ndbh_count) && dpptc) { 5403 /* found only a PTC match */ 5404 dp = dpptc; 5405 i = iptc; 5406 } else if (i < ndbhp->ndbh_count) { 5407 *ptc = 0; 5408 } 5409 if (i < (ndbhp->ndbh_count-1)) { 5410 /* next entry is *in* this buffer: return this block */ 5411 *lbnp = bp->nb_lblkno; 5412 found = 1; 5413 } else if (i == (ndbhp->ndbh_count-1)) { 5414 /* next entry refers to *next* buffer: return next block */ 5415 *lbnp = dp->d_seekoff; 5416 found = 1; 5417 } 5418 nfs_buf_drop(bp); 5419 } 5420 nfs_buf_itercomplete(dnp, &blist, NBI_CLEAN); 5421 } 5422 lck_mtx_unlock(nfs_buf_mutex); 5423 if (found) { 5424 OSAddAtomic64(1, &nfsstats.direofcache_hits); 5425 return (0); 5426 } 5427 5428 /* still not found... oh well, just start a new block */ 5429 *lbnp = cookie; 5430 OSAddAtomic64(1, &nfsstats.direofcache_misses); 5431 return (0); 5432} 5433 5434/* 5435 * scan a directory buffer for the given name 5436 * Returns: ESRCH if not found, ENOENT if found invalid, 0 if found 5437 * Note: should only be called with RDIRPLUS directory buffers 5438 */ 5439 5440#define NDBS_PURGE 1 5441#define NDBS_UPDATE 2 5442 5443int 5444nfs_dir_buf_search( 5445 struct nfsbuf *bp, 5446 struct componentname *cnp, 5447 fhandle_t *fhp, 5448 struct nfs_vattr *nvap, 5449 uint64_t *xidp, 5450 time_t *attrstampp, 5451 daddr64_t *nextlbnp, 5452 int flags) 5453{ 5454 struct direntry *dp; 5455 struct nfs_dir_buf_header *ndbhp; 5456 struct nfs_vattr *nvattrp; 5457 daddr64_t nextlbn = 0; 5458 int i, error = ESRCH, fhlen; 5459 5460 /* scan the buffer for the name */ 5461 ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5462 dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); 5463 for (i=0; i < ndbhp->ndbh_count; i++) { 5464 nextlbn = dp->d_seekoff; 5465 if ((cnp->cn_namelen == dp->d_namlen) && !strcmp(cnp->cn_nameptr, dp->d_name)) { 5466 fhlen = dp->d_name[dp->d_namlen+1]; 5467 nvattrp = NFS_DIR_BUF_NVATTR(bp, i); 5468 if ((ndbhp->ndbh_ncgen != bp->nb_np->n_ncgen) || (fhp->fh_len == 0) || 5469 (nvattrp->nva_type == VNON) || (nvattrp->nva_fileid == 0)) { 5470 /* entry is not valid */ 5471 error = ENOENT; 5472 break; 5473 } 5474 if (flags == NDBS_PURGE) { 5475 dp->d_fileno = 0; 5476 bzero(nvattrp, sizeof(*nvattrp)); 5477 error = ENOENT; 5478 break; 5479 } 5480 if (flags == NDBS_UPDATE) { 5481 /* update direntry's attrs if fh matches */ 5482 if ((fhp->fh_len == fhlen) && !bcmp(&dp->d_name[dp->d_namlen+2], fhp->fh_data, fhlen)) { 5483 bcopy(nvap, nvattrp, sizeof(*nvap)); 5484 dp->d_fileno = nvattrp->nva_fileid; 5485 nvattrp->nva_fileid = *xidp; 5486 *(time_t*)(&dp->d_name[dp->d_namlen+2+fhp->fh_len]) = *attrstampp; 5487 } 5488 error = 0; 5489 break; 5490 } 5491 /* copy out fh, attrs, attrstamp, and xid */ 5492 fhp->fh_len = fhlen; 5493 bcopy(&dp->d_name[dp->d_namlen+2], fhp->fh_data, MAX(fhp->fh_len, (int)sizeof(fhp->fh_data))); 5494 *attrstampp = *(time_t*)(&dp->d_name[dp->d_namlen+2+fhp->fh_len]); 5495 bcopy(nvattrp, nvap, sizeof(*nvap)); 5496 *xidp = nvap->nva_fileid; 5497 nvap->nva_fileid = dp->d_fileno; 5498 error = 0; 5499 break; 5500 } 5501 dp = NFS_DIRENTRY_NEXT(dp); 5502 } 5503 if (nextlbnp) 5504 *nextlbnp = nextlbn; 5505 return (error); 5506} 5507 5508/* 5509 * Look up a name in a directory's buffers. 5510 * Note: should only be called with RDIRPLUS directory buffers 5511 */ 5512int 5513nfs_dir_buf_cache_lookup(nfsnode_t dnp, nfsnode_t *npp, struct componentname *cnp, vfs_context_t ctx, int purge) 5514{ 5515 nfsnode_t newnp; 5516 struct nfsmount *nmp; 5517 int error = 0, i, found = 0, count = 0; 5518 u_int64_t xid; 5519 struct nfs_vattr nvattr; 5520 fhandle_t fh; 5521 time_t attrstamp = 0; 5522 thread_t thd = vfs_context_thread(ctx); 5523 struct nfsbuf *bp, *lastbp, *foundbp; 5524 struct nfsbuflists blist; 5525 daddr64_t lbn, nextlbn; 5526 int dotunder = (cnp->cn_namelen > 2) && (cnp->cn_nameptr[0] == '.') && (cnp->cn_nameptr[1] == '_'); 5527 5528 nmp = NFSTONMP(dnp); 5529 if (nfs_mount_gone(nmp)) 5530 return (ENXIO); 5531 if (!purge) 5532 *npp = NULL; 5533 5534 /* first check most recent buffer (and next one too) */ 5535 lbn = dnp->n_lastdbl; 5536 for (i=0; i < 2; i++) { 5537 if ((error = nfs_buf_get(dnp, lbn, NFS_DIRBLKSIZ, thd, NBLK_READ|NBLK_ONLYVALID, &bp))) 5538 return (error); 5539 if (!bp) 5540 break; 5541 count++; 5542 error = nfs_dir_buf_search(bp, cnp, &fh, &nvattr, &xid, &attrstamp, &nextlbn, purge ? NDBS_PURGE : 0); 5543 nfs_buf_release(bp, 0); 5544 if (error == ESRCH) { 5545 error = 0; 5546 } else { 5547 found = 1; 5548 break; 5549 } 5550 lbn = nextlbn; 5551 } 5552 5553 lck_mtx_lock(nfs_buf_mutex); 5554 if (found) { 5555 dnp->n_lastdbl = lbn; 5556 goto done; 5557 } 5558 5559 /* 5560 * Scan the list of buffers, keeping them in order. 5561 * Note that itercomplete inserts each of the remaining buffers 5562 * into the head of list (thus reversing the elements). So, we 5563 * make sure to iterate through all buffers, inserting them after 5564 * each other, to keep them in order. 5565 * Also note: the LIST_INSERT_AFTER(lastbp) is only safe because 5566 * we don't drop nfs_buf_mutex. 5567 */ 5568 if (!nfs_buf_iterprepare(dnp, &blist, NBI_CLEAN)) { 5569 lastbp = foundbp = NULL; 5570 while ((bp = LIST_FIRST(&blist))) { 5571 LIST_REMOVE(bp, nb_vnbufs); 5572 if (!lastbp) 5573 LIST_INSERT_HEAD(&dnp->n_cleanblkhd, bp, nb_vnbufs); 5574 else 5575 LIST_INSERT_AFTER(lastbp, bp, nb_vnbufs); 5576 lastbp = bp; 5577 if (error || found) 5578 continue; 5579 if (!purge && dotunder && (count > 100)) /* don't waste too much time looking for ._ files */ 5580 continue; 5581 nfs_buf_refget(bp); 5582 lbn = bp->nb_lblkno; 5583 if (nfs_buf_acquire(bp, NBAC_NOWAIT, 0, 0)) { 5584 /* just skip this buffer */ 5585 nfs_buf_refrele(bp); 5586 continue; 5587 } 5588 nfs_buf_refrele(bp); 5589 count++; 5590 error = nfs_dir_buf_search(bp, cnp, &fh, &nvattr, &xid, &attrstamp, NULL, purge ? NDBS_PURGE : 0); 5591 if (error == ESRCH) { 5592 error = 0; 5593 } else { 5594 found = 1; 5595 foundbp = bp; 5596 } 5597 nfs_buf_drop(bp); 5598 } 5599 if (found) { 5600 LIST_REMOVE(foundbp, nb_vnbufs); 5601 LIST_INSERT_HEAD(&dnp->n_cleanblkhd, foundbp, nb_vnbufs); 5602 dnp->n_lastdbl = foundbp->nb_lblkno; 5603 } 5604 nfs_buf_itercomplete(dnp, &blist, NBI_CLEAN); 5605 } 5606done: 5607 lck_mtx_unlock(nfs_buf_mutex); 5608 5609 if (!error && found && !purge) { 5610 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, 5611 &nvattr, &xid, dnp->n_auth, NG_MAKEENTRY, &newnp); 5612 if (error) 5613 return (error); 5614 newnp->n_attrstamp = attrstamp; 5615 *npp = newnp; 5616 nfs_node_unlock(newnp); 5617 /* check if the dir buffer's attrs are out of date */ 5618 if (!nfs_getattr(newnp, &nvattr, ctx, NGA_CACHED) && 5619 (newnp->n_attrstamp != attrstamp)) { 5620 /* they are, so update them */ 5621 error = nfs_buf_get(dnp, lbn, NFS_DIRBLKSIZ, thd, NBLK_READ|NBLK_ONLYVALID, &bp); 5622 if (!error && bp) { 5623 attrstamp = newnp->n_attrstamp; 5624 xid = newnp->n_xid; 5625 nfs_dir_buf_search(bp, cnp, &fh, &nvattr, &xid, &attrstamp, NULL, NDBS_UPDATE); 5626 nfs_buf_release(bp, 0); 5627 } 5628 error = 0; 5629 } 5630 } 5631 5632 return (error); 5633} 5634 5635/* 5636 * Purge name cache entries for the given node. 5637 * For RDIRPLUS, also invalidate the entry in the directory's buffers. 5638 */ 5639void 5640nfs_name_cache_purge(nfsnode_t dnp, nfsnode_t np, struct componentname *cnp, vfs_context_t ctx) 5641{ 5642 struct nfsmount *nmp = NFSTONMP(dnp); 5643 5644 cache_purge(NFSTOV(np)); 5645 if (nmp && (nmp->nm_vers > NFS_VER2) && NMFLAG(nmp, RDIRPLUS)) 5646 nfs_dir_buf_cache_lookup(dnp, NULL, cnp, ctx, 1); 5647} 5648 5649/* 5650 * NFS V3 readdir (plus) RPC. 5651 */ 5652int 5653nfs3_readdir_rpc(nfsnode_t dnp, struct nfsbuf *bp, vfs_context_t ctx) 5654{ 5655 struct nfsmount *nmp; 5656 int error = 0, lockerror, nfsvers, rdirplus, bigcookies; 5657 int i, status, attrflag, fhflag, more_entries = 1, eof, bp_dropped = 0; 5658 uint32_t nmreaddirsize, nmrsize; 5659 uint32_t namlen, skiplen, fhlen, xlen, attrlen, reclen, space_free, space_needed; 5660 uint64_t cookie, lastcookie, xid, savedxid, fileno; 5661 struct nfsm_chain nmreq, nmrep, nmrepsave; 5662 fhandle_t fh; 5663 struct nfs_vattr *nvattrp; 5664 struct nfs_dir_buf_header *ndbhp; 5665 struct direntry *dp; 5666 char *padstart, padlen; 5667 struct timeval now; 5668 5669 nmp = NFSTONMP(dnp); 5670 if (nfs_mount_gone(nmp)) 5671 return (ENXIO); 5672 nfsvers = nmp->nm_vers; 5673 nmreaddirsize = nmp->nm_readdirsize; 5674 nmrsize = nmp->nm_rsize; 5675 bigcookies = nmp->nm_state & NFSSTA_BIGCOOKIES; 5676noplus: 5677 rdirplus = ((nfsvers > NFS_VER2) && NMFLAG(nmp, RDIRPLUS)) ? 1 : 0; 5678 5679 if ((lockerror = nfs_node_lock(dnp))) 5680 return (lockerror); 5681 5682 /* determine cookie to use, and move dp to the right offset */ 5683 ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5684 dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); 5685 if (ndbhp->ndbh_count) { 5686 for (i=0; i < ndbhp->ndbh_count-1; i++) 5687 dp = NFS_DIRENTRY_NEXT(dp); 5688 cookie = dp->d_seekoff; 5689 dp = NFS_DIRENTRY_NEXT(dp); 5690 } else { 5691 cookie = bp->nb_lblkno; 5692 /* increment with every buffer read */ 5693 OSAddAtomic64(1, &nfsstats.readdir_bios); 5694 } 5695 lastcookie = cookie; 5696 5697 /* 5698 * Loop around doing readdir(plus) RPCs of size nm_readdirsize until 5699 * the buffer is full (or we hit EOF). Then put the remainder of the 5700 * results in the next buffer(s). 5701 */ 5702 nfsm_chain_null(&nmreq); 5703 nfsm_chain_null(&nmrep); 5704 while (nfs_dir_buf_freespace(bp, rdirplus) && !(ndbhp->ndbh_flags & NDB_FULL)) { 5705 nfsm_chain_build_alloc_init(error, &nmreq, 5706 NFSX_FH(nfsvers) + NFSX_READDIR(nfsvers) + NFSX_UNSIGNED); 5707 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 5708 if (nfsvers == NFS_VER3) { 5709 /* opaque values don't need swapping, but as long */ 5710 /* as we are consistent about it, it should be ok */ 5711 nfsm_chain_add_64(error, &nmreq, cookie); 5712 nfsm_chain_add_64(error, &nmreq, dnp->n_cookieverf); 5713 } else { 5714 nfsm_chain_add_32(error, &nmreq, cookie); 5715 } 5716 nfsm_chain_add_32(error, &nmreq, nmreaddirsize); 5717 if (rdirplus) 5718 nfsm_chain_add_32(error, &nmreq, nmrsize); 5719 nfsm_chain_build_done(error, &nmreq); 5720 nfs_node_unlock(dnp); 5721 lockerror = ENOENT; 5722 nfsmout_if(error); 5723 5724 error = nfs_request(dnp, NULL, &nmreq, 5725 rdirplus ? NFSPROC_READDIRPLUS : NFSPROC_READDIR, 5726 ctx, NULL, &nmrep, &xid, &status); 5727 5728 if ((lockerror = nfs_node_lock(dnp))) 5729 error = lockerror; 5730 5731 savedxid = xid; 5732 if (nfsvers == NFS_VER3) 5733 nfsm_chain_postop_attr_update(error, &nmrep, dnp, &xid); 5734 if (!error) 5735 error = status; 5736 if (nfsvers == NFS_VER3) 5737 nfsm_chain_get_64(error, &nmrep, dnp->n_cookieverf); 5738 nfsm_chain_get_32(error, &nmrep, more_entries); 5739 5740 if (!lockerror) { 5741 nfs_node_unlock(dnp); 5742 lockerror = ENOENT; 5743 } 5744 if (error == NFSERR_NOTSUPP) { 5745 /* oops... it doesn't look like readdirplus is supported */ 5746 lck_mtx_lock(&nmp->nm_lock); 5747 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_RDIRPLUS); 5748 lck_mtx_unlock(&nmp->nm_lock); 5749 goto noplus; 5750 } 5751 nfsmout_if(error); 5752 5753 if (rdirplus) 5754 microuptime(&now); 5755 5756 /* loop through the entries packing them into the buffer */ 5757 while (more_entries) { 5758 if (nfsvers == NFS_VER3) 5759 nfsm_chain_get_64(error, &nmrep, fileno); 5760 else 5761 nfsm_chain_get_32(error, &nmrep, fileno); 5762 nfsm_chain_get_32(error, &nmrep, namlen); 5763 nfsmout_if(error); 5764 /* just truncate names that don't fit in direntry.d_name */ 5765 if (namlen <= 0) { 5766 error = EBADRPC; 5767 goto nfsmout; 5768 } 5769 if (namlen > (sizeof(dp->d_name)-1)) { 5770 skiplen = namlen - sizeof(dp->d_name) + 1; 5771 namlen = sizeof(dp->d_name) - 1; 5772 } else { 5773 skiplen = 0; 5774 } 5775 /* guess that fh size will be same as parent */ 5776 fhlen = rdirplus ? (1 + dnp->n_fhsize) : 0; 5777 xlen = rdirplus ? (fhlen + sizeof(time_t)) : 0; 5778 attrlen = rdirplus ? sizeof(struct nfs_vattr) : 0; 5779 reclen = NFS_DIRENTRY_LEN(namlen + xlen); 5780 space_needed = reclen + attrlen; 5781 space_free = nfs_dir_buf_freespace(bp, rdirplus); 5782 if (space_needed > space_free) { 5783 /* 5784 * We still have entries to pack, but we've 5785 * run out of room in the current buffer. 5786 * So we need to move to the next buffer. 5787 * The block# for the next buffer is the 5788 * last cookie in the current buffer. 5789 */ 5790nextbuffer: 5791 ndbhp->ndbh_flags |= NDB_FULL; 5792 nfs_buf_release(bp, 0); 5793 bp_dropped = 1; 5794 bp = NULL; 5795 error = nfs_buf_get(dnp, lastcookie, NFS_DIRBLKSIZ, vfs_context_thread(ctx), NBLK_READ, &bp); 5796 nfsmout_if(error); 5797 /* initialize buffer */ 5798 ndbhp = (struct nfs_dir_buf_header*)bp->nb_data; 5799 ndbhp->ndbh_flags = 0; 5800 ndbhp->ndbh_count = 0; 5801 ndbhp->ndbh_entry_end = sizeof(*ndbhp); 5802 ndbhp->ndbh_ncgen = dnp->n_ncgen; 5803 space_free = nfs_dir_buf_freespace(bp, rdirplus); 5804 dp = NFS_DIR_BUF_FIRST_DIRENTRY(bp); 5805 /* increment with every buffer read */ 5806 OSAddAtomic64(1, &nfsstats.readdir_bios); 5807 } 5808 nmrepsave = nmrep; 5809 dp->d_fileno = fileno; 5810 dp->d_namlen = namlen; 5811 dp->d_reclen = reclen; 5812 dp->d_type = DT_UNKNOWN; 5813 nfsm_chain_get_opaque(error, &nmrep, namlen, dp->d_name); 5814 nfsmout_if(error); 5815 dp->d_name[namlen] = '\0'; 5816 if (skiplen) 5817 nfsm_chain_adv(error, &nmrep, 5818 nfsm_rndup(namlen + skiplen) - nfsm_rndup(namlen)); 5819 if (nfsvers == NFS_VER3) 5820 nfsm_chain_get_64(error, &nmrep, cookie); 5821 else 5822 nfsm_chain_get_32(error, &nmrep, cookie); 5823 nfsmout_if(error); 5824 dp->d_seekoff = cookie; 5825 if (!bigcookies && (cookie >> 32) && (nmp == NFSTONMP(dnp))) { 5826 /* we've got a big cookie, make sure flag is set */ 5827 lck_mtx_lock(&nmp->nm_lock); 5828 nmp->nm_state |= NFSSTA_BIGCOOKIES; 5829 lck_mtx_unlock(&nmp->nm_lock); 5830 bigcookies = 1; 5831 } 5832 if (rdirplus) { 5833 nvattrp = NFS_DIR_BUF_NVATTR(bp, ndbhp->ndbh_count); 5834 /* check for attributes */ 5835 nfsm_chain_get_32(error, &nmrep, attrflag); 5836 nfsmout_if(error); 5837 if (attrflag) { 5838 /* grab attributes */ 5839 error = nfs_parsefattr(&nmrep, NFS_VER3, nvattrp); 5840 nfsmout_if(error); 5841 dp->d_type = IFTODT(VTTOIF(nvattrp->nva_type)); 5842 /* fileid is already in d_fileno, so stash xid in attrs */ 5843 nvattrp->nva_fileid = savedxid; 5844 } else { 5845 /* mark the attributes invalid */ 5846 bzero(nvattrp, sizeof(struct nfs_vattr)); 5847 } 5848 /* check for file handle */ 5849 nfsm_chain_get_32(error, &nmrep, fhflag); 5850 nfsmout_if(error); 5851 if (fhflag) { 5852 nfsm_chain_get_fh(error, &nmrep, NFS_VER3, &fh); 5853 nfsmout_if(error); 5854 fhlen = fh.fh_len + 1; 5855 xlen = fhlen + sizeof(time_t); 5856 reclen = NFS_DIRENTRY_LEN(namlen + xlen); 5857 space_needed = reclen + attrlen; 5858 if (space_needed > space_free) { 5859 /* didn't actually have the room... move on to next buffer */ 5860 nmrep = nmrepsave; 5861 goto nextbuffer; 5862 } 5863 /* pack the file handle into the record */ 5864 dp->d_name[dp->d_namlen+1] = fh.fh_len; 5865 bcopy(fh.fh_data, &dp->d_name[dp->d_namlen+2], fh.fh_len); 5866 } else { 5867 /* mark the file handle invalid */ 5868 fh.fh_len = 0; 5869 fhlen = fh.fh_len + 1; 5870 xlen = fhlen + sizeof(time_t); 5871 reclen = NFS_DIRENTRY_LEN(namlen + xlen); 5872 bzero(&dp->d_name[dp->d_namlen+1], fhlen); 5873 } 5874 *(time_t*)(&dp->d_name[dp->d_namlen+1+fhlen]) = now.tv_sec; 5875 dp->d_reclen = reclen; 5876 } 5877 padstart = dp->d_name + dp->d_namlen + 1 + xlen; 5878 ndbhp->ndbh_count++; 5879 lastcookie = cookie; 5880 /* advance to next direntry in buffer */ 5881 dp = NFS_DIRENTRY_NEXT(dp); 5882 ndbhp->ndbh_entry_end = (char*)dp - bp->nb_data; 5883 /* zero out the pad bytes */ 5884 padlen = (char*)dp - padstart; 5885 if (padlen > 0) 5886 bzero(padstart, padlen); 5887 /* check for more entries */ 5888 nfsm_chain_get_32(error, &nmrep, more_entries); 5889 nfsmout_if(error); 5890 } 5891 /* Finally, get the eof boolean */ 5892 nfsm_chain_get_32(error, &nmrep, eof); 5893 nfsmout_if(error); 5894 if (eof) { 5895 ndbhp->ndbh_flags |= (NDB_FULL|NDB_EOF); 5896 nfs_node_lock_force(dnp); 5897 dnp->n_eofcookie = lastcookie; 5898 nfs_node_unlock(dnp); 5899 } else { 5900 more_entries = 1; 5901 } 5902 if (bp_dropped) { 5903 nfs_buf_release(bp, 0); 5904 bp = NULL; 5905 break; 5906 } 5907 if ((lockerror = nfs_node_lock(dnp))) 5908 error = lockerror; 5909 nfsmout_if(error); 5910 nfsm_chain_cleanup(&nmrep); 5911 nfsm_chain_null(&nmreq); 5912 } 5913nfsmout: 5914 if (bp_dropped && bp) 5915 nfs_buf_release(bp, 0); 5916 if (!lockerror) 5917 nfs_node_unlock(dnp); 5918 nfsm_chain_cleanup(&nmreq); 5919 nfsm_chain_cleanup(&nmrep); 5920 return (bp_dropped ? NFSERR_DIRBUFDROPPED : error); 5921} 5922 5923/* 5924 * Silly rename. To make the NFS filesystem that is stateless look a little 5925 * more like the "ufs" a remove of an active vnode is translated to a rename 5926 * to a funny looking filename that is removed by nfs_vnop_inactive on the 5927 * nfsnode. There is the potential for another process on a different client 5928 * to create the same funny name between when the lookitup() fails and the 5929 * rename() completes, but... 5930 */ 5931 5932/* format of "random" silly names - includes a number and pid */ 5933/* (note: shouldn't exceed size of nfs_sillyrename.nsr_name) */ 5934#define NFS_SILLYNAME_FORMAT ".nfs.%08x.%04x" 5935/* starting from zero isn't silly enough */ 5936static uint32_t nfs_sillyrename_number = 0x20051025; 5937 5938int 5939nfs_sillyrename( 5940 nfsnode_t dnp, 5941 nfsnode_t np, 5942 struct componentname *cnp, 5943 vfs_context_t ctx) 5944{ 5945 struct nfs_sillyrename *nsp; 5946 int error; 5947 short pid; 5948 kauth_cred_t cred; 5949 uint32_t num; 5950 struct nfsmount *nmp; 5951 5952 nmp = NFSTONMP(dnp); 5953 if (nfs_mount_gone(nmp)) 5954 return (ENXIO); 5955 5956 nfs_name_cache_purge(dnp, np, cnp, ctx); 5957 5958 MALLOC_ZONE(nsp, struct nfs_sillyrename *, 5959 sizeof (struct nfs_sillyrename), M_NFSREQ, M_WAITOK); 5960 if (!nsp) 5961 return (ENOMEM); 5962 cred = vfs_context_ucred(ctx); 5963 kauth_cred_ref(cred); 5964 nsp->nsr_cred = cred; 5965 nsp->nsr_dnp = dnp; 5966 error = vnode_ref(NFSTOV(dnp)); 5967 if (error) 5968 goto bad_norele; 5969 5970 /* Fudge together a funny name */ 5971 pid = vfs_context_pid(ctx); 5972 num = OSAddAtomic(1, &nfs_sillyrename_number); 5973 nsp->nsr_namlen = snprintf(nsp->nsr_name, sizeof(nsp->nsr_name), 5974 NFS_SILLYNAME_FORMAT, num, (pid & 0xffff)); 5975 if (nsp->nsr_namlen >= (int)sizeof(nsp->nsr_name)) 5976 nsp->nsr_namlen = sizeof(nsp->nsr_name) - 1; 5977 5978 /* Try lookitups until we get one that isn't there */ 5979 while (nfs_lookitup(dnp, nsp->nsr_name, nsp->nsr_namlen, ctx, NULL) == 0) { 5980 num = OSAddAtomic(1, &nfs_sillyrename_number); 5981 nsp->nsr_namlen = snprintf(nsp->nsr_name, sizeof(nsp->nsr_name), 5982 NFS_SILLYNAME_FORMAT, num, (pid & 0xffff)); 5983 if (nsp->nsr_namlen >= (int)sizeof(nsp->nsr_name)) 5984 nsp->nsr_namlen = sizeof(nsp->nsr_name) - 1; 5985 } 5986 5987 /* now, do the rename */ 5988 error = nmp->nm_funcs->nf_rename_rpc(dnp, cnp->cn_nameptr, cnp->cn_namelen, 5989 dnp, nsp->nsr_name, nsp->nsr_namlen, ctx); 5990 5991 /* Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. */ 5992 if (error == ENOENT) 5993 error = 0; 5994 if (!error) { 5995 nfs_node_lock_force(dnp); 5996 if (dnp->n_flag & NNEGNCENTRIES) { 5997 dnp->n_flag &= ~NNEGNCENTRIES; 5998 cache_purge_negatives(NFSTOV(dnp)); 5999 } 6000 nfs_node_unlock(dnp); 6001 } 6002 FSDBG(267, dnp, np, num, error); 6003 if (error) 6004 goto bad; 6005 error = nfs_lookitup(dnp, nsp->nsr_name, nsp->nsr_namlen, ctx, &np); 6006 nfs_node_lock_force(np); 6007 np->n_sillyrename = nsp; 6008 nfs_node_unlock(np); 6009 return (0); 6010bad: 6011 vnode_rele(NFSTOV(dnp)); 6012bad_norele: 6013 nsp->nsr_cred = NOCRED; 6014 kauth_cred_unref(&cred); 6015 FREE_ZONE(nsp, sizeof(*nsp), M_NFSREQ); 6016 return (error); 6017} 6018 6019int 6020nfs3_lookup_rpc_async( 6021 nfsnode_t dnp, 6022 char *name, 6023 int namelen, 6024 vfs_context_t ctx, 6025 struct nfsreq **reqp) 6026{ 6027 struct nfsmount *nmp; 6028 struct nfsm_chain nmreq; 6029 int error = 0, nfsvers; 6030 6031 nmp = NFSTONMP(dnp); 6032 if (nfs_mount_gone(nmp)) 6033 return (ENXIO); 6034 nfsvers = nmp->nm_vers; 6035 6036 nfsm_chain_null(&nmreq); 6037 6038 nfsm_chain_build_alloc_init(error, &nmreq, 6039 NFSX_FH(nfsvers) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 6040 nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize); 6041 nfsm_chain_add_name(error, &nmreq, name, namelen, nmp); 6042 nfsm_chain_build_done(error, &nmreq); 6043 nfsmout_if(error); 6044 error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_LOOKUP, 6045 vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, reqp); 6046nfsmout: 6047 nfsm_chain_cleanup(&nmreq); 6048 return (error); 6049} 6050 6051int 6052nfs3_lookup_rpc_async_finish( 6053 nfsnode_t dnp, 6054 __unused char *name, 6055 __unused int namelen, 6056 vfs_context_t ctx, 6057 struct nfsreq *req, 6058 u_int64_t *xidp, 6059 fhandle_t *fhp, 6060 struct nfs_vattr *nvap) 6061{ 6062 int error = 0, lockerror = ENOENT, status, nfsvers, attrflag; 6063 u_int64_t xid; 6064 struct nfsmount *nmp; 6065 struct nfsm_chain nmrep; 6066 6067 nmp = NFSTONMP(dnp); 6068 nfsvers = nmp->nm_vers; 6069 6070 nfsm_chain_null(&nmrep); 6071 6072 error = nfs_request_async_finish(req, &nmrep, xidp, &status); 6073 6074 if ((lockerror = nfs_node_lock(dnp))) 6075 error = lockerror; 6076 xid = *xidp; 6077 if (error || status) { 6078 if (nfsvers == NFS_VER3) 6079 nfsm_chain_postop_attr_update(error, &nmrep, dnp, &xid); 6080 if (!error) 6081 error = status; 6082 goto nfsmout; 6083 } 6084 6085 nfsmout_if(error || !fhp || !nvap); 6086 6087 /* get the file handle */ 6088 nfsm_chain_get_fh(error, &nmrep, nfsvers, fhp); 6089 6090 /* get the attributes */ 6091 if (nfsvers == NFS_VER3) { 6092 nfsm_chain_postop_attr_get(error, &nmrep, attrflag, nvap); 6093 nfsm_chain_postop_attr_update(error, &nmrep, dnp, &xid); 6094 if (!error && !attrflag) 6095 error = nfs3_getattr_rpc(NULL, NFSTOMP(dnp), fhp->fh_data, fhp->fh_len, 0, ctx, nvap, xidp); 6096 } else { 6097 error = nfs_parsefattr(&nmrep, nfsvers, nvap); 6098 } 6099nfsmout: 6100 if (!lockerror) 6101 nfs_node_unlock(dnp); 6102 nfsm_chain_cleanup(&nmrep); 6103 return (error); 6104} 6105 6106/* 6107 * Look up a file name and optionally either update the file handle or 6108 * allocate an nfsnode, depending on the value of npp. 6109 * npp == NULL --> just do the lookup 6110 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 6111 * handled too 6112 * *npp != NULL --> update the file handle in the vnode 6113 */ 6114int 6115nfs_lookitup( 6116 nfsnode_t dnp, 6117 char *name, 6118 int namelen, 6119 vfs_context_t ctx, 6120 nfsnode_t *npp) 6121{ 6122 int error = 0; 6123 nfsnode_t np, newnp = NULL; 6124 u_int64_t xid; 6125 fhandle_t fh; 6126 struct nfsmount *nmp; 6127 struct nfs_vattr nvattr; 6128 struct nfsreq rq, *req = &rq; 6129 6130 nmp = NFSTONMP(dnp); 6131 if (nfs_mount_gone(nmp)) 6132 return (ENXIO); 6133 6134 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME) && 6135 (namelen > (int)nmp->nm_fsattr.nfsa_maxname)) 6136 return (ENAMETOOLONG); 6137 6138 NVATTR_INIT(&nvattr); 6139 6140 /* check for lookup of "." */ 6141 if ((name[0] == '.') && (namelen == 1)) { 6142 /* skip lookup, we know who we are */ 6143 fh.fh_len = 0; 6144 newnp = dnp; 6145 goto nfsmout; 6146 } 6147 6148 error = nmp->nm_funcs->nf_lookup_rpc_async(dnp, name, namelen, ctx, &req); 6149 nfsmout_if(error); 6150 error = nmp->nm_funcs->nf_lookup_rpc_async_finish(dnp, name, namelen, ctx, req, &xid, &fh, &nvattr); 6151 nfsmout_if(!npp || error); 6152 6153 if (*npp) { 6154 np = *npp; 6155 if (fh.fh_len != np->n_fhsize) { 6156 u_char *oldbuf = (np->n_fhsize > NFS_SMALLFH) ? np->n_fhp : NULL; 6157 if (fh.fh_len > NFS_SMALLFH) { 6158 MALLOC_ZONE(np->n_fhp, u_char *, fh.fh_len, M_NFSBIGFH, M_WAITOK); 6159 if (!np->n_fhp) { 6160 np->n_fhp = oldbuf; 6161 error = ENOMEM; 6162 goto nfsmout; 6163 } 6164 } else { 6165 np->n_fhp = &np->n_fh[0]; 6166 } 6167 if (oldbuf) 6168 FREE_ZONE(oldbuf, np->n_fhsize, M_NFSBIGFH); 6169 } 6170 bcopy(fh.fh_data, np->n_fhp, fh.fh_len); 6171 np->n_fhsize = fh.fh_len; 6172 nfs_node_lock_force(np); 6173 error = nfs_loadattrcache(np, &nvattr, &xid, 0); 6174 nfs_node_unlock(np); 6175 nfsmout_if(error); 6176 newnp = np; 6177 } else if (NFS_CMPFH(dnp, fh.fh_data, fh.fh_len)) { 6178 nfs_node_lock_force(dnp); 6179 if (dnp->n_xid <= xid) 6180 error = nfs_loadattrcache(dnp, &nvattr, &xid, 0); 6181 nfs_node_unlock(dnp); 6182 nfsmout_if(error); 6183 newnp = dnp; 6184 } else { 6185 struct componentname cn, *cnp = &cn; 6186 bzero(cnp, sizeof(*cnp)); 6187 cnp->cn_nameptr = name; 6188 cnp->cn_namelen = namelen; 6189 error = nfs_nget(NFSTOMP(dnp), dnp, cnp, fh.fh_data, fh.fh_len, 6190 &nvattr, &xid, rq.r_auth, NG_MAKEENTRY, &np); 6191 nfsmout_if(error); 6192 newnp = np; 6193 } 6194 6195nfsmout: 6196 if (npp && !*npp && !error) 6197 *npp = newnp; 6198 NVATTR_CLEANUP(&nvattr); 6199 return (error); 6200} 6201 6202/* 6203 * set up and initialize a "._" file lookup structure used for 6204 * performing async lookups. 6205 */ 6206void 6207nfs_dulookup_init(struct nfs_dulookup *dulp, nfsnode_t dnp, const char *name, int namelen, vfs_context_t ctx) 6208{ 6209 int error, du_namelen; 6210 vnode_t du_vp; 6211 struct nfsmount *nmp = NFSTONMP(dnp); 6212 6213 /* check for ._ file in name cache */ 6214 dulp->du_flags = 0; 6215 bzero(&dulp->du_cn, sizeof(dulp->du_cn)); 6216 du_namelen = namelen + 2; 6217 if (!nmp || NMFLAG(nmp, NONEGNAMECACHE)) 6218 return; 6219 if ((namelen >= 2) && (name[0] == '.') && (name[1] == '_')) 6220 return; 6221 if (du_namelen >= (int)sizeof(dulp->du_smallname)) 6222 MALLOC(dulp->du_cn.cn_nameptr, char *, du_namelen + 1, M_TEMP, M_WAITOK); 6223 else 6224 dulp->du_cn.cn_nameptr = dulp->du_smallname; 6225 if (!dulp->du_cn.cn_nameptr) 6226 return; 6227 dulp->du_cn.cn_namelen = du_namelen; 6228 snprintf(dulp->du_cn.cn_nameptr, du_namelen + 1, "._%s", name); 6229 dulp->du_cn.cn_nameptr[du_namelen] = '\0'; 6230 dulp->du_cn.cn_nameiop = LOOKUP; 6231 dulp->du_cn.cn_flags = MAKEENTRY; 6232 6233 error = cache_lookup(NFSTOV(dnp), &du_vp, &dulp->du_cn); 6234 if (error == -1) { 6235 vnode_put(du_vp); 6236 } else if (!error) { 6237 nmp = NFSTONMP(dnp); 6238 if (nmp && (nmp->nm_vers > NFS_VER2) && NMFLAG(nmp, RDIRPLUS)) { 6239 /* if rdirplus, try dir buf cache lookup */ 6240 nfsnode_t du_np = NULL; 6241 if (!nfs_dir_buf_cache_lookup(dnp, &du_np, &dulp->du_cn, ctx, 0) && du_np) { 6242 /* dir buf cache hit */ 6243 du_vp = NFSTOV(du_np); 6244 vnode_put(du_vp); 6245 error = -1; 6246 } 6247 } 6248 if (!error) 6249 dulp->du_flags |= NFS_DULOOKUP_DOIT; 6250 } 6251} 6252 6253/* 6254 * start an async "._" file lookup request 6255 */ 6256void 6257nfs_dulookup_start(struct nfs_dulookup *dulp, nfsnode_t dnp, vfs_context_t ctx) 6258{ 6259 struct nfsmount *nmp = NFSTONMP(dnp); 6260 struct nfsreq *req = &dulp->du_req; 6261 6262 if (!nmp || !(dulp->du_flags & NFS_DULOOKUP_DOIT) || (dulp->du_flags & NFS_DULOOKUP_INPROG)) 6263 return; 6264 if (!nmp->nm_funcs->nf_lookup_rpc_async(dnp, dulp->du_cn.cn_nameptr, 6265 dulp->du_cn.cn_namelen, ctx, &req)) 6266 dulp->du_flags |= NFS_DULOOKUP_INPROG; 6267} 6268 6269/* 6270 * finish an async "._" file lookup request and clean up the structure 6271 */ 6272void 6273nfs_dulookup_finish(struct nfs_dulookup *dulp, nfsnode_t dnp, vfs_context_t ctx) 6274{ 6275 struct nfsmount *nmp = NFSTONMP(dnp); 6276 int error; 6277 nfsnode_t du_np; 6278 u_int64_t xid; 6279 fhandle_t fh; 6280 struct nfs_vattr nvattr; 6281 6282 if (!nmp || !(dulp->du_flags & NFS_DULOOKUP_INPROG)) 6283 goto out; 6284 6285 NVATTR_INIT(&nvattr); 6286 error = nmp->nm_funcs->nf_lookup_rpc_async_finish(dnp, dulp->du_cn.cn_nameptr, 6287 dulp->du_cn.cn_namelen, ctx, &dulp->du_req, &xid, &fh, &nvattr); 6288 dulp->du_flags &= ~NFS_DULOOKUP_INPROG; 6289 if (error == ENOENT) { 6290 /* add a negative entry in the name cache */ 6291 nfs_node_lock_force(dnp); 6292 cache_enter(NFSTOV(dnp), NULL, &dulp->du_cn); 6293 dnp->n_flag |= NNEGNCENTRIES; 6294 nfs_node_unlock(dnp); 6295 } else if (!error) { 6296 error = nfs_nget(NFSTOMP(dnp), dnp, &dulp->du_cn, fh.fh_data, fh.fh_len, 6297 &nvattr, &xid, dulp->du_req.r_auth, NG_MAKEENTRY, &du_np); 6298 if (!error) { 6299 nfs_node_unlock(du_np); 6300 vnode_put(NFSTOV(du_np)); 6301 } 6302 } 6303 NVATTR_CLEANUP(&nvattr); 6304out: 6305 if (dulp->du_flags & NFS_DULOOKUP_INPROG) 6306 nfs_request_async_cancel(&dulp->du_req); 6307 if (dulp->du_cn.cn_nameptr && (dulp->du_cn.cn_nameptr != dulp->du_smallname)) 6308 FREE(dulp->du_cn.cn_nameptr, M_TEMP); 6309} 6310 6311 6312/* 6313 * NFS Version 3 commit RPC 6314 */ 6315int 6316nfs3_commit_rpc( 6317 nfsnode_t np, 6318 uint64_t offset, 6319 uint64_t count, 6320 kauth_cred_t cred, 6321 uint64_t wverf) 6322{ 6323 struct nfsmount *nmp; 6324 int error = 0, lockerror, status, wccpostattr = 0, nfsvers; 6325 struct timespec premtime = { 0, 0 }; 6326 u_int64_t xid, newwverf; 6327 uint32_t count32; 6328 struct nfsm_chain nmreq, nmrep; 6329 6330 nmp = NFSTONMP(np); 6331 FSDBG(521, np, offset, count, nmp ? nmp->nm_state : 0); 6332 if (nfs_mount_gone(nmp)) 6333 return (ENXIO); 6334 if (!(nmp->nm_state & NFSSTA_HASWRITEVERF)) 6335 return (0); 6336 nfsvers = nmp->nm_vers; 6337 6338 if (count > UINT32_MAX) 6339 count32 = 0; 6340 else 6341 count32 = count; 6342 6343 nfsm_chain_null(&nmreq); 6344 nfsm_chain_null(&nmrep); 6345 6346 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(NFS_VER3)); 6347 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 6348 nfsm_chain_add_64(error, &nmreq, offset); 6349 nfsm_chain_add_32(error, &nmreq, count32); 6350 nfsm_chain_build_done(error, &nmreq); 6351 nfsmout_if(error); 6352 error = nfs_request2(np, NULL, &nmreq, NFSPROC_COMMIT, 6353 current_thread(), cred, NULL, 0, &nmrep, &xid, &status); 6354 if ((lockerror = nfs_node_lock(np))) 6355 error = lockerror; 6356 /* can we do anything useful with the wcc info? */ 6357 nfsm_chain_get_wcc_data(error, &nmrep, np, &premtime, &wccpostattr, &xid); 6358 if (!lockerror) 6359 nfs_node_unlock(np); 6360 if (!error) 6361 error = status; 6362 nfsm_chain_get_64(error, &nmrep, newwverf); 6363 nfsmout_if(error); 6364 lck_mtx_lock(&nmp->nm_lock); 6365 if (nmp->nm_verf != newwverf) 6366 nmp->nm_verf = newwverf; 6367 if (wverf != newwverf) 6368 error = NFSERR_STALEWRITEVERF; 6369 lck_mtx_unlock(&nmp->nm_lock); 6370nfsmout: 6371 nfsm_chain_cleanup(&nmreq); 6372 nfsm_chain_cleanup(&nmrep); 6373 return (error); 6374} 6375 6376 6377int 6378nfs_vnop_blockmap( 6379 __unused struct vnop_blockmap_args /* { 6380 struct vnodeop_desc *a_desc; 6381 vnode_t a_vp; 6382 off_t a_foffset; 6383 size_t a_size; 6384 daddr64_t *a_bpn; 6385 size_t *a_run; 6386 void *a_poff; 6387 int a_flags; 6388 } */ *ap) 6389{ 6390 return (ENOTSUP); 6391} 6392 6393 6394/* 6395 * fsync vnode op. Just call nfs_flush(). 6396 */ 6397/* ARGSUSED */ 6398int 6399nfs_vnop_fsync( 6400 struct vnop_fsync_args /* { 6401 struct vnodeop_desc *a_desc; 6402 vnode_t a_vp; 6403 int a_waitfor; 6404 vfs_context_t a_context; 6405 } */ *ap) 6406{ 6407 return (nfs_flush(VTONFS(ap->a_vp), ap->a_waitfor, vfs_context_thread(ap->a_context), 0)); 6408} 6409 6410 6411/* 6412 * Do an NFS pathconf RPC. 6413 */ 6414int 6415nfs3_pathconf_rpc( 6416 nfsnode_t np, 6417 struct nfs_fsattr *nfsap, 6418 vfs_context_t ctx) 6419{ 6420 u_int64_t xid; 6421 int error = 0, lockerror, status, nfsvers; 6422 struct nfsm_chain nmreq, nmrep; 6423 struct nfsmount *nmp = NFSTONMP(np); 6424 uint32_t val = 0; 6425 6426 if (nfs_mount_gone(nmp)) 6427 return (ENXIO); 6428 nfsvers = nmp->nm_vers; 6429 6430 nfsm_chain_null(&nmreq); 6431 nfsm_chain_null(&nmrep); 6432 6433 /* fetch pathconf info from server */ 6434 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(NFS_VER3)); 6435 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 6436 nfsm_chain_build_done(error, &nmreq); 6437 nfsmout_if(error); 6438 error = nfs_request(np, NULL, &nmreq, NFSPROC_PATHCONF, ctx, NULL, &nmrep, &xid, &status); 6439 if ((lockerror = nfs_node_lock(np))) 6440 error = lockerror; 6441 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 6442 if (!lockerror) 6443 nfs_node_unlock(np); 6444 if (!error) 6445 error = status; 6446 nfsm_chain_get_32(error, &nmrep, nfsap->nfsa_maxlink); 6447 nfsm_chain_get_32(error, &nmrep, nfsap->nfsa_maxname); 6448 nfsap->nfsa_flags &= ~(NFS_FSFLAG_NO_TRUNC|NFS_FSFLAG_CHOWN_RESTRICTED|NFS_FSFLAG_CASE_INSENSITIVE|NFS_FSFLAG_CASE_PRESERVING); 6449 nfsm_chain_get_32(error, &nmrep, val); 6450 if (val) 6451 nfsap->nfsa_flags |= NFS_FSFLAG_NO_TRUNC; 6452 nfsm_chain_get_32(error, &nmrep, val); 6453 if (val) 6454 nfsap->nfsa_flags |= NFS_FSFLAG_CHOWN_RESTRICTED; 6455 nfsm_chain_get_32(error, &nmrep, val); 6456 if (val) 6457 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_INSENSITIVE; 6458 nfsm_chain_get_32(error, &nmrep, val); 6459 if (val) 6460 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_PRESERVING; 6461 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_MAXLINK); 6462 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_MAXNAME); 6463 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_NO_TRUNC); 6464 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_CHOWN_RESTRICTED); 6465 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE); 6466 NFS_BITMAP_SET(nfsap->nfsa_bitmap, NFS_FATTR_CASE_PRESERVING); 6467nfsmout: 6468 nfsm_chain_cleanup(&nmreq); 6469 nfsm_chain_cleanup(&nmrep); 6470 return (error); 6471} 6472 6473/* save pathconf info for NFSv3 mount */ 6474void 6475nfs3_pathconf_cache(struct nfsmount *nmp, struct nfs_fsattr *nfsap) 6476{ 6477 nmp->nm_fsattr.nfsa_maxlink = nfsap->nfsa_maxlink; 6478 nmp->nm_fsattr.nfsa_maxname = nfsap->nfsa_maxname; 6479 nmp->nm_fsattr.nfsa_flags &= ~(NFS_FSFLAG_NO_TRUNC|NFS_FSFLAG_CHOWN_RESTRICTED|NFS_FSFLAG_CASE_INSENSITIVE|NFS_FSFLAG_CASE_PRESERVING); 6480 nmp->nm_fsattr.nfsa_flags |= nfsap->nfsa_flags & NFS_FSFLAG_NO_TRUNC; 6481 nmp->nm_fsattr.nfsa_flags |= nfsap->nfsa_flags & NFS_FSFLAG_CHOWN_RESTRICTED; 6482 nmp->nm_fsattr.nfsa_flags |= nfsap->nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE; 6483 nmp->nm_fsattr.nfsa_flags |= nfsap->nfsa_flags & NFS_FSFLAG_CASE_PRESERVING; 6484 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXLINK); 6485 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME); 6486 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_NO_TRUNC); 6487 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CHOWN_RESTRICTED); 6488 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE); 6489 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_PRESERVING); 6490 nmp->nm_state |= NFSSTA_GOTPATHCONF; 6491} 6492 6493/* 6494 * Return POSIX pathconf information applicable to nfs. 6495 * 6496 * The NFS V2 protocol doesn't support this, so just return EINVAL 6497 * for V2. 6498 */ 6499/* ARGSUSED */ 6500int 6501nfs_vnop_pathconf( 6502 struct vnop_pathconf_args /* { 6503 struct vnodeop_desc *a_desc; 6504 vnode_t a_vp; 6505 int a_name; 6506 int32_t *a_retval; 6507 vfs_context_t a_context; 6508 } */ *ap) 6509{ 6510 vnode_t vp = ap->a_vp; 6511 nfsnode_t np = VTONFS(vp); 6512 struct nfsmount *nmp; 6513 struct nfs_fsattr nfsa, *nfsap; 6514 int error = 0; 6515 uint64_t maxFileSize; 6516 uint nbits; 6517 6518 nmp = VTONMP(vp); 6519 if (nfs_mount_gone(nmp)) 6520 return (ENXIO); 6521 6522 switch (ap->a_name) { 6523 case _PC_LINK_MAX: 6524 case _PC_NAME_MAX: 6525 case _PC_CHOWN_RESTRICTED: 6526 case _PC_NO_TRUNC: 6527 case _PC_CASE_SENSITIVE: 6528 case _PC_CASE_PRESERVING: 6529 break; 6530 case _PC_FILESIZEBITS: 6531 if (nmp->nm_vers == NFS_VER2) { 6532 *ap->a_retval = 32; 6533 return (0); 6534 } 6535 break; 6536 case _PC_XATTR_SIZE_BITS: 6537 /* Do we support xattrs natively? */ 6538 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR) 6539 break; /* Yes */ 6540 /* No... so just return an error */ 6541 /* FALLTHROUGH */ 6542 default: 6543 /* don't bother contacting the server if we know the answer */ 6544 return (EINVAL); 6545 } 6546 6547 if (nmp->nm_vers == NFS_VER2) 6548 return (EINVAL); 6549 6550 lck_mtx_lock(&nmp->nm_lock); 6551 if (nmp->nm_vers == NFS_VER3) { 6552 if (!(nmp->nm_state & NFSSTA_GOTPATHCONF)) { 6553 /* no pathconf info cached */ 6554 lck_mtx_unlock(&nmp->nm_lock); 6555 NFS_CLEAR_ATTRIBUTES(nfsa.nfsa_bitmap); 6556 error = nfs3_pathconf_rpc(np, &nfsa, ap->a_context); 6557 if (error) 6558 return (error); 6559 nmp = VTONMP(vp); 6560 if (nfs_mount_gone(nmp)) 6561 return (ENXIO); 6562 lck_mtx_lock(&nmp->nm_lock); 6563 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS) { 6564 /* all files have the same pathconf info, */ 6565 /* so cache a copy of the results */ 6566 nfs3_pathconf_cache(nmp, &nfsa); 6567 } 6568 nfsap = &nfsa; 6569 } else { 6570 nfsap = &nmp->nm_fsattr; 6571 } 6572 } else if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) { 6573 /* no pathconf info cached */ 6574 lck_mtx_unlock(&nmp->nm_lock); 6575 NFS_CLEAR_ATTRIBUTES(nfsa.nfsa_bitmap); 6576 error = nfs4_pathconf_rpc(np, &nfsa, ap->a_context); 6577 if (error) 6578 return (error); 6579 nmp = VTONMP(vp); 6580 if (nfs_mount_gone(nmp)) 6581 return (ENXIO); 6582 lck_mtx_lock(&nmp->nm_lock); 6583 nfsap = &nfsa; 6584 } else { 6585 nfsap = &nmp->nm_fsattr; 6586 } 6587 6588 switch (ap->a_name) { 6589 case _PC_LINK_MAX: 6590 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_MAXLINK)) 6591 *ap->a_retval = nfsap->nfsa_maxlink; 6592 else if ((nmp->nm_vers == NFS_VER4) && NFS_BITMAP_ISSET(np->n_vattr.nva_bitmap, NFS_FATTR_MAXLINK)) 6593 *ap->a_retval = np->n_vattr.nva_maxlink; 6594 else 6595 error = EINVAL; 6596 break; 6597 case _PC_NAME_MAX: 6598 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_MAXNAME)) 6599 *ap->a_retval = nfsap->nfsa_maxname; 6600 else 6601 error = EINVAL; 6602 break; 6603 case _PC_CHOWN_RESTRICTED: 6604 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_CHOWN_RESTRICTED)) 6605 *ap->a_retval = (nfsap->nfsa_flags & NFS_FSFLAG_CHOWN_RESTRICTED) ? 200112 /* _POSIX_CHOWN_RESTRICTED */ : 0; 6606 else 6607 error = EINVAL; 6608 break; 6609 case _PC_NO_TRUNC: 6610 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_NO_TRUNC)) 6611 *ap->a_retval = (nfsap->nfsa_flags & NFS_FSFLAG_NO_TRUNC) ? 200112 /* _POSIX_NO_TRUNC */ : 0; 6612 else 6613 error = EINVAL; 6614 break; 6615 case _PC_CASE_SENSITIVE: 6616 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE)) 6617 *ap->a_retval = (nfsap->nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE) ? 0 : 1; 6618 else 6619 error = EINVAL; 6620 break; 6621 case _PC_CASE_PRESERVING: 6622 if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_CASE_PRESERVING)) 6623 *ap->a_retval = (nfsap->nfsa_flags & NFS_FSFLAG_CASE_PRESERVING) ? 1 : 0; 6624 else 6625 error = EINVAL; 6626 break; 6627 case _PC_XATTR_SIZE_BITS: /* same as file size bits if named attrs supported */ 6628 case _PC_FILESIZEBITS: 6629 if (!NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) { 6630 *ap->a_retval = 64; 6631 error = 0; 6632 break; 6633 } 6634 maxFileSize = nfsap->nfsa_maxfilesize; 6635 nbits = 1; 6636 if (maxFileSize & 0xffffffff00000000ULL) { 6637 nbits += 32; 6638 maxFileSize >>= 32; 6639 } 6640 if (maxFileSize & 0xffff0000) { 6641 nbits += 16; 6642 maxFileSize >>= 16; 6643 } 6644 if (maxFileSize & 0xff00) { 6645 nbits += 8; 6646 maxFileSize >>= 8; 6647 } 6648 if (maxFileSize & 0xf0) { 6649 nbits += 4; 6650 maxFileSize >>= 4; 6651 } 6652 if (maxFileSize & 0xc) { 6653 nbits += 2; 6654 maxFileSize >>= 2; 6655 } 6656 if (maxFileSize & 0x2) { 6657 nbits += 1; 6658 } 6659 *ap->a_retval = nbits; 6660 break; 6661 default: 6662 error = EINVAL; 6663 } 6664 6665 lck_mtx_unlock(&nmp->nm_lock); 6666 6667 return (error); 6668} 6669 6670/* 6671 * Read wrapper for special devices. 6672 */ 6673int 6674nfsspec_vnop_read( 6675 struct vnop_read_args /* { 6676 struct vnodeop_desc *a_desc; 6677 vnode_t a_vp; 6678 struct uio *a_uio; 6679 int a_ioflag; 6680 vfs_context_t a_context; 6681 } */ *ap) 6682{ 6683 nfsnode_t np = VTONFS(ap->a_vp); 6684 struct timeval now; 6685 int error; 6686 6687 /* 6688 * Set access flag. 6689 */ 6690 if ((error = nfs_node_lock(np))) 6691 return (error); 6692 np->n_flag |= NACC; 6693 microtime(&now); 6694 np->n_atim.tv_sec = now.tv_sec; 6695 np->n_atim.tv_nsec = now.tv_usec * 1000; 6696 nfs_node_unlock(np); 6697 return (VOCALL(spec_vnodeop_p, VOFFSET(vnop_read), ap)); 6698} 6699 6700/* 6701 * Write wrapper for special devices. 6702 */ 6703int 6704nfsspec_vnop_write( 6705 struct vnop_write_args /* { 6706 struct vnodeop_desc *a_desc; 6707 vnode_t a_vp; 6708 struct uio *a_uio; 6709 int a_ioflag; 6710 vfs_context_t a_context; 6711 } */ *ap) 6712{ 6713 nfsnode_t np = VTONFS(ap->a_vp); 6714 struct timeval now; 6715 int error; 6716 6717 /* 6718 * Set update flag. 6719 */ 6720 if ((error = nfs_node_lock(np))) 6721 return (error); 6722 np->n_flag |= NUPD; 6723 microtime(&now); 6724 np->n_mtim.tv_sec = now.tv_sec; 6725 np->n_mtim.tv_nsec = now.tv_usec * 1000; 6726 nfs_node_unlock(np); 6727 return (VOCALL(spec_vnodeop_p, VOFFSET(vnop_write), ap)); 6728} 6729 6730/* 6731 * Close wrapper for special devices. 6732 * 6733 * Update the times on the nfsnode then do device close. 6734 */ 6735int 6736nfsspec_vnop_close( 6737 struct vnop_close_args /* { 6738 struct vnodeop_desc *a_desc; 6739 vnode_t a_vp; 6740 int a_fflag; 6741 vfs_context_t a_context; 6742 } */ *ap) 6743{ 6744 vnode_t vp = ap->a_vp; 6745 nfsnode_t np = VTONFS(vp); 6746 struct vnode_attr vattr; 6747 mount_t mp; 6748 int error; 6749 6750 if ((error = nfs_node_lock(np))) 6751 return (error); 6752 if (np->n_flag & (NACC | NUPD)) { 6753 np->n_flag |= NCHG; 6754 if (!vnode_isinuse(vp, 0) && (mp = vnode_mount(vp)) && !vfs_isrdonly(mp)) { 6755 VATTR_INIT(&vattr); 6756 if (np->n_flag & NACC) { 6757 vattr.va_access_time = np->n_atim; 6758 VATTR_SET_ACTIVE(&vattr, va_access_time); 6759 } 6760 if (np->n_flag & NUPD) { 6761 vattr.va_modify_time = np->n_mtim; 6762 VATTR_SET_ACTIVE(&vattr, va_modify_time); 6763 } 6764 nfs_node_unlock(np); 6765 vnode_setattr(vp, &vattr, ap->a_context); 6766 } else { 6767 nfs_node_unlock(np); 6768 } 6769 } else { 6770 nfs_node_unlock(np); 6771 } 6772 return (VOCALL(spec_vnodeop_p, VOFFSET(vnop_close), ap)); 6773} 6774 6775#if FIFO 6776extern vnop_t **fifo_vnodeop_p; 6777 6778/* 6779 * Read wrapper for fifos. 6780 */ 6781int 6782nfsfifo_vnop_read( 6783 struct vnop_read_args /* { 6784 struct vnodeop_desc *a_desc; 6785 vnode_t a_vp; 6786 struct uio *a_uio; 6787 int a_ioflag; 6788 vfs_context_t a_context; 6789 } */ *ap) 6790{ 6791 nfsnode_t np = VTONFS(ap->a_vp); 6792 struct timeval now; 6793 int error; 6794 6795 /* 6796 * Set access flag. 6797 */ 6798 if ((error = nfs_node_lock(np))) 6799 return (error); 6800 np->n_flag |= NACC; 6801 microtime(&now); 6802 np->n_atim.tv_sec = now.tv_sec; 6803 np->n_atim.tv_nsec = now.tv_usec * 1000; 6804 nfs_node_unlock(np); 6805 return (VOCALL(fifo_vnodeop_p, VOFFSET(vnop_read), ap)); 6806} 6807 6808/* 6809 * Write wrapper for fifos. 6810 */ 6811int 6812nfsfifo_vnop_write( 6813 struct vnop_write_args /* { 6814 struct vnodeop_desc *a_desc; 6815 vnode_t a_vp; 6816 struct uio *a_uio; 6817 int a_ioflag; 6818 vfs_context_t a_context; 6819 } */ *ap) 6820{ 6821 nfsnode_t np = VTONFS(ap->a_vp); 6822 struct timeval now; 6823 int error; 6824 6825 /* 6826 * Set update flag. 6827 */ 6828 if ((error = nfs_node_lock(np))) 6829 return (error); 6830 np->n_flag |= NUPD; 6831 microtime(&now); 6832 np->n_mtim.tv_sec = now.tv_sec; 6833 np->n_mtim.tv_nsec = now.tv_usec * 1000; 6834 nfs_node_unlock(np); 6835 return (VOCALL(fifo_vnodeop_p, VOFFSET(vnop_write), ap)); 6836} 6837 6838/* 6839 * Close wrapper for fifos. 6840 * 6841 * Update the times on the nfsnode then do fifo close. 6842 */ 6843int 6844nfsfifo_vnop_close( 6845 struct vnop_close_args /* { 6846 struct vnodeop_desc *a_desc; 6847 vnode_t a_vp; 6848 int a_fflag; 6849 vfs_context_t a_context; 6850 } */ *ap) 6851{ 6852 vnode_t vp = ap->a_vp; 6853 nfsnode_t np = VTONFS(vp); 6854 struct vnode_attr vattr; 6855 struct timeval now; 6856 mount_t mp; 6857 int error; 6858 6859 if ((error = nfs_node_lock(np))) 6860 return (error); 6861 if (np->n_flag & (NACC | NUPD)) { 6862 microtime(&now); 6863 if (np->n_flag & NACC) { 6864 np->n_atim.tv_sec = now.tv_sec; 6865 np->n_atim.tv_nsec = now.tv_usec * 1000; 6866 } 6867 if (np->n_flag & NUPD) { 6868 np->n_mtim.tv_sec = now.tv_sec; 6869 np->n_mtim.tv_nsec = now.tv_usec * 1000; 6870 } 6871 np->n_flag |= NCHG; 6872 if (!vnode_isinuse(vp, 1) && (mp = vnode_mount(vp)) && !vfs_isrdonly(mp)) { 6873 VATTR_INIT(&vattr); 6874 if (np->n_flag & NACC) { 6875 vattr.va_access_time = np->n_atim; 6876 VATTR_SET_ACTIVE(&vattr, va_access_time); 6877 } 6878 if (np->n_flag & NUPD) { 6879 vattr.va_modify_time = np->n_mtim; 6880 VATTR_SET_ACTIVE(&vattr, va_modify_time); 6881 } 6882 nfs_node_unlock(np); 6883 vnode_setattr(vp, &vattr, ap->a_context); 6884 } else { 6885 nfs_node_unlock(np); 6886 } 6887 } else { 6888 nfs_node_unlock(np); 6889 } 6890 return (VOCALL(fifo_vnodeop_p, VOFFSET(vnop_close), ap)); 6891} 6892#endif /* FIFO */ 6893 6894/*ARGSUSED*/ 6895int 6896nfs_vnop_ioctl( 6897 struct vnop_ioctl_args /* { 6898 struct vnodeop_desc *a_desc; 6899 vnode_t a_vp; 6900 u_int32_t a_command; 6901 caddr_t a_data; 6902 int a_fflag; 6903 vfs_context_t a_context; 6904 } */ *ap) 6905{ 6906 vfs_context_t ctx = ap->a_context; 6907 vnode_t vp = ap->a_vp; 6908 struct nfsmount *mp = VTONMP(vp); 6909 int error = ENOTTY; 6910 6911 if (mp == NULL) 6912 return (ENXIO); 6913 6914 switch (ap->a_command) { 6915 6916 case F_FULLFSYNC: 6917 if (vnode_vfsisrdonly(vp)) 6918 return (EROFS); 6919 error = nfs_flush(VTONFS(vp), MNT_WAIT, vfs_context_thread(ctx), 0); 6920 break; 6921 case NFS_FSCTL_DESTROY_CRED: 6922 error = nfs_gss_clnt_ctx_remove(mp, vfs_context_ucred(ctx)); 6923 break; 6924 } 6925 6926 return (error); 6927} 6928 6929/*ARGSUSED*/ 6930int 6931nfs_vnop_select( 6932 __unused struct vnop_select_args /* { 6933 struct vnodeop_desc *a_desc; 6934 vnode_t a_vp; 6935 int a_which; 6936 int a_fflags; 6937 void *a_wql; 6938 vfs_context_t a_context; 6939 } */ *ap) 6940{ 6941 6942 /* 6943 * We were once bogusly seltrue() which returns 1. Is this right? 6944 */ 6945 return (1); 6946} 6947 6948/* 6949 * vnode OP for pagein using UPL 6950 * 6951 * No buffer I/O, just RPCs straight into the mapped pages. 6952 */ 6953int 6954nfs_vnop_pagein( 6955 struct vnop_pagein_args /* { 6956 struct vnodeop_desc *a_desc; 6957 vnode_t a_vp; 6958 upl_t a_pl; 6959 vm_offset_t a_pl_offset; 6960 off_t a_f_offset; 6961 size_t a_size; 6962 int a_flags; 6963 vfs_context_t a_context; 6964 } */ *ap) 6965{ 6966 vnode_t vp = ap->a_vp; 6967 upl_t pl = ap->a_pl; 6968 size_t size = ap->a_size; 6969 off_t f_offset = ap->a_f_offset; 6970 vm_offset_t pl_offset = ap->a_pl_offset; 6971 int flags = ap->a_flags; 6972 thread_t thd; 6973 kauth_cred_t cred; 6974 nfsnode_t np = VTONFS(vp); 6975 size_t nmrsize, iosize, txsize, rxsize, retsize; 6976 off_t txoffset; 6977 struct nfsmount *nmp; 6978 int error = 0; 6979 vm_offset_t ioaddr, rxaddr; 6980 uio_t uio; 6981 char uio_buf [ UIO_SIZEOF(1) ]; 6982 int nofreeupl = flags & UPL_NOCOMMIT; 6983 upl_page_info_t *plinfo; 6984#define MAXPAGINGREQS 16 /* max outstanding RPCs for pagein/pageout */ 6985 struct nfsreq *req[MAXPAGINGREQS]; 6986 int nextsend, nextwait; 6987 uint32_t stategenid = 0, restart = 0; 6988 kern_return_t kret; 6989 6990 FSDBG(322, np, f_offset, size, flags); 6991 if (pl == (upl_t)NULL) 6992 panic("nfs_pagein: no upl"); 6993 6994 if (size <= 0) { 6995 printf("nfs_pagein: invalid size %ld", size); 6996 if (!nofreeupl) 6997 (void) ubc_upl_abort_range(pl, pl_offset, size, 0); 6998 return (EINVAL); 6999 } 7000 if (f_offset < 0 || f_offset >= (off_t)np->n_size || (f_offset & PAGE_MASK_64)) { 7001 if (!nofreeupl) 7002 ubc_upl_abort_range(pl, pl_offset, size, 7003 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); 7004 return (EINVAL); 7005 } 7006 7007 thd = vfs_context_thread(ap->a_context); 7008 cred = ubc_getcred(vp); 7009 if (!IS_VALID_CRED(cred)) 7010 cred = vfs_context_ucred(ap->a_context); 7011 7012 uio = uio_createwithbuffer(1, f_offset, UIO_SYSSPACE, UIO_READ, 7013 &uio_buf, sizeof(uio_buf)); 7014 7015 nmp = VTONMP(vp); 7016 if (nfs_mount_gone(nmp)) { 7017 if (!nofreeupl) 7018 ubc_upl_abort_range(pl, pl_offset, size, 7019 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); 7020 return (ENXIO); 7021 } 7022 nmrsize = nmp->nm_rsize; 7023 7024 plinfo = ubc_upl_pageinfo(pl); 7025 kret = ubc_upl_map(pl, &ioaddr); 7026 if (kret != KERN_SUCCESS) 7027 panic("nfs_vnop_pagein: ubc_upl_map() failed with (%d)", kret); 7028 ioaddr += pl_offset; 7029 7030tryagain: 7031 if (nmp->nm_vers >= NFS_VER4) 7032 stategenid = nmp->nm_stategenid; 7033 txsize = rxsize = size; 7034 txoffset = f_offset; 7035 rxaddr = ioaddr; 7036 7037 bzero(req, sizeof(req)); 7038 nextsend = nextwait = 0; 7039 do { 7040 if (np->n_flag & NREVOKE) { 7041 error = EIO; 7042 break; 7043 } 7044 /* send requests while we need to and have available slots */ 7045 while ((txsize > 0) && (req[nextsend] == NULL)) { 7046 iosize = MIN(nmrsize, txsize); 7047 if ((error = nmp->nm_funcs->nf_read_rpc_async(np, txoffset, iosize, thd, cred, NULL, &req[nextsend]))) { 7048 req[nextsend] = NULL; 7049 break; 7050 } 7051 txoffset += iosize; 7052 txsize -= iosize; 7053 nextsend = (nextsend + 1) % MAXPAGINGREQS; 7054 } 7055 /* wait while we need to and break out if more requests to send */ 7056 while ((rxsize > 0) && req[nextwait]) { 7057 iosize = retsize = MIN(nmrsize, rxsize); 7058 uio_reset(uio, uio_offset(uio), UIO_SYSSPACE, UIO_READ); 7059 uio_addiov(uio, CAST_USER_ADDR_T(rxaddr), iosize); 7060 FSDBG(322, uio_offset(uio), uio_resid(uio), rxaddr, rxsize); 7061#if UPL_DEBUG 7062 upl_ubc_alias_set(pl, (uintptr_t) current_thread(), (uintptr_t) 2); 7063#endif /* UPL_DEBUG */ 7064 OSAddAtomic64(1, &nfsstats.pageins); 7065 error = nmp->nm_funcs->nf_read_rpc_async_finish(np, req[nextwait], uio, &retsize, NULL); 7066 req[nextwait] = NULL; 7067 nextwait = (nextwait + 1) % MAXPAGINGREQS; 7068 if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) { 7069 lck_mtx_lock(&nmp->nm_lock); 7070 if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) { 7071 NP(np, "nfs_vnop_pagein: error %d, initiating recovery", error); 7072 nfs_need_recover(nmp, error); 7073 } 7074 lck_mtx_unlock(&nmp->nm_lock); 7075 restart++; 7076 goto cancel; 7077 } 7078 if (error) { 7079 FSDBG(322, uio_offset(uio), uio_resid(uio), error, -1); 7080 break; 7081 } 7082 if (retsize < iosize) { 7083 /* Just zero fill the rest of the valid area. */ 7084 int zcnt = iosize - retsize; 7085 bzero((char *)rxaddr + retsize, zcnt); 7086 FSDBG(324, uio_offset(uio), retsize, zcnt, rxaddr); 7087 uio_update(uio, zcnt); 7088 } 7089 rxaddr += iosize; 7090 rxsize -= iosize; 7091 if (txsize) 7092 break; 7093 } 7094 } while (!error && (txsize || rxsize)); 7095 7096 restart = 0; 7097 7098 if (error) { 7099cancel: 7100 /* cancel any outstanding requests */ 7101 while (req[nextwait]) { 7102 nfs_request_async_cancel(req[nextwait]); 7103 req[nextwait] = NULL; 7104 nextwait = (nextwait + 1) % MAXPAGINGREQS; 7105 } 7106 if (np->n_flag & NREVOKE) { 7107 error = EIO; 7108 } else if (restart) { 7109 if (restart <= nfs_mount_state_max_restarts(nmp)) { /* guard against no progress */ 7110 if (error == NFSERR_GRACE) 7111 tsleep(&nmp->nm_state, (PZERO-1), "nfsgrace", 2*hz); 7112 if (!(error = nfs_mount_state_wait_for_recovery(nmp))) 7113 goto tryagain; 7114 } else { 7115 NP(np, "nfs_pagein: too many restarts, aborting"); 7116 } 7117 } 7118 } 7119 7120 ubc_upl_unmap(pl); 7121 7122 if (!nofreeupl) { 7123 if (error) 7124 ubc_upl_abort_range(pl, pl_offset, size, 7125 UPL_ABORT_ERROR | 7126 UPL_ABORT_FREE_ON_EMPTY); 7127 else 7128 ubc_upl_commit_range(pl, pl_offset, size, 7129 UPL_COMMIT_CLEAR_DIRTY | 7130 UPL_COMMIT_FREE_ON_EMPTY); 7131 } 7132 return (error); 7133} 7134 7135 7136/* 7137 * the following are needed only by nfs_pageout to know how to handle errors 7138 * see nfs_pageout comments on explanation of actions. 7139 * the errors here are copied from errno.h and errors returned by servers 7140 * are expected to match the same numbers here. If not, our actions maybe 7141 * erroneous. 7142 */ 7143char nfs_pageouterrorhandler(int); 7144enum actiontype {NOACTION, DUMP, DUMPANDLOG, RETRY, SEVER}; 7145#define NFS_ELAST 88 7146static u_char errorcount[NFS_ELAST+1]; /* better be zeros when initialized */ 7147static const char errortooutcome[NFS_ELAST+1] = { 7148 NOACTION, 7149 DUMP, /* EPERM 1 Operation not permitted */ 7150 DUMP, /* ENOENT 2 No such file or directory */ 7151 DUMPANDLOG, /* ESRCH 3 No such process */ 7152 RETRY, /* EINTR 4 Interrupted system call */ 7153 DUMP, /* EIO 5 Input/output error */ 7154 DUMP, /* ENXIO 6 Device not configured */ 7155 DUMPANDLOG, /* E2BIG 7 Argument list too long */ 7156 DUMPANDLOG, /* ENOEXEC 8 Exec format error */ 7157 DUMPANDLOG, /* EBADF 9 Bad file descriptor */ 7158 DUMPANDLOG, /* ECHILD 10 No child processes */ 7159 DUMPANDLOG, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */ 7160 RETRY, /* ENOMEM 12 Cannot allocate memory */ 7161 DUMP, /* EACCES 13 Permission denied */ 7162 DUMPANDLOG, /* EFAULT 14 Bad address */ 7163 DUMPANDLOG, /* ENOTBLK 15 POSIX - Block device required */ 7164 RETRY, /* EBUSY 16 Device busy */ 7165 DUMP, /* EEXIST 17 File exists */ 7166 DUMP, /* EXDEV 18 Cross-device link */ 7167 DUMP, /* ENODEV 19 Operation not supported by device */ 7168 DUMP, /* ENOTDIR 20 Not a directory */ 7169 DUMP, /* EISDIR 21 Is a directory */ 7170 DUMP, /* EINVAL 22 Invalid argument */ 7171 DUMPANDLOG, /* ENFILE 23 Too many open files in system */ 7172 DUMPANDLOG, /* EMFILE 24 Too many open files */ 7173 DUMPANDLOG, /* ENOTTY 25 Inappropriate ioctl for device */ 7174 DUMPANDLOG, /* ETXTBSY 26 Text file busy - POSIX */ 7175 DUMP, /* EFBIG 27 File too large */ 7176 DUMP, /* ENOSPC 28 No space left on device */ 7177 DUMPANDLOG, /* ESPIPE 29 Illegal seek */ 7178 DUMP, /* EROFS 30 Read-only file system */ 7179 DUMP, /* EMLINK 31 Too many links */ 7180 RETRY, /* EPIPE 32 Broken pipe */ 7181 /* math software */ 7182 DUMPANDLOG, /* EDOM 33 Numerical argument out of domain */ 7183 DUMPANDLOG, /* ERANGE 34 Result too large */ 7184 RETRY, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */ 7185 DUMPANDLOG, /* EINPROGRESS 36 Operation now in progress */ 7186 DUMPANDLOG, /* EALREADY 37 Operation already in progress */ 7187 /* ipc/network software -- argument errors */ 7188 DUMPANDLOG, /* ENOTSOC 38 Socket operation on non-socket */ 7189 DUMPANDLOG, /* EDESTADDRREQ 39 Destination address required */ 7190 DUMPANDLOG, /* EMSGSIZE 40 Message too long */ 7191 DUMPANDLOG, /* EPROTOTYPE 41 Protocol wrong type for socket */ 7192 DUMPANDLOG, /* ENOPROTOOPT 42 Protocol not available */ 7193 DUMPANDLOG, /* EPROTONOSUPPORT 43 Protocol not supported */ 7194 DUMPANDLOG, /* ESOCKTNOSUPPORT 44 Socket type not supported */ 7195 DUMPANDLOG, /* ENOTSUP 45 Operation not supported */ 7196 DUMPANDLOG, /* EPFNOSUPPORT 46 Protocol family not supported */ 7197 DUMPANDLOG, /* EAFNOSUPPORT 47 Address family not supported by protocol family */ 7198 DUMPANDLOG, /* EADDRINUSE 48 Address already in use */ 7199 DUMPANDLOG, /* EADDRNOTAVAIL 49 Can't assign requested address */ 7200 /* ipc/network software -- operational errors */ 7201 RETRY, /* ENETDOWN 50 Network is down */ 7202 RETRY, /* ENETUNREACH 51 Network is unreachable */ 7203 RETRY, /* ENETRESET 52 Network dropped connection on reset */ 7204 RETRY, /* ECONNABORTED 53 Software caused connection abort */ 7205 RETRY, /* ECONNRESET 54 Connection reset by peer */ 7206 RETRY, /* ENOBUFS 55 No buffer space available */ 7207 RETRY, /* EISCONN 56 Socket is already connected */ 7208 RETRY, /* ENOTCONN 57 Socket is not connected */ 7209 RETRY, /* ESHUTDOWN 58 Can't send after socket shutdown */ 7210 RETRY, /* ETOOMANYREFS 59 Too many references: can't splice */ 7211 RETRY, /* ETIMEDOUT 60 Operation timed out */ 7212 RETRY, /* ECONNREFUSED 61 Connection refused */ 7213 7214 DUMPANDLOG, /* ELOOP 62 Too many levels of symbolic links */ 7215 DUMP, /* ENAMETOOLONG 63 File name too long */ 7216 RETRY, /* EHOSTDOWN 64 Host is down */ 7217 RETRY, /* EHOSTUNREACH 65 No route to host */ 7218 DUMP, /* ENOTEMPTY 66 Directory not empty */ 7219 /* quotas & mush */ 7220 DUMPANDLOG, /* PROCLIM 67 Too many processes */ 7221 DUMPANDLOG, /* EUSERS 68 Too many users */ 7222 DUMPANDLOG, /* EDQUOT 69 Disc quota exceeded */ 7223 /* Network File System */ 7224 DUMP, /* ESTALE 70 Stale NFS file handle */ 7225 DUMP, /* EREMOTE 71 Too many levels of remote in path */ 7226 DUMPANDLOG, /* EBADRPC 72 RPC struct is bad */ 7227 DUMPANDLOG, /* ERPCMISMATCH 73 RPC version wrong */ 7228 DUMPANDLOG, /* EPROGUNAVAIL 74 RPC prog. not avail */ 7229 DUMPANDLOG, /* EPROGMISMATCH 75 Program version wrong */ 7230 DUMPANDLOG, /* EPROCUNAVAIL 76 Bad procedure for program */ 7231 7232 DUMPANDLOG, /* ENOLCK 77 No locks available */ 7233 DUMPANDLOG, /* ENOSYS 78 Function not implemented */ 7234 DUMPANDLOG, /* EFTYPE 79 Inappropriate file type or format */ 7235 DUMPANDLOG, /* EAUTH 80 Authentication error */ 7236 DUMPANDLOG, /* ENEEDAUTH 81 Need authenticator */ 7237 /* Intelligent device errors */ 7238 DUMPANDLOG, /* EPWROFF 82 Device power is off */ 7239 DUMPANDLOG, /* EDEVERR 83 Device error, e.g. paper out */ 7240 DUMPANDLOG, /* EOVERFLOW 84 Value too large to be stored in data type */ 7241 /* Program loading errors */ 7242 DUMPANDLOG, /* EBADEXEC 85 Bad executable */ 7243 DUMPANDLOG, /* EBADARCH 86 Bad CPU type in executable */ 7244 DUMPANDLOG, /* ESHLIBVERS 87 Shared library version mismatch */ 7245 DUMPANDLOG, /* EBADMACHO 88 Malformed Macho file */ 7246}; 7247 7248char 7249nfs_pageouterrorhandler(int error) 7250{ 7251 if (error > NFS_ELAST) 7252 return(DUMP); 7253 else 7254 return(errortooutcome[error]); 7255} 7256 7257 7258/* 7259 * vnode OP for pageout using UPL 7260 * 7261 * No buffer I/O, just RPCs straight from the mapped pages. 7262 * File size changes are not permitted in pageout. 7263 */ 7264int 7265nfs_vnop_pageout( 7266 struct vnop_pageout_args /* { 7267 struct vnodeop_desc *a_desc; 7268 vnode_t a_vp; 7269 upl_t a_pl; 7270 vm_offset_t a_pl_offset; 7271 off_t a_f_offset; 7272 size_t a_size; 7273 int a_flags; 7274 vfs_context_t a_context; 7275 } */ *ap) 7276{ 7277 vnode_t vp = ap->a_vp; 7278 upl_t pl = ap->a_pl; 7279 size_t size = ap->a_size; 7280 off_t f_offset = ap->a_f_offset; 7281 vm_offset_t pl_offset = ap->a_pl_offset; 7282 int flags = ap->a_flags; 7283 nfsnode_t np = VTONFS(vp); 7284 thread_t thd; 7285 kauth_cred_t cred; 7286 struct nfsbuf *bp; 7287 struct nfsmount *nmp = VTONMP(vp); 7288 daddr64_t lbn; 7289 int error = 0, iomode; 7290 off_t off, txoffset, rxoffset; 7291 vm_offset_t ioaddr, txaddr, rxaddr; 7292 uio_t auio; 7293 char uio_buf [ UIO_SIZEOF(1) ]; 7294 int nofreeupl = flags & UPL_NOCOMMIT; 7295 size_t nmwsize, biosize, iosize, pgsize, txsize, rxsize, xsize, remsize; 7296 struct nfsreq *req[MAXPAGINGREQS]; 7297 int nextsend, nextwait, wverfset, commit; 7298 uint64_t wverf, wverf2; 7299 uint32_t stategenid = 0, vrestart = 0, restart = 0, vrestarts = 0, restarts = 0; 7300 kern_return_t kret; 7301 7302 FSDBG(323, f_offset, size, pl, pl_offset); 7303 7304 if (pl == (upl_t)NULL) 7305 panic("nfs_pageout: no upl"); 7306 7307 if (size <= 0) { 7308 printf("nfs_pageout: invalid size %ld", size); 7309 if (!nofreeupl) 7310 ubc_upl_abort_range(pl, pl_offset, size, 0); 7311 return (EINVAL); 7312 } 7313 7314 if (!nmp) { 7315 if (!nofreeupl) 7316 ubc_upl_abort(pl, UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY); 7317 return (ENXIO); 7318 } 7319 biosize = nmp->nm_biosize; 7320 nmwsize = nmp->nm_wsize; 7321 7322 nfs_data_lock_noupdate(np, NFS_DATA_LOCK_SHARED); 7323 7324 /* 7325 * Check to see whether the buffer is incore. 7326 * If incore and not busy, invalidate it from the cache. 7327 */ 7328 for (iosize = 0; iosize < size; iosize += xsize) { 7329 off = f_offset + iosize; 7330 /* need make sure we do things on block boundaries */ 7331 xsize = biosize - (off % biosize); 7332 if (off + xsize > f_offset + size) 7333 xsize = f_offset + size - off; 7334 lbn = (daddr64_t)(off / biosize); 7335 lck_mtx_lock(nfs_buf_mutex); 7336 if ((bp = nfs_buf_incore(np, lbn))) { 7337 FSDBG(323, off, bp, bp->nb_lflags, bp->nb_flags); 7338 if (nfs_buf_acquire(bp, NBAC_NOWAIT, 0, 0)) { 7339 lck_mtx_unlock(nfs_buf_mutex); 7340 nfs_data_unlock_noupdate(np); 7341 /* no panic. just tell vm we are busy */ 7342 if (!nofreeupl) 7343 ubc_upl_abort_range(pl, pl_offset, size, 0); 7344 return (EBUSY); 7345 } 7346 if (bp->nb_dirtyend > 0) { 7347 /* 7348 * if there's a dirty range in the buffer, check 7349 * to see if it extends beyond the pageout region 7350 * 7351 * if the dirty region lies completely within the 7352 * pageout region, we just invalidate the buffer 7353 * because it's all being written out now anyway. 7354 * 7355 * if any of the dirty region lies outside the 7356 * pageout region, we'll try to clip the dirty 7357 * region to eliminate the portion that's being 7358 * paged out. If that's not possible, because 7359 * the dirty region extends before and after the 7360 * pageout region, then we'll just return EBUSY. 7361 */ 7362 off_t boff, start, end; 7363 boff = NBOFF(bp); 7364 start = off; 7365 end = off + xsize; 7366 /* clip end to EOF */ 7367 if (end > (off_t)np->n_size) 7368 end = np->n_size; 7369 start -= boff; 7370 end -= boff; 7371 if ((bp->nb_dirtyoff < start) && 7372 (bp->nb_dirtyend > end)) { 7373 /* 7374 * not gonna be able to clip the dirty region 7375 * 7376 * But before returning the bad news, move the 7377 * buffer to the start of the delwri list and 7378 * give the list a push to try to flush the 7379 * buffer out. 7380 */ 7381 FSDBG(323, np, bp, 0xd00deebc, EBUSY); 7382 nfs_buf_remfree(bp); 7383 TAILQ_INSERT_HEAD(&nfsbufdelwri, bp, nb_free); 7384 nfsbufdelwricnt++; 7385 nfs_buf_drop(bp); 7386 nfs_buf_delwri_push(1); 7387 lck_mtx_unlock(nfs_buf_mutex); 7388 nfs_data_unlock_noupdate(np); 7389 if (!nofreeupl) 7390 ubc_upl_abort_range(pl, pl_offset, size, 0); 7391 return (EBUSY); 7392 } 7393 if ((bp->nb_dirtyoff < start) || 7394 (bp->nb_dirtyend > end)) { 7395 /* clip dirty region, if necessary */ 7396 if (bp->nb_dirtyoff < start) 7397 bp->nb_dirtyend = min(bp->nb_dirtyend, start); 7398 if (bp->nb_dirtyend > end) 7399 bp->nb_dirtyoff = max(bp->nb_dirtyoff, end); 7400 FSDBG(323, bp, bp->nb_dirtyoff, bp->nb_dirtyend, 0xd00dee00); 7401 /* we're leaving this block dirty */ 7402 nfs_buf_drop(bp); 7403 lck_mtx_unlock(nfs_buf_mutex); 7404 continue; 7405 } 7406 } 7407 nfs_buf_remfree(bp); 7408 lck_mtx_unlock(nfs_buf_mutex); 7409 SET(bp->nb_flags, NB_INVAL); 7410 nfs_node_lock_force(np); 7411 if (ISSET(bp->nb_flags, NB_NEEDCOMMIT)) { 7412 CLR(bp->nb_flags, NB_NEEDCOMMIT); 7413 np->n_needcommitcnt--; 7414 CHECK_NEEDCOMMITCNT(np); 7415 } 7416 nfs_node_unlock(np); 7417 nfs_buf_release(bp, 1); 7418 } else { 7419 lck_mtx_unlock(nfs_buf_mutex); 7420 } 7421 } 7422 7423 thd = vfs_context_thread(ap->a_context); 7424 cred = ubc_getcred(vp); 7425 if (!IS_VALID_CRED(cred)) 7426 cred = vfs_context_ucred(ap->a_context); 7427 7428 nfs_node_lock_force(np); 7429 if (np->n_flag & NWRITEERR) { 7430 error = np->n_error; 7431 nfs_node_unlock(np); 7432 nfs_data_unlock_noupdate(np); 7433 if (!nofreeupl) 7434 ubc_upl_abort_range(pl, pl_offset, size, 7435 UPL_ABORT_FREE_ON_EMPTY); 7436 return (error); 7437 } 7438 nfs_node_unlock(np); 7439 7440 if (f_offset < 0 || f_offset >= (off_t)np->n_size || 7441 f_offset & PAGE_MASK_64 || size & PAGE_MASK_64) { 7442 nfs_data_unlock_noupdate(np); 7443 if (!nofreeupl) 7444 ubc_upl_abort_range(pl, pl_offset, size, 7445 UPL_ABORT_FREE_ON_EMPTY); 7446 return (EINVAL); 7447 } 7448 7449 kret = ubc_upl_map(pl, &ioaddr); 7450 if (kret != KERN_SUCCESS) 7451 panic("nfs_vnop_pageout: ubc_upl_map() failed with (%d)", kret); 7452 ioaddr += pl_offset; 7453 7454 if ((u_quad_t)f_offset + size > np->n_size) 7455 xsize = np->n_size - f_offset; 7456 else 7457 xsize = size; 7458 7459 pgsize = round_page_64(xsize); 7460 if ((size > pgsize) && !nofreeupl) 7461 ubc_upl_abort_range(pl, pl_offset + pgsize, size - pgsize, 7462 UPL_ABORT_FREE_ON_EMPTY); 7463 7464 /* 7465 * check for partial page and clear the 7466 * contents past end of the file before 7467 * releasing it in the VM page cache 7468 */ 7469 if ((u_quad_t)f_offset < np->n_size && (u_quad_t)f_offset + size > np->n_size) { 7470 size_t io = np->n_size - f_offset; 7471 bzero((caddr_t)(ioaddr + io), size - io); 7472 FSDBG(321, np->n_size, f_offset, f_offset + io, size - io); 7473 } 7474 nfs_data_unlock_noupdate(np); 7475 7476 auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_WRITE, 7477 &uio_buf, sizeof(uio_buf)); 7478 7479tryagain: 7480 if (nmp->nm_vers >= NFS_VER4) 7481 stategenid = nmp->nm_stategenid; 7482 wverf = wverf2 = wverfset = 0; 7483 txsize = rxsize = xsize; 7484 txoffset = rxoffset = f_offset; 7485 txaddr = rxaddr = ioaddr; 7486 commit = NFS_WRITE_FILESYNC; 7487 7488 bzero(req, sizeof(req)); 7489 nextsend = nextwait = 0; 7490 do { 7491 if (np->n_flag & NREVOKE) { 7492 error = EIO; 7493 break; 7494 } 7495 /* send requests while we need to and have available slots */ 7496 while ((txsize > 0) && (req[nextsend] == NULL)) { 7497 iosize = MIN(nmwsize, txsize); 7498 uio_reset(auio, txoffset, UIO_SYSSPACE, UIO_WRITE); 7499 uio_addiov(auio, CAST_USER_ADDR_T(txaddr), iosize); 7500 FSDBG(323, uio_offset(auio), iosize, txaddr, txsize); 7501 OSAddAtomic64(1, &nfsstats.pageouts); 7502 nfs_node_lock_force(np); 7503 np->n_numoutput++; 7504 nfs_node_unlock(np); 7505 vnode_startwrite(vp); 7506 iomode = NFS_WRITE_UNSTABLE; 7507 if ((error = nmp->nm_funcs->nf_write_rpc_async(np, auio, iosize, thd, cred, iomode, NULL, &req[nextsend]))) { 7508 req[nextsend] = NULL; 7509 vnode_writedone(vp); 7510 nfs_node_lock_force(np); 7511 np->n_numoutput--; 7512 nfs_node_unlock(np); 7513 break; 7514 } 7515 txaddr += iosize; 7516 txoffset += iosize; 7517 txsize -= iosize; 7518 nextsend = (nextsend + 1) % MAXPAGINGREQS; 7519 } 7520 /* wait while we need to and break out if more requests to send */ 7521 while ((rxsize > 0) && req[nextwait]) { 7522 iosize = remsize = MIN(nmwsize, rxsize); 7523 error = nmp->nm_funcs->nf_write_rpc_async_finish(np, req[nextwait], &iomode, &iosize, &wverf2); 7524 req[nextwait] = NULL; 7525 nextwait = (nextwait + 1) % MAXPAGINGREQS; 7526 vnode_writedone(vp); 7527 nfs_node_lock_force(np); 7528 np->n_numoutput--; 7529 nfs_node_unlock(np); 7530 if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) { 7531 lck_mtx_lock(&nmp->nm_lock); 7532 if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) { 7533 NP(np, "nfs_vnop_pageout: error %d, initiating recovery", error); 7534 nfs_need_recover(nmp, error); 7535 } 7536 lck_mtx_unlock(&nmp->nm_lock); 7537 restart = 1; 7538 goto cancel; 7539 } 7540 if (error) { 7541 FSDBG(323, rxoffset, rxsize, error, -1); 7542 break; 7543 } 7544 if (!wverfset) { 7545 wverf = wverf2; 7546 wverfset = 1; 7547 } else if (wverf != wverf2) { 7548 /* verifier changed, so we need to restart all the writes */ 7549 vrestart = 1; 7550 goto cancel; 7551 } 7552 /* Retain the lowest commitment level returned. */ 7553 if (iomode < commit) 7554 commit = iomode; 7555 rxaddr += iosize; 7556 rxoffset += iosize; 7557 rxsize -= iosize; 7558 remsize -= iosize; 7559 if (remsize > 0) { 7560 /* need to try sending the remainder */ 7561 iosize = remsize; 7562 uio_reset(auio, rxoffset, UIO_SYSSPACE, UIO_WRITE); 7563 uio_addiov(auio, CAST_USER_ADDR_T(rxaddr), remsize); 7564 iomode = NFS_WRITE_UNSTABLE; 7565 error = nfs_write_rpc2(np, auio, thd, cred, &iomode, &wverf2); 7566 if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) { 7567 NP(np, "nfs_vnop_pageout: restart: error %d", error); 7568 lck_mtx_lock(&nmp->nm_lock); 7569 if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) { 7570 NP(np, "nfs_vnop_pageout: error %d, initiating recovery", error); 7571 nfs_need_recover(nmp, error); 7572 } 7573 lck_mtx_unlock(&nmp->nm_lock); 7574 restart = 1; 7575 goto cancel; 7576 } 7577 if (error) { 7578 FSDBG(323, rxoffset, rxsize, error, -1); 7579 break; 7580 } 7581 if (wverf != wverf2) { 7582 /* verifier changed, so we need to restart all the writes */ 7583 vrestart = 1; 7584 goto cancel; 7585 } 7586 if (iomode < commit) 7587 commit = iomode; 7588 rxaddr += iosize; 7589 rxoffset += iosize; 7590 rxsize -= iosize; 7591 } 7592 if (txsize) 7593 break; 7594 } 7595 } while (!error && (txsize || rxsize)); 7596 7597 vrestart = 0; 7598 7599 if (!error && (commit != NFS_WRITE_FILESYNC)) { 7600 error = nmp->nm_funcs->nf_commit_rpc(np, f_offset, xsize, cred, wverf); 7601 if (error == NFSERR_STALEWRITEVERF) { 7602 vrestart = 1; 7603 error = EIO; 7604 } 7605 } 7606 7607 if (error) { 7608cancel: 7609 /* cancel any outstanding requests */ 7610 while (req[nextwait]) { 7611 nfs_request_async_cancel(req[nextwait]); 7612 req[nextwait] = NULL; 7613 nextwait = (nextwait + 1) % MAXPAGINGREQS; 7614 vnode_writedone(vp); 7615 nfs_node_lock_force(np); 7616 np->n_numoutput--; 7617 nfs_node_unlock(np); 7618 } 7619 if (np->n_flag & NREVOKE) { 7620 error = EIO; 7621 } else { 7622 if (vrestart) { 7623 if (++vrestarts <= 100) /* guard against no progress */ 7624 goto tryagain; 7625 NP(np, "nfs_pageout: too many restarts, aborting"); 7626 FSDBG(323, f_offset, xsize, ERESTART, -1); 7627 } 7628 if (restart) { 7629 if (restarts <= nfs_mount_state_max_restarts(nmp)) { /* guard against no progress */ 7630 if (error == NFSERR_GRACE) 7631 tsleep(&nmp->nm_state, (PZERO-1), "nfsgrace", 2*hz); 7632 if (!(error = nfs_mount_state_wait_for_recovery(nmp))) 7633 goto tryagain; 7634 } else { 7635 NP(np, "nfs_pageout: too many restarts, aborting"); 7636 FSDBG(323, f_offset, xsize, ERESTART, -1); 7637 } 7638 } 7639 } 7640 } 7641 7642 ubc_upl_unmap(pl); 7643 7644 /* 7645 * We've had several different solutions on what to do when the pageout 7646 * gets an error. If we don't handle it, and return an error to the 7647 * caller, vm, it will retry . This can end in endless looping 7648 * between vm and here doing retries of the same page. Doing a dump 7649 * back to vm, will get it out of vm's knowledge and we lose whatever 7650 * data existed. This is risky, but in some cases necessary. For 7651 * example, the initial fix here was to do that for ESTALE. In that case 7652 * the server is telling us that the file is no longer the same. We 7653 * would not want to keep paging out to that. We also saw some 151 7654 * errors from Auspex server and NFSv3 can return errors higher than 7655 * ELAST. Those along with NFS known server errors we will "dump" from 7656 * vm. Errors we don't expect to occur, we dump and log for further 7657 * analysis. Errors that could be transient, networking ones, 7658 * we let vm "retry". Lastly, errors that we retry, but may have potential 7659 * to storm the network, we "retrywithsleep". "sever" will be used in 7660 * in the future to dump all pages of object for cases like ESTALE. 7661 * All this is the basis for the states returned and first guesses on 7662 * error handling. Tweaking expected as more statistics are gathered. 7663 * Note, in the long run we may need another more robust solution to 7664 * have some kind of persistant store when the vm cannot dump nor keep 7665 * retrying as a solution, but this would be a file architectural change 7666 */ 7667 if (!nofreeupl) { /* otherwise stacked file system has to handle this */ 7668 if (error) { 7669 int abortflags = 0; 7670 char action = nfs_pageouterrorhandler(error); 7671 7672 switch (action) { 7673 case DUMP: 7674 abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; 7675 break; 7676 case DUMPANDLOG: 7677 abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; 7678 if (error <= NFS_ELAST) { 7679 if ((errorcount[error] % 100) == 0) 7680 NP(np, "nfs_pageout: unexpected error %d. dumping vm page", error); 7681 errorcount[error]++; 7682 } 7683 break; 7684 case RETRY: 7685 abortflags = UPL_ABORT_FREE_ON_EMPTY; 7686 break; 7687 case SEVER: /* not implemented */ 7688 default: 7689 NP(np, "nfs_pageout: action %d not expected", action); 7690 break; 7691 } 7692 7693 ubc_upl_abort_range(pl, pl_offset, pgsize, abortflags); 7694 /* return error in all cases above */ 7695 7696 } else { 7697 ubc_upl_commit_range(pl, pl_offset, pgsize, 7698 UPL_COMMIT_CLEAR_DIRTY | 7699 UPL_COMMIT_FREE_ON_EMPTY); 7700 } 7701 } 7702 return (error); 7703} 7704 7705/* Blktooff derives file offset given a logical block number */ 7706int 7707nfs_vnop_blktooff( 7708 struct vnop_blktooff_args /* { 7709 struct vnodeop_desc *a_desc; 7710 vnode_t a_vp; 7711 daddr64_t a_lblkno; 7712 off_t *a_offset; 7713 } */ *ap) 7714{ 7715 int biosize; 7716 vnode_t vp = ap->a_vp; 7717 struct nfsmount *nmp = VTONMP(vp); 7718 7719 if (nfs_mount_gone(nmp)) 7720 return (ENXIO); 7721 biosize = nmp->nm_biosize; 7722 7723 *ap->a_offset = (off_t)(ap->a_lblkno * biosize); 7724 7725 return (0); 7726} 7727 7728int 7729nfs_vnop_offtoblk( 7730 struct vnop_offtoblk_args /* { 7731 struct vnodeop_desc *a_desc; 7732 vnode_t a_vp; 7733 off_t a_offset; 7734 daddr64_t *a_lblkno; 7735 } */ *ap) 7736{ 7737 int biosize; 7738 vnode_t vp = ap->a_vp; 7739 struct nfsmount *nmp = VTONMP(vp); 7740 7741 if (nfs_mount_gone(nmp)) 7742 return (ENXIO); 7743 biosize = nmp->nm_biosize; 7744 7745 *ap->a_lblkno = (daddr64_t)(ap->a_offset / biosize); 7746 7747 return (0); 7748} 7749 7750/* 7751 * vnode change monitoring 7752 */ 7753int 7754nfs_vnop_monitor( 7755 struct vnop_monitor_args /* { 7756 struct vnodeop_desc *a_desc; 7757 vnode_t a_vp; 7758 uint32_t a_events; 7759 uint32_t a_flags; 7760 void *a_handle; 7761 vfs_context_t a_context; 7762 } */ *ap) 7763{ 7764 nfsnode_t np = VTONFS(ap->a_vp); 7765 struct nfsmount *nmp = VTONMP(ap->a_vp); 7766 int error = 0; 7767 7768 if (nfs_mount_gone(nmp)) 7769 return (ENXIO); 7770 7771 /* make sure that the vnode's monitoring status is up to date */ 7772 lck_mtx_lock(&nmp->nm_lock); 7773 if (vnode_ismonitored(ap->a_vp)) { 7774 /* This vnode is currently being monitored, make sure we're tracking it. */ 7775 if (np->n_monlink.le_next == NFSNOLIST) { 7776 LIST_INSERT_HEAD(&nmp->nm_monlist, np, n_monlink); 7777 nfs_mount_sock_thread_wake(nmp); 7778 } 7779 } else { 7780 /* This vnode is no longer being monitored, make sure we're not tracking it. */ 7781 /* Wait for any in-progress getattr to complete first. */ 7782 while (np->n_mflag & NMMONSCANINPROG) { 7783 struct timespec ts = { 1, 0 }; 7784 np->n_mflag |= NMMONSCANWANT; 7785 msleep(&np->n_mflag, &nmp->nm_lock, PZERO-1, "nfswaitmonscan", &ts); 7786 } 7787 if (np->n_monlink.le_next != NFSNOLIST) { 7788 LIST_REMOVE(np, n_monlink); 7789 np->n_monlink.le_next = NFSNOLIST; 7790 } 7791 } 7792 lck_mtx_unlock(&nmp->nm_lock); 7793 7794 return (error); 7795} 7796 7797/* 7798 * Send a vnode notification for the given events. 7799 */ 7800void 7801nfs_vnode_notify(nfsnode_t np, uint32_t events) 7802{ 7803 struct nfsmount *nmp = NFSTONMP(np); 7804 struct nfs_vattr nvattr; 7805 struct vnode_attr vattr, *vap = NULL; 7806 struct timeval now; 7807 7808 microuptime(&now); 7809 if ((np->n_evtstamp == now.tv_sec) || !nmp) { 7810 /* delay sending this notify */ 7811 np->n_events |= events; 7812 return; 7813 } 7814 events |= np->n_events; 7815 np->n_events = 0; 7816 np->n_evtstamp = now.tv_sec; 7817 7818 vfs_get_notify_attributes(&vattr); 7819 if (!nfs_getattrcache(np, &nvattr, 0)) { 7820 vap = &vattr; 7821 VATTR_INIT(vap); 7822 VATTR_RETURN(vap, va_fsid, vfs_statfs(nmp->nm_mountp)->f_fsid.val[0]); 7823 VATTR_RETURN(vap, va_fileid, nvattr.nva_fileid); 7824 VATTR_RETURN(vap, va_mode, nvattr.nva_mode); 7825 VATTR_RETURN(vap, va_uid, nvattr.nva_uid); 7826 VATTR_RETURN(vap, va_gid, nvattr.nva_gid); 7827 VATTR_RETURN(vap, va_nlink, nvattr.nva_nlink); 7828 } 7829 vnode_notify(NFSTOV(np), events, vap); 7830} 7831