17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 /*
32 * Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
33 * All Rights Reserved
34 */
35
36 /*
37 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
38 */
39
40 #include <sys/param.h>
41 #include <sys/types.h>
42 #include <sys/systm.h>
43 #include <sys/cred.h>
44 #include <sys/time.h>
45 #include <sys/vnode.h>
46 #include <sys/vfs.h>
47 #include <sys/vfs_opreg.h>
48 #include <sys/file.h>
49 #include <sys/filio.h>
50 #include <sys/uio.h>
51 #include <sys/buf.h>
52 #include <sys/mman.h>
53 #include <sys/pathname.h>
54 #include <sys/dirent.h>
55 #include <sys/debug.h>
56 #include <sys/vmsystm.h>
57 #include <sys/fcntl.h>
3722 {
3723 int error;
3724
3725 if (vap->va_mask & AT_NOSET)
3726 return (EINVAL);
3727
3728 if (nfs_zone() != VTOMI4(vp)->mi_zone)
3729 return (EIO);
3730
3731 /*
3732 * Don't call secpolicy_vnode_setattr, the client cannot
3733 * use its cached attributes to make security decisions
3734 * as the server may be faking mode bits or mapping uid/gid.
3735 * Always just let the server to the checking.
3736 * If we provide the ability to remove basic priviledges
3737 * to setattr (e.g. basic without chmod) then we will
3738 * need to add a check here before calling the server.
3739 */
3740 error = nfs4setattr(vp, vap, flags, cr, NULL);
3741
3742 if (error == 0 && (vap->va_mask & AT_SIZE) && vap->va_size == 0)
3743 vnevent_truncate(vp, ct);
3744
3745 return (error);
3746 }
3747
3748 /*
3749 * To replace the "guarded" version 3 setattr, we use two types of compound
3750 * setattr requests:
3751 * 1. The "normal" setattr, used when the size of the file isn't being
3752 * changed - { Putfh <fh>; Setattr; Getattr }/
3753 * 2. If the size is changed, precede Setattr with: Getattr; Verify
3754 * with only ctime as the argument. If the server ctime differs from
3755 * what is cached on the client, the verify will fail, but we would
3756 * already have the ctime from the preceding getattr, so just set it
3757 * and retry. Thus the compound here is - { Putfh <fh>; Getattr; Verify;
3758 * Setattr; Getattr }.
3759 *
3760 * The vsecattr_t * input parameter will be non-NULL if ACLs are being set in
3761 * this setattr and NULL if they are not.
3762 */
3763 static int
8046 */
8047 mutex_enter(&rp->r_statelock);
8048 if (rp->r_unldvp != NULL) {
8049 if (strcmp(rp->r_unlname, onm) == 0) {
8050 (void) strncpy(rp->r_unlname, nnm, MAXNAMELEN);
8051 rp->r_unlname[MAXNAMELEN - 1] = '\0';
8052 if (ndvp != rp->r_unldvp) {
8053 VN_RELE(rp->r_unldvp);
8054 rp->r_unldvp = ndvp;
8055 VN_HOLD(ndvp);
8056 }
8057 }
8058 }
8059 mutex_exit(&rp->r_statelock);
8060
8061 /*
8062 * Notify the rename vnevents to source vnode, and to the target
8063 * vnode if it already existed.
8064 */
8065 if (error == 0) {
8066 vnode_t *tvp;
8067 rnode4_t *trp;
8068 /*
8069 * Notify the vnode. Each links is represented by
8070 * a different vnode, in nfsv4.
8071 */
8072 if (nvp) {
8073 trp = VTOR4(nvp);
8074 tvp = nvp;
8075 if (IS_SHADOW(nvp, trp))
8076 tvp = RTOV4(trp);
8077 vnevent_rename_dest(tvp, ndvp, nnm, ct);
8078 }
8079
8080 /*
8081 * if the source and destination directory are not the
8082 * same notify the destination directory.
8083 */
8084 if (VTOR4(odvp) != VTOR4(ndvp)) {
8085 trp = VTOR4(ndvp);
8086 tvp = ndvp;
8087 if (IS_SHADOW(ndvp, trp))
8088 tvp = RTOV4(trp);
8089 vnevent_rename_dest_dir(tvp, ct);
8090 }
8091
8092 trp = VTOR4(ovp);
8093 tvp = ovp;
8094 if (IS_SHADOW(ovp, trp))
8095 tvp = RTOV4(trp);
8096 vnevent_rename_src(tvp, odvp, onm, ct);
8097 }
8098
8099 if (nvp) {
8100 VN_RELE(nvp);
8101 }
8102 VN_RELE(ovp);
8103
8104 nfs_rw_exit(&odrp->r_rwlock);
8105 nfs_rw_exit(&ndrp->r_rwlock);
8106
8107 return (error);
8108 }
8109
8110 /*
8111 * When the parent directory has changed, sv_dfh must be updated
8112 */
8113 static void
8114 update_parentdir_sfh(vnode_t *vp, vnode_t *ndvp)
8115 {
8116 svnode_t *sv = VTOSV(vp);
10985 offset_t offset, cred_t *cr, caller_context_t *ct)
10986 {
10987 int error;
10988
10989 if (nfs_zone() != VTOMI4(vp)->mi_zone)
10990 return (EIO);
10991 ASSERT(vp->v_type == VREG);
10992 if (cmd != F_FREESP)
10993 return (EINVAL);
10994
10995 error = convoff(vp, bfp, 0, offset);
10996 if (!error) {
10997 ASSERT(bfp->l_start >= 0);
10998 if (bfp->l_len == 0) {
10999 struct vattr va;
11000
11001 va.va_mask = AT_SIZE;
11002 va.va_size = bfp->l_start;
11003 error = nfs4setattr(vp, &va, 0, cr, NULL);
11004
11005 if (error == 0 && bfp->l_start == 0)
11006 vnevent_truncate(vp, ct);
11007 } else
11008 error = EINVAL;
11009 }
11010
11011 return (error);
11012 }
11013
11014 /* ARGSUSED */
11015 int
11016 nfs4_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
11017 {
11018 rnode4_t *rp;
11019 rp = VTOR4(vp);
11020
11021 if (vp->v_type == VREG && IS_SHADOW(vp, rp)) {
11022 vp = RTOV4(rp);
11023 }
11024 *vpp = vp;
11025 return (0);
11026 }
|
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 /*
32 * Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
33 * All Rights Reserved
34 */
35
36 /*
37 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
38 */
39
40 #include <sys/param.h>
41 #include <sys/types.h>
42 #include <sys/systm.h>
43 #include <sys/cred.h>
44 #include <sys/time.h>
45 #include <sys/vnode.h>
46 #include <sys/vfs.h>
47 #include <sys/vfs_opreg.h>
48 #include <sys/file.h>
49 #include <sys/filio.h>
50 #include <sys/uio.h>
51 #include <sys/buf.h>
52 #include <sys/mman.h>
53 #include <sys/pathname.h>
54 #include <sys/dirent.h>
55 #include <sys/debug.h>
56 #include <sys/vmsystm.h>
57 #include <sys/fcntl.h>
3722 {
3723 int error;
3724
3725 if (vap->va_mask & AT_NOSET)
3726 return (EINVAL);
3727
3728 if (nfs_zone() != VTOMI4(vp)->mi_zone)
3729 return (EIO);
3730
3731 /*
3732 * Don't call secpolicy_vnode_setattr, the client cannot
3733 * use its cached attributes to make security decisions
3734 * as the server may be faking mode bits or mapping uid/gid.
3735 * Always just let the server to the checking.
3736 * If we provide the ability to remove basic priviledges
3737 * to setattr (e.g. basic without chmod) then we will
3738 * need to add a check here before calling the server.
3739 */
3740 error = nfs4setattr(vp, vap, flags, cr, NULL);
3741
3742 if (error == 0 && (vap->va_mask & AT_SIZE)) {
3743 if (vap->va_size == 0) {
3744 vnevent_truncate(vp, ct);
3745 } else {
3746 vnevent_resize(vp, ct);
3747 }
3748 }
3749
3750 return (error);
3751 }
3752
3753 /*
3754 * To replace the "guarded" version 3 setattr, we use two types of compound
3755 * setattr requests:
3756 * 1. The "normal" setattr, used when the size of the file isn't being
3757 * changed - { Putfh <fh>; Setattr; Getattr }/
3758 * 2. If the size is changed, precede Setattr with: Getattr; Verify
3759 * with only ctime as the argument. If the server ctime differs from
3760 * what is cached on the client, the verify will fail, but we would
3761 * already have the ctime from the preceding getattr, so just set it
3762 * and retry. Thus the compound here is - { Putfh <fh>; Getattr; Verify;
3763 * Setattr; Getattr }.
3764 *
3765 * The vsecattr_t * input parameter will be non-NULL if ACLs are being set in
3766 * this setattr and NULL if they are not.
3767 */
3768 static int
8051 */
8052 mutex_enter(&rp->r_statelock);
8053 if (rp->r_unldvp != NULL) {
8054 if (strcmp(rp->r_unlname, onm) == 0) {
8055 (void) strncpy(rp->r_unlname, nnm, MAXNAMELEN);
8056 rp->r_unlname[MAXNAMELEN - 1] = '\0';
8057 if (ndvp != rp->r_unldvp) {
8058 VN_RELE(rp->r_unldvp);
8059 rp->r_unldvp = ndvp;
8060 VN_HOLD(ndvp);
8061 }
8062 }
8063 }
8064 mutex_exit(&rp->r_statelock);
8065
8066 /*
8067 * Notify the rename vnevents to source vnode, and to the target
8068 * vnode if it already existed.
8069 */
8070 if (error == 0) {
8071 vnode_t *tvp, *tovp;
8072 rnode4_t *trp;
8073
8074 /*
8075 * Notify the vnode. Each links is represented by
8076 * a different vnode, in nfsv4.
8077 */
8078 if (nvp) {
8079 trp = VTOR4(nvp);
8080 tvp = nvp;
8081 if (IS_SHADOW(nvp, trp))
8082 tvp = RTOV4(trp);
8083 vnevent_rename_dest(tvp, ndvp, nnm, ct);
8084 }
8085
8086 trp = VTOR4(ovp);
8087 tovp = ovp;
8088 if (IS_SHADOW(ovp, trp))
8089 tovp = RTOV4(trp);
8090
8091 vnevent_rename_src(tovp, odvp, onm, ct);
8092
8093 trp = VTOR4(ndvp);
8094 tvp = ndvp;
8095
8096 if (IS_SHADOW(ndvp, trp))
8097 tvp = RTOV4(trp);
8098
8099 vnevent_rename_dest_dir(tvp, tovp, nnm, ct);
8100 }
8101
8102 if (nvp) {
8103 VN_RELE(nvp);
8104 }
8105 VN_RELE(ovp);
8106
8107 nfs_rw_exit(&odrp->r_rwlock);
8108 nfs_rw_exit(&ndrp->r_rwlock);
8109
8110 return (error);
8111 }
8112
8113 /*
8114 * When the parent directory has changed, sv_dfh must be updated
8115 */
8116 static void
8117 update_parentdir_sfh(vnode_t *vp, vnode_t *ndvp)
8118 {
8119 svnode_t *sv = VTOSV(vp);
10988 offset_t offset, cred_t *cr, caller_context_t *ct)
10989 {
10990 int error;
10991
10992 if (nfs_zone() != VTOMI4(vp)->mi_zone)
10993 return (EIO);
10994 ASSERT(vp->v_type == VREG);
10995 if (cmd != F_FREESP)
10996 return (EINVAL);
10997
10998 error = convoff(vp, bfp, 0, offset);
10999 if (!error) {
11000 ASSERT(bfp->l_start >= 0);
11001 if (bfp->l_len == 0) {
11002 struct vattr va;
11003
11004 va.va_mask = AT_SIZE;
11005 va.va_size = bfp->l_start;
11006 error = nfs4setattr(vp, &va, 0, cr, NULL);
11007
11008 if (error == 0) {
11009 if (bfp->l_start == 0) {
11010 vnevent_truncate(vp, ct);
11011 } else {
11012 vnevent_resize(vp, ct);
11013 }
11014 }
11015 } else
11016 error = EINVAL;
11017 }
11018
11019 return (error);
11020 }
11021
11022 /* ARGSUSED */
11023 int
11024 nfs4_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
11025 {
11026 rnode4_t *rp;
11027 rp = VTOR4(vp);
11028
11029 if (vp->v_type == VREG && IS_SHADOW(vp, rp)) {
11030 vp = RTOV4(rp);
11031 }
11032 *vpp = vp;
11033 return (0);
11034 }
|