/*
- * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* FreeBSD-Id: nfs_vnops.c,v 1.72 1997/11/07 09:20:48 phk Exp $
*/
+#include <nfs/nfs_conf.h>
+#if CONFIG_NFS_CLIENT
/*
* vnode op calls for Sun NFS version 2 and 3
#include <sys/attr.h>
#include <sys/signalvar.h>
#include <sys/uio_internal.h>
+#include <sys/xattr.h>
#include <vfs/vfs_support.h>
int nfs3_vnop_rmdir(struct vnop_rmdir_args *);
int nfs3_vnop_symlink(struct vnop_symlink_args *);
+
vnop_t **nfsv2_vnodeop_p;
-static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
- { &vnop_default_desc, (vnop_t *)vn_default_error },
- { &vnop_lookup_desc, (vnop_t *)nfs_vnop_lookup }, /* lookup */
- { &vnop_create_desc, (vnop_t *)nfs3_vnop_create }, /* create */
- { &vnop_mknod_desc, (vnop_t *)nfs3_vnop_mknod }, /* mknod */
- { &vnop_open_desc, (vnop_t *)nfs_vnop_open }, /* open */
- { &vnop_close_desc, (vnop_t *)nfs_vnop_close }, /* close */
- { &vnop_access_desc, (vnop_t *)nfs_vnop_access }, /* access */
- { &vnop_getattr_desc, (vnop_t *)nfs3_vnop_getattr }, /* getattr */
- { &vnop_setattr_desc, (vnop_t *)nfs_vnop_setattr }, /* setattr */
- { &vnop_read_desc, (vnop_t *)nfs_vnop_read }, /* read */
- { &vnop_write_desc, (vnop_t *)nfs_vnop_write }, /* write */
- { &vnop_ioctl_desc, (vnop_t *)nfs_vnop_ioctl }, /* ioctl */
- { &vnop_select_desc, (vnop_t *)nfs_vnop_select }, /* select */
- { &vnop_revoke_desc, (vnop_t *)nfs_vnop_revoke }, /* revoke */
- { &vnop_mmap_desc, (vnop_t *)nfs_vnop_mmap }, /* mmap */
- { &vnop_mnomap_desc, (vnop_t *)nfs_vnop_mnomap }, /* mnomap */
- { &vnop_fsync_desc, (vnop_t *)nfs_vnop_fsync }, /* fsync */
- { &vnop_remove_desc, (vnop_t *)nfs_vnop_remove }, /* remove */
- { &vnop_link_desc, (vnop_t *)nfs3_vnop_link }, /* link */
- { &vnop_rename_desc, (vnop_t *)nfs_vnop_rename }, /* rename */
- { &vnop_mkdir_desc, (vnop_t *)nfs3_vnop_mkdir }, /* mkdir */
- { &vnop_rmdir_desc, (vnop_t *)nfs3_vnop_rmdir }, /* rmdir */
- { &vnop_symlink_desc, (vnop_t *)nfs3_vnop_symlink }, /* symlink */
- { &vnop_readdir_desc, (vnop_t *)nfs_vnop_readdir }, /* readdir */
- { &vnop_readlink_desc, (vnop_t *)nfs_vnop_readlink }, /* readlink */
- { &vnop_inactive_desc, (vnop_t *)nfs_vnop_inactive }, /* inactive */
- { &vnop_reclaim_desc, (vnop_t *)nfs_vnop_reclaim }, /* reclaim */
- { &vnop_strategy_desc, (vnop_t *)err_strategy }, /* strategy */
- { &vnop_pathconf_desc, (vnop_t *)nfs_vnop_pathconf }, /* pathconf */
- { &vnop_advlock_desc, (vnop_t *)nfs_vnop_advlock }, /* advlock */
- { &vnop_bwrite_desc, (vnop_t *)err_bwrite }, /* bwrite */
- { &vnop_pagein_desc, (vnop_t *)nfs_vnop_pagein }, /* Pagein */
- { &vnop_pageout_desc, (vnop_t *)nfs_vnop_pageout }, /* Pageout */
- { &vnop_copyfile_desc, (vnop_t *)err_copyfile }, /* Copyfile */
- { &vnop_blktooff_desc, (vnop_t *)nfs_vnop_blktooff }, /* blktooff */
- { &vnop_offtoblk_desc, (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */
- { &vnop_blockmap_desc, (vnop_t *)nfs_vnop_blockmap }, /* blockmap */
- { &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
- { NULL, NULL }
+static const struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
+ { .opve_op = &vnop_default_desc, .opve_impl = (vnop_t *)vn_default_error },
+ { .opve_op = &vnop_lookup_desc, .opve_impl = (vnop_t *)nfs_vnop_lookup }, /* lookup */
+ { .opve_op = &vnop_create_desc, .opve_impl = (vnop_t *)nfs3_vnop_create }, /* create */
+ { .opve_op = &vnop_mknod_desc, .opve_impl = (vnop_t *)nfs3_vnop_mknod }, /* mknod */
+ { .opve_op = &vnop_open_desc, .opve_impl = (vnop_t *)nfs_vnop_open }, /* open */
+ { .opve_op = &vnop_close_desc, .opve_impl = (vnop_t *)nfs_vnop_close }, /* close */
+ { .opve_op = &vnop_access_desc, .opve_impl = (vnop_t *)nfs_vnop_access }, /* access */
+ { .opve_op = &vnop_getattr_desc, .opve_impl = (vnop_t *)nfs3_vnop_getattr }, /* getattr */
+ { .opve_op = &vnop_setattr_desc, .opve_impl = (vnop_t *)nfs_vnop_setattr }, /* setattr */
+ { .opve_op = &vnop_read_desc, .opve_impl = (vnop_t *)nfs_vnop_read }, /* read */
+ { .opve_op = &vnop_write_desc, .opve_impl = (vnop_t *)nfs_vnop_write }, /* write */
+ { .opve_op = &vnop_ioctl_desc, .opve_impl = (vnop_t *)nfs_vnop_ioctl }, /* ioctl */
+ { .opve_op = &vnop_select_desc, .opve_impl = (vnop_t *)nfs_vnop_select }, /* select */
+ { .opve_op = &vnop_revoke_desc, .opve_impl = (vnop_t *)nfs_vnop_revoke }, /* revoke */
+ { .opve_op = &vnop_mmap_desc, .opve_impl = (vnop_t *)nfs_vnop_mmap }, /* mmap */
+ { .opve_op = &vnop_mnomap_desc, .opve_impl = (vnop_t *)nfs_vnop_mnomap }, /* mnomap */
+ { .opve_op = &vnop_fsync_desc, .opve_impl = (vnop_t *)nfs_vnop_fsync }, /* fsync */
+ { .opve_op = &vnop_remove_desc, .opve_impl = (vnop_t *)nfs_vnop_remove }, /* remove */
+ { .opve_op = &vnop_link_desc, .opve_impl = (vnop_t *)nfs3_vnop_link }, /* link */
+ { .opve_op = &vnop_rename_desc, .opve_impl = (vnop_t *)nfs_vnop_rename }, /* rename */
+ { .opve_op = &vnop_mkdir_desc, .opve_impl = (vnop_t *)nfs3_vnop_mkdir }, /* mkdir */
+ { .opve_op = &vnop_rmdir_desc, .opve_impl = (vnop_t *)nfs3_vnop_rmdir }, /* rmdir */
+ { .opve_op = &vnop_symlink_desc, .opve_impl = (vnop_t *)nfs3_vnop_symlink }, /* symlink */
+ { .opve_op = &vnop_readdir_desc, .opve_impl = (vnop_t *)nfs_vnop_readdir }, /* readdir */
+ { .opve_op = &vnop_readlink_desc, .opve_impl = (vnop_t *)nfs_vnop_readlink }, /* readlink */
+ { .opve_op = &vnop_inactive_desc, .opve_impl = (vnop_t *)nfs_vnop_inactive }, /* inactive */
+ { .opve_op = &vnop_reclaim_desc, .opve_impl = (vnop_t *)nfs_vnop_reclaim }, /* reclaim */
+ { .opve_op = &vnop_strategy_desc, .opve_impl = (vnop_t *)err_strategy }, /* strategy */
+ { .opve_op = &vnop_pathconf_desc, .opve_impl = (vnop_t *)nfs_vnop_pathconf }, /* pathconf */
+ { .opve_op = &vnop_advlock_desc, .opve_impl = (vnop_t *)nfs_vnop_advlock }, /* advlock */
+ { .opve_op = &vnop_bwrite_desc, .opve_impl = (vnop_t *)err_bwrite }, /* bwrite */
+ { .opve_op = &vnop_pagein_desc, .opve_impl = (vnop_t *)nfs_vnop_pagein }, /* Pagein */
+ { .opve_op = &vnop_pageout_desc, .opve_impl = (vnop_t *)nfs_vnop_pageout }, /* Pageout */
+ { .opve_op = &vnop_copyfile_desc, .opve_impl = (vnop_t *)err_copyfile }, /* Copyfile */
+ { .opve_op = &vnop_blktooff_desc, .opve_impl = (vnop_t *)nfs_vnop_blktooff }, /* blktooff */
+ { .opve_op = &vnop_offtoblk_desc, .opve_impl = (vnop_t *)nfs_vnop_offtoblk }, /* offtoblk */
+ { .opve_op = &vnop_blockmap_desc, .opve_impl = (vnop_t *)nfs_vnop_blockmap }, /* blockmap */
+ { .opve_op = &vnop_monitor_desc, .opve_impl = (vnop_t *)nfs_vnop_monitor }, /* monitor */
+ { .opve_op = NULL, .opve_impl = NULL }
};
-struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
+const struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
{ &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
+
+#if CONFIG_NFS4
vnop_t **nfsv4_vnodeop_p;
-static struct vnodeopv_entry_desc nfsv4_vnodeop_entries[] = {
+static const struct vnodeopv_entry_desc nfsv4_vnodeop_entries[] = {
{ &vnop_default_desc, (vnop_t *)vn_default_error },
{ &vnop_lookup_desc, (vnop_t *)nfs_vnop_lookup }, /* lookup */
{ &vnop_create_desc, (vnop_t *)nfs4_vnop_create }, /* create */
{ &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
{ NULL, NULL }
};
-struct vnodeopv_desc nfsv4_vnodeop_opv_desc =
+const struct vnodeopv_desc nfsv4_vnodeop_opv_desc =
{ &nfsv4_vnodeop_p, nfsv4_vnodeop_entries };
+#endif
/*
* Special device vnode ops
*/
vnop_t **spec_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
+static const struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
{ &vnop_default_desc, (vnop_t *)vn_default_error },
{ &vnop_lookup_desc, (vnop_t *)spec_lookup }, /* lookup */
{ &vnop_create_desc, (vnop_t *)spec_create }, /* create */
{ &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
{ NULL, NULL }
};
-struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
+const struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
{ &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
+#if CONFIG_NFS4
vnop_t **spec_nfsv4nodeop_p;
-static struct vnodeopv_entry_desc spec_nfsv4nodeop_entries[] = {
+static const struct vnodeopv_entry_desc spec_nfsv4nodeop_entries[] = {
{ &vnop_default_desc, (vnop_t *)vn_default_error },
{ &vnop_lookup_desc, (vnop_t *)spec_lookup }, /* lookup */
{ &vnop_create_desc, (vnop_t *)spec_create }, /* create */
{ &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
{ NULL, NULL }
};
-struct vnodeopv_desc spec_nfsv4nodeop_opv_desc =
+const struct vnodeopv_desc spec_nfsv4nodeop_opv_desc =
{ &spec_nfsv4nodeop_p, spec_nfsv4nodeop_entries };
+#endif /* CONFIG_NFS4 */
#if FIFO
vnop_t **fifo_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
+static const struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
{ &vnop_default_desc, (vnop_t *)vn_default_error },
{ &vnop_lookup_desc, (vnop_t *)fifo_lookup }, /* lookup */
{ &vnop_create_desc, (vnop_t *)fifo_create }, /* create */
{ &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
{ NULL, NULL }
};
-struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
+const struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
{ &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
+#endif
+#if CONFIG_NFS4
+#if FIFO
vnop_t **fifo_nfsv4nodeop_p;
-static struct vnodeopv_entry_desc fifo_nfsv4nodeop_entries[] = {
+static const struct vnodeopv_entry_desc fifo_nfsv4nodeop_entries[] = {
{ &vnop_default_desc, (vnop_t *)vn_default_error },
{ &vnop_lookup_desc, (vnop_t *)fifo_lookup }, /* lookup */
{ &vnop_create_desc, (vnop_t *)fifo_create }, /* create */
{ &vnop_monitor_desc, (vnop_t *)nfs_vnop_monitor }, /* monitor */
{ NULL, NULL }
};
-struct vnodeopv_desc fifo_nfsv4nodeop_opv_desc =
+const struct vnodeopv_desc fifo_nfsv4nodeop_opv_desc =
{ &fifo_nfsv4nodeop_p, fifo_nfsv4nodeop_entries };
#endif /* FIFO */
+#endif /* CONFIG_NFS4 */
int nfs_sillyrename(nfsnode_t, nfsnode_t, struct componentname *, vfs_context_t);
int nfs_getattr_internal(nfsnode_t, struct nfs_vattr *, vfs_context_t, int);
int nfs_refresh_fh(nfsnode_t, vfs_context_t);
+
+/*
+ * Update nfsnode attributes to avoid extra getattr calls for each direntry.
+ * This function should be called only if RDIRPLUS flag is enabled.
+ */
+void
+nfs_rdirplus_update_node_attrs(nfsnode_t dnp, struct direntry *dp, fhandle_t *fhp, struct nfs_vattr *nvattrp, uint64_t *savedxidp)
+{
+ nfsnode_t np;
+ struct componentname cn;
+ int isdot = (dp->d_namlen == 1) && (dp->d_name[0] == '.');
+ int isdotdot = (dp->d_namlen == 2) && (dp->d_name[0] == '.') && (dp->d_name[1] == '.');
+
+ if (isdot || isdotdot) {
+ return;
+ }
+
+ np = NULL;
+ bzero(&cn, sizeof(cn));
+ cn.cn_nameptr = dp->d_name;
+ cn.cn_namelen = dp->d_namlen;
+ cn.cn_nameiop = LOOKUP;
+
+ nfs_nget(NFSTOMP(dnp), dnp, &cn, fhp->fh_data, fhp->fh_len, nvattrp, savedxidp, RPCAUTH_UNKNOWN, NG_NOCREATE, &np);
+ if (np) {
+ nfs_node_unlock(np);
+ vnode_put(NFSTOV(np));
+ }
+}
+
/*
* Find the slot in the access cache for this UID.
* If adding and no existing slot is found, reuse slots in FIFO order.
}
nfsmout_if(error);
+#if CONFIG_NFS_GSS
if (auth_is_kerberized(np->n_auth) || auth_is_kerberized(nmp->nm_auth)) {
uid = nfs_cred_getasid2uid(vfs_context_ucred(ctx));
} else {
uid = kauth_cred_getuid(vfs_context_ucred(ctx));
}
+#else
+ uid = kauth_cred_getuid(vfs_context_ucred(ctx));
+#endif /* CONFIG_NFS_GSS */
slot = nfs_node_access_slot(np, uid, 1);
np->n_accessuid[slot] = uid;
microuptime(&now);
return error;
}
+
/*
* NFS access vnode op.
* For NFS version 2, just return ok. File accesses may fail later.
}
nfsvers = nmp->nm_vers;
- if (nfsvers == NFS_VER2) {
+
+ if (nfsvers == NFS_VER2 || NMFLAG(nmp, NOOPAQUE_AUTH)) {
if ((ap->a_action & KAUTH_VNODE_WRITE_RIGHTS) &&
vfs_isrdonly(vnode_mount(vp))) {
return EROFS;
* Does our cached result allow us to give a definite yes to
* this request?
*/
+#if CONFIG_NFS_GSS
if (auth_is_kerberized(np->n_auth) || auth_is_kerberized(nmp->nm_auth)) {
uid = nfs_cred_getasid2uid(vfs_context_ucred(ctx));
} else {
uid = kauth_cred_getuid(vfs_context_ucred(ctx));
}
+#else
+ uid = kauth_cred_getuid(vfs_context_ucred(ctx));
+#endif /* CONFIG_NFS_GSS */
slot = nfs_node_access_slot(np, uid, 0);
dorpc = 1;
if (access == 0) {
NP(np, "nfs_vnop_open: LOST %d", kauth_cred_getuid(nofp->nof_owner->noo_cred));
error = EIO;
}
+#if CONFIG_NFS4
if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) {
nfs_mount_state_in_use_end(nmp, 0);
error = nfs4_reopen(nofp, vfs_context_thread(ctx));
goto restart;
}
}
+#endif
if (!error) {
error = nfs_open_file_set_busy(nofp, vfs_context_thread(ctx));
}
nofp->nof_flags &= ~NFS_OPEN_FILE_CREATE;
nofp->nof_creator = NULL;
} else {
+#if CONFIG_NFS4
if (!opened) {
error = nfs4_open(np, nofp, accessMode, denyMode, ctx);
}
+#endif
if ((error == EACCES) && (nofp->nof_flags & NFS_OPEN_FILE_CREATE) &&
(nofp->nof_creator == current_thread())) {
/*
}
error = nfs_open_file_find(np, noop, &nofp, 0, 0, 0);
+#if CONFIG_NFS4
if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) {
nfs_mount_state_in_use_end(nmp, 0);
error = nfs4_reopen(nofp, NULL);
goto restart;
}
}
+#endif
if (error) {
NP(np, "nfs_vnop_close: no open file for owner, error %d, %d", error, kauth_cred_getuid(noop->noo_cred));
error = EBADF;
struct nfs_open_file *nofp,
uint32_t accessMode,
uint32_t denyMode,
- vfs_context_t ctx)
+ __unused vfs_context_t ctx)
{
+#if CONFIG_NFS4
struct nfs_lock_owner *nlop;
+#endif
int error = 0, changed = 0, delegated = 0, closed = 0, downgrade = 0;
uint32_t newAccessMode, newDenyMode;
changed = 0;
}
- if (NFSTONMP(np)->nm_vers < NFS_VER4) { /* NFS v2/v3 closes simply need to remove the open. */
+ if (NFSTONMP(np)->nm_vers < NFS_VER4) {
+ /* NFS v2/v3 closes simply need to remove the open. */
goto v3close;
}
-
+#if CONFIG_NFS4
if ((newAccessMode == 0) || (nofp->nof_opencnt == 1)) {
/*
* No more access after this close, so clean up and close it.
}
}
}
-
+#endif
+v3close:
if (error) {
NP(np, "nfs_close: error %d, %d", error, kauth_cred_getuid(nofp->nof_owner->noo_cred));
return error;
}
-v3close:
if (!downgrade) {
nfs_open_file_remove_open(nofp, accessMode, denyMode);
}
error = status;
}
nfsmout_if(error);
- error = nfs_parsefattr(&nmrep, nfsvers, nvap);
+ error = nfs_parsefattr(nmp, &nmrep, nfsvers, nvap);
nfsmout:
nfsm_chain_cleanup(&nmreq);
nfsm_chain_cleanup(&nmrep);
int namelen, fhsize, refreshed;
int error, wanted = 0;
uint8_t *fhp;
- struct timespec ts = {2, 0};
+ struct timespec ts = {.tv_sec = 2, .tv_nsec = 0};
NFS_VNOP_DBG("vnode is %d\n", vnode_vtype(vp));
struct nfsmount *nmp;
int error = 0, nfsvers, inprogset = 0, wanted = 0, avoidfloods;
struct nfs_vattr nvattr;
- struct timespec ts = { 2, 0 };
+ struct timespec ts = { .tv_sec = 2, .tv_nsec = 0 };
u_int64_t xid;
FSDBG_TOP(513, np->n_size, np, np->n_vattr.nva_size, np->n_flag);
return error;
}
+
/*
* NFS getattr call from vfs.
*/
VNODE_ATTR_va_fileid | \
VNODE_ATTR_va_type)
+
int
nfs3_vnop_getattr(
struct vnop_getattr_args /* {
* } */*ap)
{
int error;
+ nfsnode_t np;
+ uint64_t supported_attrs;
struct nfs_vattr nva;
struct vnode_attr *vap = ap->a_vap;
struct nfsmount *nmp;
dev_t rdev;
+ nmp = VTONMP(ap->a_vp);
+
/*
* Lets don't go over the wire if we don't support any of the attributes.
* Just fall through at the VFS layer and let it cons up what it needs.
*/
/* Return the io size no matter what, since we don't go over the wire for this */
VATTR_RETURN(vap, va_iosize, nfs_iosize);
- if ((vap->va_active & NFS3_SUPPORTED_VATTRS) == 0) {
+
+ supported_attrs = NFS3_SUPPORTED_VATTRS;
+
+ if ((vap->va_active & supported_attrs) == 0) {
return 0;
}
(uint64_t)VM_KERNEL_ADDRPERM(ap->a_vp),
ap->a_vp->v_name ? ap->a_vp->v_name : "empty");
}
+
+ /*
+ * We should not go over the wire if only fileid was requested and has ever been populated.
+ */
+ if ((vap->va_active & supported_attrs) == VNODE_ATTR_va_fileid) {
+ np = VTONFS(ap->a_vp);
+ if (np->n_attrstamp) {
+ VATTR_RETURN(vap, va_fileid, np->n_vattr.nva_fileid);
+ return 0;
+ }
+ }
+
error = nfs_getattr(VTONFS(ap->a_vp), &nva, ap->a_context, NGA_CACHED);
if (error) {
return error;
}
/* copy nva to *a_vap */
- nmp = VTONMP(ap->a_vp);
VATTR_RETURN(vap, va_type, nva.nva_type);
VATTR_RETURN(vap, va_mode, nva.nva_mode);
rdev = makedev(nva.nva_rawdev.specdata1, nva.nva_rawdev.specdata2);
vap->va_change_time.tv_nsec = nva.nva_timensec[NFSTIME_CHANGE];
VATTR_SET_SUPPORTED(vap, va_change_time);
+
// VATTR_RETURN(vap, va_encoding, 0xffff /* kTextEncodingUnknown */);
return error;
}
int dul_in_progress = 0;
vnode_t dvp = NULL;
const char *vname = NULL;
+#if CONFIG_NFS4
struct nfs_open_owner *noop = NULL;
struct nfs_open_file *nofp = NULL;
-
+#endif
nmp = VTONMP(vp);
if (nfs_mount_gone(nmp)) {
return ENXIO;
FSDBG_BOT(512, np->n_size, vap->va_data_size, np->n_vattr.nva_size, -1);
return error;
}
+#if CONFIG_NFS4
if (nfsvers >= NFS_VER4) {
/* setting file size requires having the file open for write access */
if (np->n_flag & NREVOKE) {
}
}
}
+#endif
nfs_data_lock(np, NFS_DATA_LOCK_EXCLUSIVE);
if (np->n_size > vap->va_data_size) { /* shrinking? */
daddr64_t obn, bn;
nfs_node_unlock(np);
}
nfs_data_unlock(np);
+#if CONFIG_NFS4
if (nfsvers >= NFS_VER4) {
if (nofp) {
/* don't close our setattr open if we'll be restarting... */
}
nfs_open_owner_rele(noop);
}
+#endif
}
return error;
}
VATTR_SET_SUPPORTED(vap, va_access_time);
VATTR_SET_SUPPORTED(vap, va_modify_time);
- if (VATTR_IS_ACTIVE(vap, va_flags)) {
+
+ if (VATTR_IS_ACTIVE(vap, va_flags)
+ ) {
if (vap->va_flags) { /* we don't support setting flags */
if (vap->va_active & ~VNODE_ATTR_va_flags) {
return EINVAL; /* return EINVAL if other attributes also set */
error = lockerror;
}
if (nfsvers == NFS_VER3) {
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
nfsm_chain_get_wcc_data(error, &nmrep, np, &premtime, &wccpostattr, &xid);
nfsmout_if(error);
/* if file hadn't changed, update cached mtime */
fh.fh_len = 0;
goto found;
}
+#if CONFIG_NFS4
if ((nfsvers >= NFS_VER4) && (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER)) {
/* we should never be looking things up in a trigger directory, return nothing */
error = ENOENT;
goto error_return;
}
+#endif
/* do we know this name is too long? */
nmp = VTONMP(dvp);
user_ssize_t tsiz;
off_t txoffset;
struct nfsreq rq, *req = &rq;
+#if CONFIG_NFS4
uint32_t stategenid = 0, restart = 0;
-
+#endif
FSDBG_TOP(536, np, uio_offset(uio), uio_resid(uio), 0);
nmp = NFSTONMP(np);
if (nfs_mount_gone(nmp)) {
error = EIO;
break;
}
+#if CONFIG_NFS4
if (nmp->nm_vers >= NFS_VER4) {
stategenid = nmp->nm_stategenid;
}
+#endif
error = nmp->nm_funcs->nf_read_rpc_async(np, txoffset, len,
vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, &req);
if (!error) {
error = nmp->nm_funcs->nf_read_rpc_async_finish(np, req, uio, &retlen, &eof);
}
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error) &&
(++restart <= nfs_mount_state_max_restarts(nmp))) { /* guard against no progress */
lck_mtx_lock(&nmp->nm_lock);
}
}
}
+#endif
if (error) {
break;
}
}
nfs_buf_write_delayed(bp);
}
+
+
if (np->n_needcommitcnt >= NFS_A_LOT_OF_NEEDCOMMITS) {
nfs_flushcommits(np, 1);
}
out:
nfs_node_lock_force(np);
np->n_wrbusy--;
+ if ((ioflag & IO_SYNC) && !np->n_wrbusy && !np->n_numoutput) {
+ np->n_flag &= ~NMODIFIED;
+ }
nfs_node_unlock(np);
nfs_data_unlock(np);
FSDBG_BOT(515, np, uio_offset(uio), uio_resid(uio), error);
uint64_t wverf = 0, wverf2;
size_t nmwsize, totalsize, tsiz, len, rlen;
struct nfsreq rq, *req = &rq;
- uint32_t stategenid = 0, vrestart = 0, restart = 0;
+#if CONFIG_NFS4
+ uint32_t stategenid = 0, restart = 0;
+#endif
+ uint32_t vrestart = 0;
uio_t uio_save = NULL;
#if DIAGNOSTIC
error = EIO;
break;
}
+#if CONFIG_NFS4
if (nmp->nm_vers >= NFS_VER4) {
stategenid = nmp->nm_stategenid;
}
+#endif
error = nmp->nm_funcs->nf_write_rpc_async(np, uio, len, thd, cred, *iomodep, NULL, &req);
if (!error) {
error = nmp->nm_funcs->nf_write_rpc_async_finish(np, req, &commit, &rlen, &wverf2);
if (nfs_mount_gone(nmp)) {
error = ENXIO;
}
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error) &&
(++restart <= nfs_mount_state_max_restarts(nmp))) { /* guard against no progress */
lck_mtx_lock(&nmp->nm_lock);
}
}
}
+#endif
if (error) {
break;
}
error = lockerror;
}
if (nfsvers == NFS_VER3) {
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
nfsm_chain_get_wcc_data(error, &nmrep, np, &premtime, &wccpostattr, &xid);
if (nfstimespeccmp(&np->n_mtime, &premtime, ==)) {
updatemtime = 1;
struct nfs_vattr nvattr;
fhandle_t fh;
int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
u_int32_t rdev;
u_int64_t xid = 0, dxid;
int nfsvers, gotuid, gotgid;
nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp);
if (nfsvers == NFS_VER3) {
nfsm_chain_add_32(error, &nmreq, vtonfs_type(vap->va_type, nfsvers));
- nfsm_chain_add_v3sattr(error, &nmreq, vap);
+ nfsm_chain_add_v3sattr(nmp, error, &nmreq, vap);
if (vap->va_type == VCHR || vap->va_type == VBLK) {
nfsm_chain_add_32(error, &nmreq, major(vap->va_rdev));
nfsm_chain_add_32(error, &nmreq, minor(vap->va_rdev));
dnp->n_flag &= ~NNEGNCENTRIES;
cache_purge_negatives(dvp);
}
- error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
+ error = nfsm_chain_get_fh_attr(nmp, &nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
}
if (nfsvers == NFS_VER3) {
nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid);
nfsnode_t dnp = VTONFS(dvp);
vnode_t newvp = NULL;
int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0, fmode = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
int nfsvers, gotuid, gotgid;
u_int64_t xid, dxid;
uint32_t val;
struct nfsm_chain nmreq, nmrep;
struct nfsreq rq, *req = &rq;
struct nfs_dulookup dul;
+ int dul_in_progress = 0;
+ int namedattrs;
nmp = VTONMP(dvp);
if (nfs_mount_gone(nmp)) {
return ENXIO;
}
nfsvers = nmp->nm_vers;
+ namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR);
if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) {
return ENAMETOOLONG;
gotuid = VATTR_IS_ACTIVE(vap, va_uid);
gotgid = VATTR_IS_ACTIVE(vap, va_gid);
- if (vap->va_vaflags & VA_EXCLUSIVE) {
+ if ((vap->va_vaflags & VA_EXCLUSIVE)
+ ) {
fmode |= O_EXCL;
if (!VATTR_IS_ACTIVE(vap, va_access_time) || !VATTR_IS_ACTIVE(vap, va_modify_time)) {
vap->va_vaflags |= VA_UTIMES_NULL;
again:
error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx));
- nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ }
nfsm_chain_null(&nmreq);
nfsm_chain_null(&nmrep);
nfsm_chain_add_32(error, &nmreq, create_verf);
} else {
nfsm_chain_add_32(error, &nmreq, NFS_CREATE_UNCHECKED);
- nfsm_chain_add_v3sattr(error, &nmreq, vap);
+ nfsm_chain_add_v3sattr(nmp, error, &nmreq, vap);
}
} else {
nfsm_chain_add_v2sattr(error, &nmreq, vap, 0);
error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_CREATE,
vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req);
if (!error) {
- nfs_dulookup_start(&dul, dnp, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_start(&dul, dnp, ctx);
+ dul_in_progress = 1;
+ }
error = nfs_request_async_finish(req, &nmrep, &xid, &status);
}
dnp->n_flag &= ~NNEGNCENTRIES;
cache_purge_negatives(dvp);
}
- error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
+ error = nfsm_chain_get_fh_attr(nmp, &nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
}
if (nfsvers == NFS_VER3) {
nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid);
newvp = NFSTOV(np);
}
- nfs_dulookup_finish(&dul, dnp, ctx);
+ if (dul_in_progress) {
+ nfs_dulookup_finish(&dul, dnp, ctx);
+ }
if (!busyerror) {
nfs_node_clear_busy(dnp);
}
}
goto again_relock;
}
-
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && (np->n_openflags & N_DELEG_MASK)) {
nfs4_delegation_return(np, 0, vfs_context_thread(ctx), vfs_context_ucred(ctx));
}
-
+#endif
/*
* Purge the name cache so that the chance of a lookup for
* the name succeeding while the remove is in progress is
kauth_cred_t cred)
{
int error = 0, lockerror = ENOENT, status, wccpostattr = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
struct nfsmount *nmp;
int nfsvers;
u_int64_t xid;
/* sillyrename succeeded.*/
tvp = NULL;
}
- } else if (tvp && (nmp->nm_vers >= NFS_VER4) && (tnp->n_openflags & N_DELEG_MASK)) {
+ }
+#if CONFIG_NFS4
+ else if (tvp && (nmp->nm_vers >= NFS_VER4) && (tnp->n_openflags & N_DELEG_MASK)) {
nfs4_delegation_return(tnp, 0, vfs_context_thread(ctx), vfs_context_ucred(ctx));
}
-
+#endif
error = nmp->nm_funcs->nf_rename_rpc(fdnp, fcnp->cn_nameptr, fcnp->cn_namelen,
tdnp, tcnp->cn_nameptr, tcnp->cn_namelen, ctx);
vfs_context_t ctx)
{
int error = 0, lockerror = ENOENT, status, fwccpostattr = 0, twccpostattr = 0;
- struct timespec fpremtime = { 0, 0 }, tpremtime = { 0, 0 };
+ struct timespec fpremtime = { .tv_sec = 0, .tv_nsec = 0 }, tpremtime = { .tv_sec = 0, .tv_nsec = 0 };
struct nfsmount *nmp;
int nfsvers;
u_int64_t xid, txid;
vnode_t tdvp = ap->a_tdvp;
struct componentname *cnp = ap->a_cnp;
int error = 0, lockerror = ENOENT, status, wccpostattr = 0, attrflag = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
struct nfsmount *nmp;
nfsnode_t np = VTONFS(vp);
nfsnode_t tdnp = VTONFS(tdvp);
struct nfs_vattr nvattr;
fhandle_t fh;
int slen, error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
vnode_t newvp = NULL;
int nfsvers, gotuid, gotgid;
u_int64_t xid = 0, dxid;
struct nfsm_chain nmreq, nmrep;
struct nfsreq rq, *req = &rq;
struct nfs_dulookup dul;
+ int namedattrs;
+ int dul_in_progress = 0;
nmp = VTONMP(dvp);
if (nfs_mount_gone(nmp)) {
return ENXIO;
}
nfsvers = nmp->nm_vers;
+ namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR);
slen = strlen(ap->a_target);
if ((nfsvers == NFS_VER2) &&
gotgid = VATTR_IS_ACTIVE(vap, va_gid);
error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx));
- nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ }
nfsm_chain_null(&nmreq);
nfsm_chain_null(&nmrep);
nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize);
nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp);
if (nfsvers == NFS_VER3) {
- nfsm_chain_add_v3sattr(error, &nmreq, vap);
+ nfsm_chain_add_v3sattr(nmp, error, &nmreq, vap);
}
nfsm_chain_add_name(error, &nmreq, ap->a_target, slen, nmp);
if (nfsvers == NFS_VER2) {
error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_SYMLINK,
vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req);
if (!error) {
- nfs_dulookup_start(&dul, dnp, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_start(&dul, dnp, ctx);
+ dul_in_progress = 1;
+ }
error = nfs_request_async_finish(req, &nmrep, &xid, &status);
}
cache_purge_negatives(dvp);
}
if (nfsvers == NFS_VER3) {
- error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
+ error = nfsm_chain_get_fh_attr(nmp, &nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
} else {
fh.fh_len = 0;
}
newvp = NFSTOV(np);
}
- nfs_dulookup_finish(&dul, dnp, ctx);
+ if (dul_in_progress) {
+ nfs_dulookup_finish(&dul, dnp, ctx);
+ }
/*
* Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
nfsnode_t dnp = VTONFS(dvp);
vnode_t newvp = NULL;
int error = 0, lockerror = ENOENT, busyerror = ENOENT, status, wccpostattr = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
int nfsvers, gotuid, gotgid;
u_int64_t xid = 0, dxid;
fhandle_t fh;
struct nfsm_chain nmreq, nmrep;
struct nfsreq rq, *req = &rq;
struct nfs_dulookup dul;
+ int namedattrs;
+ int dul_in_progress = 0;
nmp = VTONMP(dvp);
if (nfs_mount_gone(nmp)) {
return ENXIO;
}
nfsvers = nmp->nm_vers;
+ namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR);
+
if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) {
return ENAMETOOLONG;
}
gotgid = VATTR_IS_ACTIVE(vap, va_gid);
error = busyerror = nfs_node_set_busy(dnp, vfs_context_thread(ctx));
- nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ }
nfsm_chain_null(&nmreq);
nfsm_chain_null(&nmrep);
nfsm_chain_add_fh(error, &nmreq, nfsvers, dnp->n_fhp, dnp->n_fhsize);
nfsm_chain_add_name(error, &nmreq, cnp->cn_nameptr, cnp->cn_namelen, nmp);
if (nfsvers == NFS_VER3) {
- nfsm_chain_add_v3sattr(error, &nmreq, vap);
+ nfsm_chain_add_v3sattr(nmp, error, &nmreq, vap);
} else {
nfsm_chain_add_v2sattr(error, &nmreq, vap, -1);
}
error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_MKDIR,
vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req);
if (!error) {
- nfs_dulookup_start(&dul, dnp, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_start(&dul, dnp, ctx);
+ dul_in_progress = 1;
+ }
error = nfs_request_async_finish(req, &nmrep, &xid, &status);
}
dnp->n_flag &= ~NNEGNCENTRIES;
cache_purge_negatives(dvp);
}
- error = nfsm_chain_get_fh_attr(&nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
+ error = nfsm_chain_get_fh_attr(nmp, &nmrep, dnp, ctx, nfsvers, &xid, &fh, &nvattr);
}
if (nfsvers == NFS_VER3) {
nfsm_chain_get_wcc_data(error, &nmrep, dnp, &premtime, &wccpostattr, &dxid);
newvp = NFSTOV(np);
}
- nfs_dulookup_finish(&dul, dnp, ctx);
+ if (dul_in_progress) {
+ nfs_dulookup_finish(&dul, dnp, ctx);
+ }
/*
* Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
vnode_t dvp = ap->a_dvp;
struct componentname *cnp = ap->a_cnp;
int error = 0, lockerror = ENOENT, status, wccpostattr = 0;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
struct nfsmount *nmp;
nfsnode_t np = VTONFS(vp);
nfsnode_t dnp = VTONFS(dvp);
struct nfsm_chain nmreq, nmrep;
struct nfsreq rq, *req = &rq;
struct nfs_dulookup dul;
+ int namedattrs;
+ int dul_in_progress = 0;
nmp = VTONMP(vp);
if (nfs_mount_gone(nmp)) {
return ENXIO;
}
nfsvers = nmp->nm_vers;
+ namedattrs = (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR);
+
if ((nfsvers == NFS_VER2) && (cnp->cn_namelen > NFS_MAXNAMLEN)) {
return ENAMETOOLONG;
}
return error;
}
- nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_init(&dul, dnp, cnp->cn_nameptr, cnp->cn_namelen, ctx);
+ }
nfsm_chain_null(&nmreq);
nfsm_chain_null(&nmrep);
error = nfs_request_async(dnp, NULL, &nmreq, NFSPROC_RMDIR,
vfs_context_thread(ctx), vfs_context_ucred(ctx), NULL, 0, NULL, &req);
if (!error) {
- nfs_dulookup_start(&dul, dnp, ctx);
+ if (!namedattrs) {
+ nfs_dulookup_start(&dul, dnp, ctx);
+ dul_in_progress = 1;
+ }
error = nfs_request_async_finish(req, &nmrep, &xid, &status);
}
/* nfs_getattr() will check changed and purge caches */
nfs_getattr(dnp, NULL, ctx, wccpostattr ? NGA_CACHED : NGA_UNCACHED);
}
- nfs_dulookup_finish(&dul, dnp, ctx);
+ if (dul_in_progress) {
+ nfs_dulookup_finish(&dul, dnp, ctx);
+ }
nfs_node_clear_busy2(dnp, np);
/*
nfsnode_t dnp = VTONFS(dvp);
struct nfsmount *nmp;
uio_t uio = ap->a_uio;
- int error, nfsvers, extended, numdirent, bigcookies, ptc, done;
+ int error, nfsvers, extended, numdirent, bigcookies, ptc, done, attrcachetimeout;
uint16_t i, iptc, rlen, nlen;
uint64_t cookie, nextcookie, lbn = 0;
struct nfsbuf *bp = NULL;
struct direntry *dp, *dpptc;
struct dirent dent;
char *cp = NULL;
+ struct timeval now;
thread_t thd;
nmp = VTONMP(dvp);
if (uio_resid(uio) == 0) {
return 0;
}
-
+#if CONFIG_NFS4
if ((nfsvers >= NFS_VER4) && (dnp->n_vattr.nva_flags & NFS_FFLAG_TRIGGER)) {
/* trigger directories should never be read, return nothing */
return 0;
}
-
+#endif
thd = vfs_context_thread(ctx);
numdirent = done = 0;
nextcookie = uio_offset(uio);
}
}
+ if (dnp->n_rdirplusstamp_eof && dnp->n_rdirplusstamp_sof) {
+ attrcachetimeout = nfs_attrcachetimeout(dnp);
+ microuptime(&now);
+ if (attrcachetimeout && (now.tv_sec - dnp->n_rdirplusstamp_sof > attrcachetimeout - 1)) {
+ dnp->n_rdirplusstamp_eof = dnp->n_rdirplusstamp_sof = 0;
+ nfs_invaldir(dnp);
+ nfs_node_unlock(dnp);
+ error = nfs_vinvalbuf(dvp, 0, ctx, 1);
+ if (!error) {
+ error = nfs_node_lock(dnp);
+ }
+ if (error) {
+ goto out;
+ }
+ }
+ }
+
/*
* check for need to invalidate when (re)starting at beginning
*/
if ((cnp->cn_namelen == dp->d_namlen) && !strcmp(cnp->cn_nameptr, dp->d_name)) {
fhlen = dp->d_name[dp->d_namlen + 1];
nvattrp = NFS_DIR_BUF_NVATTR(bp, i);
- if ((ndbhp->ndbh_ncgen != bp->nb_np->n_ncgen) || (fhp->fh_len == 0) ||
+ if ((ndbhp->ndbh_ncgen != bp->nb_np->n_ncgen) || (fhlen == 0) ||
(nvattrp->nva_type == VNON) || (nvattrp->nva_fileid == 0)) {
/* entry is not valid */
error = ENOENT;
struct nfsbuflists blist;
daddr64_t lbn, nextlbn;
int dotunder = (cnp->cn_namelen > 2) && (cnp->cn_nameptr[0] == '.') && (cnp->cn_nameptr[1] == '_');
+ int isdot = (cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.');
+ int isdotdot = (cnp->cn_namelen == 2) && (cnp->cn_nameptr[0] == '.') && (cnp->cn_nameptr[1] == '.');
nmp = NFSTONMP(dnp);
if (nfs_mount_gone(nmp)) {
*npp = NULL;
}
+ if (isdot || isdotdot) {
+ return 0;
+ }
+
/* first check most recent buffer (and next one too) */
lbn = dnp->n_lastdbl;
for (i = 0; i < 2; i++) {
if (rdirplus) {
microuptime(&now);
+ if (lastcookie == 0) {
+ dnp->n_rdirplusstamp_sof = now.tv_sec;
+ dnp->n_rdirplusstamp_eof = 0;
+ }
}
/* loop through the entries packing them into the buffer */
nfsmout_if(error);
if (attrflag) {
/* grab attributes */
- error = nfs_parsefattr(&nmrep, NFS_VER3, nvattrp);
+ error = nfs_parsefattr(nmp, &nmrep, NFS_VER3, nvattrp);
nfsmout_if(error);
dp->d_type = IFTODT(VTTOIF(nvattrp->nva_type));
/* fileid is already in d_fileno, so stash xid in attrs */
}
*(time_t*)(&dp->d_name[dp->d_namlen + 1 + fhlen]) = now.tv_sec;
dp->d_reclen = reclen;
+ nfs_rdirplus_update_node_attrs(dnp, dp, &fh, nvattrp, &savedxid);
}
padstart = dp->d_name + dp->d_namlen + 1 + xlen;
ndbhp->ndbh_count++;
ndbhp->ndbh_flags |= (NDB_FULL | NDB_EOF);
nfs_node_lock_force(dnp);
dnp->n_eofcookie = lastcookie;
+ if (rdirplus) {
+ dnp->n_rdirplusstamp_eof = now.tv_sec;
+ }
nfs_node_unlock(dnp);
} else {
more_entries = 1;
/* get the attributes */
if (nfsvers == NFS_VER3) {
- nfsm_chain_postop_attr_get(error, &nmrep, attrflag, nvap);
+ nfsm_chain_postop_attr_get(nmp, error, &nmrep, attrflag, nvap);
nfsm_chain_postop_attr_update(error, &nmrep, dnp, &xid);
if (!error && !attrflag) {
error = nfs3_getattr_rpc(NULL, NFSTOMP(dnp), fhp->fh_data, fhp->fh_len, 0, ctx, nvap, xidp);
}
} else {
- error = nfs_parsefattr(&nmrep, nfsvers, nvap);
+ error = nfs_parsefattr(nmp, &nmrep, nfsvers, nvap);
}
nfsmout:
if (!lockerror) {
{
struct nfsmount *nmp;
int error = 0, lockerror, status, wccpostattr = 0, nfsvers;
- struct timespec premtime = { 0, 0 };
+ struct timespec premtime = { .tv_sec = 0, .tv_nsec = 0 };
u_int64_t xid, newwverf;
uint32_t count32;
struct nfsm_chain nmreq, nmrep;
} else {
nfsap = &nmp->nm_fsattr;
}
- } else if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) {
+ }
+#if CONFIG_NFS4
+ else if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) {
/* no pathconf info cached */
lck_mtx_unlock(&nmp->nm_lock);
NFS_CLEAR_ATTRIBUTES(nfsa.nfsa_bitmap);
}
lck_mtx_lock(&nmp->nm_lock);
nfsap = &nfsa;
- } else {
+ }
+#endif
+ else {
nfsap = &nmp->nm_fsattr;
}
-
switch (ap->a_name) {
case _PC_LINK_MAX:
if (NFS_BITMAP_ISSET(nfsap->nfsa_bitmap, NFS_FATTR_MAXLINK)) {
*ap->a_retval = nfsap->nfsa_maxlink;
+#if CONFIG_NFS4
} else if ((nmp->nm_vers == NFS_VER4) && NFS_BITMAP_ISSET(np->n_vattr.nva_bitmap, NFS_FATTR_MAXLINK)) {
*ap->a_retval = np->n_vattr.nva_maxlink;
+#endif
} else {
error = EINVAL;
}
vfs_context_t ctx = ap->a_context;
vnode_t vp = ap->a_vp;
struct nfsmount *mp = VTONMP(vp);
+ int error = ENOTTY;
+#if CONFIG_NFS_GSS
struct user_nfs_gss_principal gprinc = {};
uint32_t len;
- int error = ENOTTY;
+#endif
if (mp == NULL) {
return ENXIO;
}
-
switch (ap->a_command) {
case F_FULLFSYNC:
if (vnode_vfsisrdonly(vp)) {
}
error = nfs_flush(VTONFS(vp), MNT_WAIT, vfs_context_thread(ctx), 0);
break;
+#if CONFIG_NFS_GSS
case NFS_IOC_DESTROY_CRED:
if (!auth_is_kerberized(mp->nm_auth)) {
return ENOTSUP;
if (gprinc.principal) {
FREE(gprinc.principal, M_TEMP);
}
+#endif /* CONFIG_NFS_GSS */
}
return error;
#define MAXPAGINGREQS 16 /* max outstanding RPCs for pagein/pageout */
struct nfsreq *req[MAXPAGINGREQS];
int nextsend, nextwait;
- uint32_t stategenid = 0, restart = 0;
+#if CONFIG_NFS4
+ uint32_t stategenid = 0;
+#endif
+ uint32_t restart = 0;
kern_return_t kret;
FSDBG(322, np, f_offset, size, flags);
ioaddr += pl_offset;
tryagain:
+#if CONFIG_NFS4
if (nmp->nm_vers >= NFS_VER4) {
stategenid = nmp->nm_stategenid;
}
+#endif
txsize = rxsize = size;
txoffset = f_offset;
rxaddr = ioaddr;
error = nmp->nm_funcs->nf_read_rpc_async_finish(np, req[nextwait], uio, &retsize, NULL);
req[nextwait] = NULL;
nextwait = (nextwait + 1) % MAXPAGINGREQS;
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) {
lck_mtx_lock(&nmp->nm_lock);
if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) {
restart++;
goto cancel;
}
+#endif
if (error) {
FSDBG(322, uio_offset(uio), uio_resid(uio), error, -1);
break;
restart = 0;
if (error) {
+#if CONFIG_NFS4
cancel:
+#endif
/* cancel any outstanding requests */
while (req[nextwait]) {
nfs_request_async_cancel(req[nextwait]);
struct nfsreq *req[MAXPAGINGREQS];
int nextsend, nextwait, wverfset, commit;
uint64_t wverf, wverf2;
- uint32_t stategenid = 0, vrestart = 0, restart = 0, vrestarts = 0, restarts = 0;
+#if CONFIG_NFS4
+ uint32_t stategenid = 0;
+#endif
+ uint32_t vrestart = 0, restart = 0, vrestarts = 0, restarts = 0;
kern_return_t kret;
FSDBG(323, f_offset, size, pl, pl_offset);
&uio_buf, sizeof(uio_buf));
tryagain:
+#if CONFIG_NFS4
if (nmp->nm_vers >= NFS_VER4) {
stategenid = nmp->nm_stategenid;
}
+#endif
wverf = wverf2 = wverfset = 0;
txsize = rxsize = xsize;
txoffset = rxoffset = f_offset;
nfs_node_lock_force(np);
np->n_numoutput--;
nfs_node_unlock(np);
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) {
lck_mtx_lock(&nmp->nm_lock);
if ((error != NFSERR_GRACE) && (stategenid == nmp->nm_stategenid)) {
restart = 1;
goto cancel;
}
+#endif
if (error) {
FSDBG(323, rxoffset, rxsize, error, -1);
break;
uio_addiov(auio, CAST_USER_ADDR_T(rxaddr), remsize);
iomode = NFS_WRITE_UNSTABLE;
error = nfs_write_rpc2(np, auio, thd, cred, &iomode, &wverf2);
+#if CONFIG_NFS4
if ((nmp->nm_vers >= NFS_VER4) && nfs_mount_state_error_should_restart(error)) {
NP(np, "nfs_vnop_pageout: restart: error %d", error);
lck_mtx_lock(&nmp->nm_lock);
restart = 1;
goto cancel;
}
+#endif
if (error) {
FSDBG(323, rxoffset, rxsize, error, -1);
break;
/* This vnode is no longer being monitored, make sure we're not tracking it. */
/* Wait for any in-progress getattr to complete first. */
while (np->n_mflag & NMMONSCANINPROG) {
- struct timespec ts = { 1, 0 };
+ struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
np->n_mflag |= NMMONSCANWANT;
msleep(&np->n_mflag, &nmp->nm_lock, PZERO - 1, "nfswaitmonscan", &ts);
}
}
vnode_notify(NFSTOV(np), events, vap);
}
+
+#endif /* CONFIG_NFS_CLIENT */