4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015, Joyent, Inc.
  25  */
  26 
  27 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * Portions of this source code were derived from Berkeley 4.3 BSD
  32  * under license from the Regents of the University of California.
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/t_lock.h>
  37 #include <sys/ksynch.h>
  38 #include <sys/param.h>
  39 #include <sys/time.h>
  40 #include <sys/systm.h>
  41 #include <sys/sysmacros.h>
  42 #include <sys/resource.h>
  43 #include <sys/signal.h>
  44 #include <sys/cred.h>
 
 
2176 
2177         /*
2178          * Truncate file.  Must have write permission and not be a directory.
2179          */
2180         if (mask & AT_SIZE) {
2181                 rw_enter(&ip->i_contents, RW_WRITER);
2182                 if (vp->v_type == VDIR) {
2183                         error = EISDIR;
2184                         goto update_inode;
2185                 }
2186                 if (error = ufs_iaccess(ip, IWRITE, cr, 0))
2187                         goto update_inode;
2188 
2189                 rw_exit(&ip->i_contents);
2190                 error = TRANS_ITRUNC(ip, vap->va_size, 0, cr);
2191                 if (error) {
2192                         rw_enter(&ip->i_contents, RW_WRITER);
2193                         goto update_inode;
2194                 }
2195 
2196                 if (error == 0 && vap->va_size)
2197                         vnevent_truncate(vp, ct);
2198         }
2199 
2200         if (ulp) {
2201                 trans_size = (int)TOP_SETATTR_SIZE(ip);
2202                 TRANS_BEGIN_CSYNC(ufsvfsp, issync, TOP_SETATTR, trans_size);
2203                 ++dotrans;
2204         }
2205 
2206         /*
2207          * Acquire i_rwlock after TRANS_BEGIN_CSYNC() if this is a directory.
2208          * This follows the protocol established by
2209          * ufs_link/create/remove/rename/mkdir/rmdir/symlink.
2210          */
2211         if (vp->v_type == VDIR) {
2212                 ufs_tryirwlock_trans(&ip->i_rwlock, RW_WRITER, TOP_SETATTR,
2213                     retry_dir);
2214                 if (indeadlock)
2215                         goto again;
2216                 dorwlock = 1;
2217         }
2218 
 
3709                         error = 0;
3710                 goto errout;
3711         }
3712 
3713         if (error == 0 && tvp != NULL)
3714                 vnevent_rename_dest(tvp, tdvp, tnm, ct);
3715 
3716         /*
3717          * Unlink the source.
3718          * Remove the source entry.  ufs_dirremove() checks that the entry
3719          * still reflects sip, and returns an error if it doesn't.
3720          * If the entry has changed just forget about it.  Release
3721          * the source inode.
3722          */
3723         if ((error = ufs_dirremove(sdp, snm, sip, (struct vnode *)0,
3724             DR_RENAME, cr)) == ENOENT)
3725                 error = 0;
3726 
3727         if (error == 0) {
3728                 vnevent_rename_src(ITOV(sip), sdvp, snm, ct);
3729                 /*
3730                  * Notify the target directory of the rename event
3731                  * if source and target directories are not the same.
3732                  */
3733                 if (sdvp != tdvp)
3734                         vnevent_rename_dest_dir(tdvp, ct);
3735         }
3736 
3737 errout:
3738         if (slot.fbp)
3739                 fbrelse(slot.fbp, S_OTHER);
3740 
3741         rw_exit(&tdp->i_rwlock);
3742         if (sdp != tdp) {
3743                 rw_exit(&sdp->i_rwlock);
3744         }
3745 
3746 unlock:
3747         if (tvp != NULL)
3748                 VN_RELE(tvp);
3749         if (sip != NULL)
3750                 VN_RELE(ITOV(sip));
3751 
3752         if (ulp) {
3753                 TRANS_END_CSYNC(ufsvfsp, error, issync, TOP_RENAME, trans_size);
3754                 ufs_lockfs_end(ulp);
 
4461         return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
4462 }
4463 
4464 /* ARGSUSED */
4465 static int
4466 ufs_space(struct vnode *vp, int cmd, struct flock64 *bfp, int flag,
4467         offset_t offset, cred_t *cr, caller_context_t *ct)
4468 {
4469         struct ufsvfs *ufsvfsp = VTOI(vp)->i_ufsvfs;
4470         struct ulockfs *ulp;
4471         int error;
4472 
4473         if ((error = convoff(vp, bfp, 0, offset)) == 0) {
4474                 if (cmd == F_FREESP) {
4475                         error = ufs_lockfs_begin(ufsvfsp, &ulp,
4476                             ULOCKFS_SPACE_MASK);
4477                         if (error)
4478                                 return (error);
4479                         error = ufs_freesp(vp, bfp, flag, cr);
4480 
4481                         if (error == 0 && bfp->l_start == 0)
4482                                 vnevent_truncate(vp, ct);
4483                 } else if (cmd == F_ALLOCSP) {
4484                         error = ufs_lockfs_begin(ufsvfsp, &ulp,
4485                             ULOCKFS_FALLOCATE_MASK);
4486                         if (error)
4487                                 return (error);
4488                         error = ufs_allocsp(vp, bfp, cr);
4489                 } else
4490                         return (EINVAL); /* Command not handled here */
4491 
4492                 if (ulp)
4493                         ufs_lockfs_end(ulp);
4494 
4495         }
4496         return (error);
4497 }
4498 
4499 /*
4500  * Used to determine if read ahead should be done. Also used to
4501  * to determine when write back occurs.
4502  */
 
 | 
 
 
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2016, Joyent, Inc.
  25  */
  26 
  27 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * Portions of this source code were derived from Berkeley 4.3 BSD
  32  * under license from the Regents of the University of California.
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/t_lock.h>
  37 #include <sys/ksynch.h>
  38 #include <sys/param.h>
  39 #include <sys/time.h>
  40 #include <sys/systm.h>
  41 #include <sys/sysmacros.h>
  42 #include <sys/resource.h>
  43 #include <sys/signal.h>
  44 #include <sys/cred.h>
 
 
