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 */
|