2176 
2177         /*
2178          * Truncate file.  Must have write permission and not be a directory.
2179          */
2180         if (mask & AT_SIZE) {
2181                 rw_enter(&ip->i_contents, RW_WRITER);
2182                 if (vp->v_type == VDIR) {
2183                         error = EISDIR;
2184                         goto update_inode;
2185                 }
2186                 if (error = ufs_iaccess(ip, IWRITE, cr, 0))
2187                         goto update_inode;
2188 
2189                 rw_exit(&ip->i_contents);
2190                 error = TRANS_ITRUNC(ip, vap->va_size, 0, cr);
2191                 if (error) {
2192                         rw_enter(&ip->i_contents, RW_WRITER);
2193                         goto update_inode;
2194                 }
2195 
2196                 if (error == 0) {
2197                         if (vap->va_size) {
2198                                 vnevent_truncate(vp, ct);
2199                         } else {
2200                                 vnevent_resize(vp, ct);
2201                         }
2202                 }
2203         }
2204 
2205         if (ulp) {
2206                 trans_size = (int)TOP_SETATTR_SIZE(ip);
2207                 TRANS_BEGIN_CSYNC(ufsvfsp, issync, TOP_SETATTR, trans_size);
2208                 ++dotrans;
2209         }
2210 
2211         /*
2212          * Acquire i_rwlock after TRANS_BEGIN_CSYNC() if this is a directory.
2213          * This follows the protocol established by
2214          * ufs_link/create/remove/rename/mkdir/rmdir/symlink.
2215          */
2216         if (vp->v_type == VDIR) {
2217                 ufs_tryirwlock_trans(&ip->i_rwlock, RW_WRITER, TOP_SETATTR,
2218                     retry_dir);
2219                 if (indeadlock)
2220                         goto again;
2221                 dorwlock = 1;
2222         }
2223 
 
3714                         error = 0;
3715                 goto errout;
3716         }
3717 
3718         if (error == 0 && tvp != NULL)
3719                 vnevent_rename_dest(tvp, tdvp, tnm, ct);
3720 
3721         /*
3722          * Unlink the source.
3723          * Remove the source entry.  ufs_dirremove() checks that the entry
3724          * still reflects sip, and returns an error if it doesn't.
3725          * If the entry has changed just forget about it.  Release
3726          * the source inode.
3727          */
3728         if ((error = ufs_dirremove(sdp, snm, sip, (struct vnode *)0,
3729             DR_RENAME, cr)) == ENOENT)
3730                 error = 0;
3731 
3732         if (error == 0) {
3733                 vnevent_rename_src(ITOV(sip), sdvp, snm, ct);
3734                 vnevent_rename_dest_dir(tdvp, ITOV(sip), tnm, ct);
3735         }
3736 
3737 errout:
3738         if (slot.fbp)
3739                 fbrelse(slot.fbp, S_OTHER);
3740 
3741         rw_exit(&tdp->i_rwlock);
3742         if (sdp != tdp) {
3743                 rw_exit(&sdp->i_rwlock);
3744         }
3745 
3746 unlock:
3747         if (tvp != NULL)
3748                 VN_RELE(tvp);
3749         if (sip != NULL)
3750                 VN_RELE(ITOV(sip));
3751 
3752         if (ulp) {
3753                 TRANS_END_CSYNC(ufsvfsp, error, issync, TOP_RENAME, trans_size);
3754                 ufs_lockfs_end(ulp);
 
4461         return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
4462 }
4463 
4464 /* ARGSUSED */
4465 static int
4466 ufs_space(struct vnode *vp, int cmd, struct flock64 *bfp, int flag,
4467         offset_t offset, cred_t *cr, caller_context_t *ct)
4468 {
4469         struct ufsvfs *ufsvfsp = VTOI(vp)->i_ufsvfs;
4470         struct ulockfs *ulp;
4471         int error;
4472 
4473         if ((error = convoff(vp, bfp, 0, offset)) == 0) {
4474                 if (cmd == F_FREESP) {
4475                         error = ufs_lockfs_begin(ufsvfsp, &ulp,
4476                             ULOCKFS_SPACE_MASK);
4477                         if (error)
4478                                 return (error);
4479                         error = ufs_freesp(vp, bfp, flag, cr);
4480 
4481                         if (error == 0) {
4482                                 if (bfp->l_start == 0) {
4483                                         vnevent_truncate(vp, ct);
4484                                 } else {
4485                                         vnevent_resize(vp, ct);
4486                                 }
4487                         }
4488                 } else if (cmd == F_ALLOCSP) {
4489                         error = ufs_lockfs_begin(ufsvfsp, &ulp,
4490                             ULOCKFS_FALLOCATE_MASK);
4491                         if (error)
4492                                 return (error);
4493                         error = ufs_allocsp(vp, bfp, cr);
4494                 } else
4495                         return (EINVAL); /* Command not handled here */
4496 
4497                 if (ulp)
4498                         ufs_lockfs_end(ulp);
4499 
4500         }
4501         return (error);
4502 }
4503 
4504 /*
4505  * Used to determine if read ahead should be done. Also used to
4506  * to determine when write back occurs.
4507  */
 
 |