1 /* $NetBSD: ulfs_vnops.c,v 1.21 2014/05/17 07:09:09 dholland Exp $ */ 2 /* from NetBSD: ufs_vnops.c,v 1.213 2013/06/08 05:47:02 kardel Exp */ 3 4 /*- 5 * Copyright (c) 2008 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Wasabi Systems, Inc. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1986, 1989, 1993, 1995 35 * The Regents of the University of California. All rights reserved. 36 * (c) UNIX System Laboratories, Inc. 37 * All or some portions of this file are derived from material licensed 38 * to the University of California by American Telephone and Telegraph 39 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 40 * the permission of UNIX System Laboratories, Inc. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95 67 */ 68 69 #include <sys/cdefs.h> 70 __KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.21 2014/05/17 07:09:09 dholland Exp $"); 71 72 #if defined(_KERNEL_OPT) 73 #include "opt_lfs.h" 74 #include "opt_quota.h" 75 #endif 76 77 #include <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/namei.h> 80 #include <sys/resourcevar.h> 81 #include <sys/kernel.h> 82 #include <sys/file.h> 83 #include <sys/stat.h> 84 #include <sys/buf.h> 85 #include <sys/proc.h> 86 #include <sys/mount.h> 87 #include <sys/vnode.h> 88 #include <sys/kmem.h> 89 #include <sys/malloc.h> 90 #include <sys/dirent.h> 91 #include <sys/lockf.h> 92 #include <sys/kauth.h> 93 #include <sys/wapbl.h> 94 #include <sys/fstrans.h> 95 96 #include <miscfs/specfs/specdev.h> 97 #include <miscfs/fifofs/fifo.h> 98 #include <miscfs/genfs/genfs.h> 99 100 #include <ufs/lfs/ulfs_inode.h> 101 #include <ufs/lfs/ulfsmount.h> 102 #include <ufs/lfs/ulfs_bswap.h> 103 #include <ufs/lfs/ulfs_extern.h> 104 #ifdef LFS_DIRHASH 105 #include <ufs/lfs/ulfs_dirhash.h> 106 #endif 107 #include <ufs/lfs/lfs_extern.h> 108 #include <ufs/lfs/lfs.h> 109 110 #include <uvm/uvm.h> 111 112 static int ulfs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *); 113 static int ulfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, 114 struct lwp *); 115 116 /* 117 * Open called. 118 * 119 * Nothing to do. 120 */ 121 /* ARGSUSED */ 122 int 123 ulfs_open(void *v) 124 { 125 struct vop_open_args /* { 126 struct vnode *a_vp; 127 int a_mode; 128 kauth_cred_t a_cred; 129 } */ *ap = v; 130 131 /* 132 * Files marked append-only must be opened for appending. 133 */ 134 if ((VTOI(ap->a_vp)->i_flags & APPEND) && 135 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 136 return (EPERM); 137 return (0); 138 } 139 140 static int 141 ulfs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode, 142 kauth_cred_t cred) 143 { 144 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 145 int error; 146 #endif 147 148 /* 149 * Disallow write attempts on read-only file systems; 150 * unless the file is a socket, fifo, or a block or 151 * character device resident on the file system. 152 */ 153 if (mode & VWRITE) { 154 switch (vp->v_type) { 155 case VDIR: 156 case VLNK: 157 case VREG: 158 if (vp->v_mount->mnt_flag & MNT_RDONLY) 159 return (EROFS); 160 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 161 fstrans_start(vp->v_mount, FSTRANS_SHARED); 162 error = lfs_chkdq(ip, 0, cred, 0); 163 fstrans_done(vp->v_mount); 164 if (error != 0) 165 return error; 166 #endif 167 break; 168 case VBAD: 169 case VBLK: 170 case VCHR: 171 case VSOCK: 172 case VFIFO: 173 case VNON: 174 default: 175 break; 176 } 177 } 178 179 /* If it is a snapshot, nobody gets access to it. */ 180 if ((ip->i_flags & SF_SNAPSHOT)) 181 return (EPERM); 182 /* If immutable bit set, nobody gets to write it. */ 183 if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE)) 184 return (EPERM); 185 186 return 0; 187 } 188 189 static int 190 ulfs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode, 191 kauth_cred_t cred) 192 { 193 194 return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, 195 ip->i_mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, 196 ip->i_mode & ALLPERMS, ip->i_uid, ip->i_gid, mode, cred)); 197 } 198 199 int 200 ulfs_access(void *v) 201 { 202 struct vop_access_args /* { 203 struct vnode *a_vp; 204 int a_mode; 205 kauth_cred_t a_cred; 206 } */ *ap = v; 207 struct vnode *vp; 208 struct inode *ip; 209 mode_t mode; 210 int error; 211 212 vp = ap->a_vp; 213 ip = VTOI(vp); 214 mode = ap->a_mode; 215 216 error = ulfs_check_possible(vp, ip, mode, ap->a_cred); 217 if (error) 218 return error; 219 220 error = ulfs_check_permitted(vp, ip, mode, ap->a_cred); 221 222 return error; 223 } 224 225 /* 226 * Set attribute vnode op. called from several syscalls 227 */ 228 int 229 ulfs_setattr(void *v) 230 { 231 struct vop_setattr_args /* { 232 struct vnode *a_vp; 233 struct vattr *a_vap; 234 kauth_cred_t a_cred; 235 } */ *ap = v; 236 struct vattr *vap; 237 struct vnode *vp; 238 struct inode *ip; 239 kauth_cred_t cred; 240 struct lwp *l; 241 int error; 242 kauth_action_t action; 243 bool changing_sysflags; 244 245 vap = ap->a_vap; 246 vp = ap->a_vp; 247 ip = VTOI(vp); 248 cred = ap->a_cred; 249 l = curlwp; 250 action = KAUTH_VNODE_WRITE_FLAGS; 251 changing_sysflags = false; 252 253 /* 254 * Check for unsettable attributes. 255 */ 256 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 257 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 258 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 259 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 260 return (EINVAL); 261 } 262 263 fstrans_start(vp->v_mount, FSTRANS_SHARED); 264 265 if (vap->va_flags != VNOVAL) { 266 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 267 error = EROFS; 268 goto out; 269 } 270 271 /* Snapshot flag cannot be set or cleared */ 272 if ((vap->va_flags & (SF_SNAPSHOT | SF_SNAPINVAL)) != 273 (ip->i_flags & (SF_SNAPSHOT | SF_SNAPINVAL))) { 274 error = EPERM; 275 goto out; 276 } 277 278 if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) { 279 action |= KAUTH_VNODE_HAS_SYSFLAGS; 280 } 281 282 if ((vap->va_flags & SF_SETTABLE) != (ip->i_flags & SF_SETTABLE)) { 283 action |= KAUTH_VNODE_WRITE_SYSFLAGS; 284 changing_sysflags = true; 285 } 286 287 error = kauth_authorize_vnode(cred, action, vp, NULL, 288 genfs_can_chflags(cred, vp->v_type, ip->i_uid, 289 changing_sysflags)); 290 if (error) 291 goto out; 292 293 if (changing_sysflags) { 294 ip->i_flags = vap->va_flags; 295 DIP_ASSIGN(ip, flags, ip->i_flags); 296 } else { 297 ip->i_flags &= SF_SETTABLE; 298 ip->i_flags |= (vap->va_flags & UF_SETTABLE); 299 DIP_ASSIGN(ip, flags, ip->i_flags); 300 } 301 ip->i_flag |= IN_CHANGE; 302 if (vap->va_flags & (IMMUTABLE | APPEND)) { 303 error = 0; 304 goto out; 305 } 306 } 307 if (ip->i_flags & (IMMUTABLE | APPEND)) { 308 error = EPERM; 309 goto out; 310 } 311 /* 312 * Go through the fields and update iff not VNOVAL. 313 */ 314 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 315 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 316 error = EROFS; 317 goto out; 318 } 319 error = ulfs_chown(vp, vap->va_uid, vap->va_gid, cred, l); 320 if (error) 321 goto out; 322 } 323 if (vap->va_size != VNOVAL) { 324 /* 325 * Disallow write attempts on read-only file systems; 326 * unless the file is a socket, fifo, or a block or 327 * character device resident on the file system. 328 */ 329 switch (vp->v_type) { 330 case VDIR: 331 error = EISDIR; 332 goto out; 333 case VCHR: 334 case VBLK: 335 case VFIFO: 336 break; 337 case VREG: 338 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 339 error = EROFS; 340 goto out; 341 } 342 if ((ip->i_flags & SF_SNAPSHOT) != 0) { 343 error = EPERM; 344 goto out; 345 } 346 error = lfs_truncate(vp, vap->va_size, 0, cred); 347 if (error) 348 goto out; 349 break; 350 default: 351 error = EOPNOTSUPP; 352 goto out; 353 } 354 } 355 ip = VTOI(vp); 356 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || 357 vap->va_birthtime.tv_sec != VNOVAL) { 358 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 359 error = EROFS; 360 goto out; 361 } 362 if ((ip->i_flags & SF_SNAPSHOT) != 0) { 363 error = EPERM; 364 goto out; 365 } 366 error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, 367 NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred)); 368 if (error) 369 goto out; 370 if (vap->va_atime.tv_sec != VNOVAL) 371 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) 372 ip->i_flag |= IN_ACCESS; 373 if (vap->va_mtime.tv_sec != VNOVAL) { 374 ip->i_flag |= IN_CHANGE | IN_UPDATE; 375 if (vp->v_mount->mnt_flag & MNT_RELATIME) 376 ip->i_flag |= IN_ACCESS; 377 } 378 if (vap->va_birthtime.tv_sec != VNOVAL && 379 ip->i_ump->um_fstype == ULFS2) { 380 ip->i_ffs2_birthtime = vap->va_birthtime.tv_sec; 381 ip->i_ffs2_birthnsec = vap->va_birthtime.tv_nsec; 382 } 383 error = lfs_update(vp, &vap->va_atime, &vap->va_mtime, 0); 384 if (error) 385 goto out; 386 } 387 error = 0; 388 if (vap->va_mode != (mode_t)VNOVAL) { 389 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 390 error = EROFS; 391 goto out; 392 } 393 if ((ip->i_flags & SF_SNAPSHOT) != 0 && 394 (vap->va_mode & (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | 395 S_IXOTH | S_IWOTH))) { 396 error = EPERM; 397 goto out; 398 } 399 error = ulfs_chmod(vp, (int)vap->va_mode, cred, l); 400 } 401 VN_KNOTE(vp, NOTE_ATTRIB); 402 out: 403 fstrans_done(vp->v_mount); 404 return (error); 405 } 406 407 /* 408 * Change the mode on a file. 409 * Inode must be locked before calling. 410 */ 411 static int 412 ulfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l) 413 { 414 struct inode *ip; 415 int error; 416 417 ip = VTOI(vp); 418 419 error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, 420 NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, ip->i_gid, mode)); 421 if (error) 422 return (error); 423 424 fstrans_start(vp->v_mount, FSTRANS_SHARED); 425 ip->i_mode &= ~ALLPERMS; 426 ip->i_mode |= (mode & ALLPERMS); 427 ip->i_flag |= IN_CHANGE; 428 DIP_ASSIGN(ip, mode, ip->i_mode); 429 fstrans_done(vp->v_mount); 430 return (0); 431 } 432 433 /* 434 * Perform chown operation on inode ip; 435 * inode must be locked prior to call. 436 */ 437 static int 438 ulfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred, 439 struct lwp *l) 440 { 441 struct inode *ip; 442 int error = 0; 443 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 444 uid_t ouid; 445 gid_t ogid; 446 int64_t change; 447 #endif 448 ip = VTOI(vp); 449 error = 0; 450 451 if (uid == (uid_t)VNOVAL) 452 uid = ip->i_uid; 453 if (gid == (gid_t)VNOVAL) 454 gid = ip->i_gid; 455 456 error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, 457 NULL, genfs_can_chown(cred, ip->i_uid, ip->i_gid, uid, gid)); 458 if (error) 459 return (error); 460 461 fstrans_start(vp->v_mount, FSTRANS_SHARED); 462 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 463 ogid = ip->i_gid; 464 ouid = ip->i_uid; 465 change = DIP(ip, blocks); 466 (void) lfs_chkdq(ip, -change, cred, 0); 467 (void) lfs_chkiq(ip, -1, cred, 0); 468 #endif 469 ip->i_gid = gid; 470 DIP_ASSIGN(ip, gid, gid); 471 ip->i_uid = uid; 472 DIP_ASSIGN(ip, uid, uid); 473 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 474 if ((error = lfs_chkdq(ip, change, cred, 0)) == 0) { 475 if ((error = lfs_chkiq(ip, 1, cred, 0)) == 0) 476 goto good; 477 else 478 (void) lfs_chkdq(ip, -change, cred, FORCE); 479 } 480 ip->i_gid = ogid; 481 DIP_ASSIGN(ip, gid, ogid); 482 ip->i_uid = ouid; 483 DIP_ASSIGN(ip, uid, ouid); 484 (void) lfs_chkdq(ip, change, cred, FORCE); 485 (void) lfs_chkiq(ip, 1, cred, FORCE); 486 fstrans_done(vp->v_mount); 487 return (error); 488 good: 489 #endif /* LFS_QUOTA || LFS_QUOTA2 */ 490 ip->i_flag |= IN_CHANGE; 491 fstrans_done(vp->v_mount); 492 return (0); 493 } 494 495 int 496 ulfs_remove(void *v) 497 { 498 struct vop_remove_args /* { 499 struct vnode *a_dvp; 500 struct vnode *a_vp; 501 struct componentname *a_cnp; 502 } */ *ap = v; 503 struct vnode *vp, *dvp; 504 struct inode *ip; 505 int error; 506 struct ulfs_lookup_results *ulr; 507 508 vp = ap->a_vp; 509 dvp = ap->a_dvp; 510 ip = VTOI(vp); 511 512 /* XXX should handle this material another way */ 513 ulr = &VTOI(dvp)->i_crap; 514 ULFS_CHECK_CRAPCOUNTER(VTOI(dvp)); 515 516 fstrans_start(dvp->v_mount, FSTRANS_SHARED); 517 if (vp->v_type == VDIR || (ip->i_flags & (IMMUTABLE | APPEND)) || 518 (VTOI(dvp)->i_flags & APPEND)) 519 error = EPERM; 520 else { 521 error = ulfs_dirremove(dvp, ulr, 522 ip, ap->a_cnp->cn_flags, 0); 523 } 524 VN_KNOTE(vp, NOTE_DELETE); 525 VN_KNOTE(dvp, NOTE_WRITE); 526 if (dvp == vp) 527 vrele(vp); 528 else 529 vput(vp); 530 vput(dvp); 531 fstrans_done(dvp->v_mount); 532 return (error); 533 } 534 535 /* 536 * ulfs_link: create hard link. 537 */ 538 int 539 ulfs_link(void *v) 540 { 541 struct vop_link_args /* { 542 struct vnode *a_dvp; 543 struct vnode *a_vp; 544 struct componentname *a_cnp; 545 } */ *ap = v; 546 struct vnode *dvp = ap->a_dvp; 547 struct vnode *vp = ap->a_vp; 548 struct componentname *cnp = ap->a_cnp; 549 struct inode *ip; 550 struct lfs_direct *newdir; 551 int error; 552 struct ulfs_lookup_results *ulr; 553 554 KASSERT(dvp != vp); 555 KASSERT(vp->v_type != VDIR); 556 KASSERT(dvp->v_mount == vp->v_mount); 557 558 /* XXX should handle this material another way */ 559 ulr = &VTOI(dvp)->i_crap; 560 ULFS_CHECK_CRAPCOUNTER(VTOI(dvp)); 561 562 fstrans_start(dvp->v_mount, FSTRANS_SHARED); 563 error = vn_lock(vp, LK_EXCLUSIVE); 564 if (error) { 565 VOP_ABORTOP(dvp, cnp); 566 goto out2; 567 } 568 ip = VTOI(vp); 569 if ((nlink_t)ip->i_nlink >= LINK_MAX) { 570 VOP_ABORTOP(dvp, cnp); 571 error = EMLINK; 572 goto out1; 573 } 574 if (ip->i_flags & (IMMUTABLE | APPEND)) { 575 VOP_ABORTOP(dvp, cnp); 576 error = EPERM; 577 goto out1; 578 } 579 ip->i_nlink++; 580 DIP_ASSIGN(ip, nlink, ip->i_nlink); 581 ip->i_flag |= IN_CHANGE; 582 error = lfs_update(vp, NULL, NULL, UPDATE_DIROP); 583 if (!error) { 584 newdir = pool_cache_get(ulfs_direct_cache, PR_WAITOK); 585 ulfs_makedirentry(ip, cnp, newdir); 586 error = ulfs_direnter(dvp, ulr, vp, newdir, cnp, NULL); 587 pool_cache_put(ulfs_direct_cache, newdir); 588 } 589 if (error) { 590 ip->i_nlink--; 591 DIP_ASSIGN(ip, nlink, ip->i_nlink); 592 ip->i_flag |= IN_CHANGE; 593 } 594 out1: 595 VOP_UNLOCK(vp); 596 out2: 597 VN_KNOTE(vp, NOTE_LINK); 598 VN_KNOTE(dvp, NOTE_WRITE); 599 vput(dvp); 600 fstrans_done(dvp->v_mount); 601 return (error); 602 } 603 604 /* 605 * whiteout vnode call 606 */ 607 int 608 ulfs_whiteout(void *v) 609 { 610 struct vop_whiteout_args /* { 611 struct vnode *a_dvp; 612 struct componentname *a_cnp; 613 int a_flags; 614 } */ *ap = v; 615 struct vnode *dvp = ap->a_dvp; 616 struct componentname *cnp = ap->a_cnp; 617 struct lfs_direct *newdir; 618 int error; 619 struct ulfsmount *ump = VFSTOULFS(dvp->v_mount); 620 struct lfs *fs = ump->um_lfs; 621 struct ulfs_lookup_results *ulr; 622 623 /* XXX should handle this material another way */ 624 ulr = &VTOI(dvp)->i_crap; 625 ULFS_CHECK_CRAPCOUNTER(VTOI(dvp)); 626 627 error = 0; 628 switch (ap->a_flags) { 629 case LOOKUP: 630 /* 4.4 format directories support whiteout operations */ 631 if (fs->um_maxsymlinklen > 0) 632 return (0); 633 return (EOPNOTSUPP); 634 635 case CREATE: 636 /* create a new directory whiteout */ 637 fstrans_start(dvp->v_mount, FSTRANS_SHARED); 638 #ifdef DIAGNOSTIC 639 if (fs->um_maxsymlinklen <= 0) 640 panic("ulfs_whiteout: old format filesystem"); 641 #endif 642 643 newdir = pool_cache_get(ulfs_direct_cache, PR_WAITOK); 644 newdir->d_ino = ULFS_WINO; 645 newdir->d_namlen = cnp->cn_namelen; 646 memcpy(newdir->d_name, cnp->cn_nameptr, 647 (size_t)cnp->cn_namelen); 648 newdir->d_name[cnp->cn_namelen] = '\0'; 649 newdir->d_type = LFS_DT_WHT; 650 error = ulfs_direnter(dvp, ulr, NULL, newdir, cnp, NULL); 651 pool_cache_put(ulfs_direct_cache, newdir); 652 break; 653 654 case DELETE: 655 /* remove an existing directory whiteout */ 656 fstrans_start(dvp->v_mount, FSTRANS_SHARED); 657 #ifdef DIAGNOSTIC 658 if (fs->um_maxsymlinklen <= 0) 659 panic("ulfs_whiteout: old format filesystem"); 660 #endif 661 662 cnp->cn_flags &= ~DOWHITEOUT; 663 error = ulfs_dirremove(dvp, ulr, NULL, cnp->cn_flags, 0); 664 break; 665 default: 666 panic("ulfs_whiteout: unknown op"); 667 /* NOTREACHED */ 668 } 669 fstrans_done(dvp->v_mount); 670 return (error); 671 } 672 673 int 674 ulfs_rmdir(void *v) 675 { 676 struct vop_rmdir_args /* { 677 struct vnode *a_dvp; 678 struct vnode *a_vp; 679 struct componentname *a_cnp; 680 } */ *ap = v; 681 struct vnode *vp, *dvp; 682 struct componentname *cnp; 683 struct inode *ip, *dp; 684 int error; 685 struct ulfs_lookup_results *ulr; 686 687 vp = ap->a_vp; 688 dvp = ap->a_dvp; 689 cnp = ap->a_cnp; 690 ip = VTOI(vp); 691 dp = VTOI(dvp); 692 693 /* XXX should handle this material another way */ 694 ulr = &dp->i_crap; 695 ULFS_CHECK_CRAPCOUNTER(dp); 696 697 /* 698 * No rmdir "." or of mounted directories please. 699 */ 700 if (dp == ip || vp->v_mountedhere != NULL) { 701 if (dp == ip) 702 vrele(dvp); 703 else 704 vput(dvp); 705 vput(vp); 706 return (EINVAL); 707 } 708 709 fstrans_start(dvp->v_mount, FSTRANS_SHARED); 710 711 /* 712 * Do not remove a directory that is in the process of being renamed. 713 * Verify that the directory is empty (and valid). (Rmdir ".." won't 714 * be valid since ".." will contain a reference to the current 715 * directory and thus be non-empty.) 716 */ 717 error = 0; 718 if (ip->i_nlink != 2 || 719 !ulfs_dirempty(ip, dp->i_number, cnp->cn_cred)) { 720 error = ENOTEMPTY; 721 goto out; 722 } 723 if ((dp->i_flags & APPEND) || 724 (ip->i_flags & (IMMUTABLE | APPEND))) { 725 error = EPERM; 726 goto out; 727 } 728 /* 729 * Delete reference to directory before purging 730 * inode. If we crash in between, the directory 731 * will be reattached to lost+found, 732 */ 733 error = ulfs_dirremove(dvp, ulr, ip, cnp->cn_flags, 1); 734 if (error) { 735 goto out; 736 } 737 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 738 cache_purge(dvp); 739 /* 740 * Truncate inode. The only stuff left in the directory is "." and 741 * "..". The "." reference is inconsequential since we're quashing 742 * it. 743 */ 744 dp->i_nlink--; 745 DIP_ASSIGN(dp, nlink, dp->i_nlink); 746 dp->i_flag |= IN_CHANGE; 747 ip->i_nlink--; 748 DIP_ASSIGN(ip, nlink, ip->i_nlink); 749 ip->i_flag |= IN_CHANGE; 750 error = lfs_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred); 751 cache_purge(vp); 752 #ifdef LFS_DIRHASH 753 if (ip->i_dirhash != NULL) 754 ulfsdirhash_free(ip); 755 #endif 756 out: 757 VN_KNOTE(vp, NOTE_DELETE); 758 vput(vp); 759 fstrans_done(dvp->v_mount); 760 vput(dvp); 761 return (error); 762 } 763 764 /* 765 * Vnode op for reading directories. 766 * 767 * This routine handles converting from the on-disk directory format 768 * "struct lfs_direct" to the in-memory format "struct dirent" as well as 769 * byte swapping the entries if necessary. 770 */ 771 int 772 ulfs_readdir(void *v) 773 { 774 struct vop_readdir_args /* { 775 struct vnode *a_vp; 776 struct uio *a_uio; 777 kauth_cred_t a_cred; 778 int *a_eofflag; 779 off_t **a_cookies; 780 int *ncookies; 781 } */ *ap = v; 782 struct vnode *vp = ap->a_vp; 783 struct lfs_direct *cdp, *ecdp; 784 struct dirent *ndp; 785 char *cdbuf, *ndbuf, *endp; 786 struct uio auio, *uio; 787 struct iovec aiov; 788 int error; 789 size_t count, ccount, rcount, cdbufsz, ndbufsz; 790 off_t off, *ccp; 791 off_t startoff; 792 size_t skipbytes; 793 struct ulfsmount *ump = VFSTOULFS(vp->v_mount); 794 struct lfs *fs = ump->um_lfs; 795 int nswap = ULFS_MPNEEDSWAP(fs); 796 #if BYTE_ORDER == LITTLE_ENDIAN 797 int needswap = fs->um_maxsymlinklen <= 0 && nswap == 0; 798 #else 799 int needswap = fs->um_maxsymlinklen <= 0 && nswap != 0; 800 #endif 801 uio = ap->a_uio; 802 count = uio->uio_resid; 803 rcount = count - ((uio->uio_offset + count) & (fs->um_dirblksiz - 1)); 804 805 if (rcount < _DIRENT_MINSIZE(cdp) || count < _DIRENT_MINSIZE(ndp)) 806 return EINVAL; 807 808 startoff = uio->uio_offset & ~(fs->um_dirblksiz - 1); 809 skipbytes = uio->uio_offset - startoff; 810 rcount += skipbytes; 811 812 auio.uio_iov = &aiov; 813 auio.uio_iovcnt = 1; 814 auio.uio_offset = startoff; 815 auio.uio_resid = rcount; 816 UIO_SETUP_SYSSPACE(&auio); 817 auio.uio_rw = UIO_READ; 818 cdbufsz = rcount; 819 cdbuf = kmem_alloc(cdbufsz, KM_SLEEP); 820 aiov.iov_base = cdbuf; 821 aiov.iov_len = rcount; 822 error = VOP_READ(vp, &auio, 0, ap->a_cred); 823 if (error != 0) { 824 kmem_free(cdbuf, cdbufsz); 825 return error; 826 } 827 828 rcount -= auio.uio_resid; 829 830 cdp = (struct lfs_direct *)(void *)cdbuf; 831 ecdp = (struct lfs_direct *)(void *)&cdbuf[rcount]; 832 833 ndbufsz = count; 834 ndbuf = kmem_alloc(ndbufsz, KM_SLEEP); 835 ndp = (struct dirent *)(void *)ndbuf; 836 endp = &ndbuf[count]; 837 838 off = uio->uio_offset; 839 if (ap->a_cookies) { 840 ccount = rcount / _DIRENT_RECLEN(cdp, 1); 841 ccp = *(ap->a_cookies) = malloc(ccount * sizeof(*ccp), 842 M_TEMP, M_WAITOK); 843 } else { 844 /* XXX: GCC */ 845 ccount = 0; 846 ccp = NULL; 847 } 848 849 while (cdp < ecdp) { 850 cdp->d_reclen = ulfs_rw16(cdp->d_reclen, nswap); 851 if (skipbytes > 0) { 852 if (cdp->d_reclen <= skipbytes) { 853 skipbytes -= cdp->d_reclen; 854 cdp = _DIRENT_NEXT(cdp); 855 continue; 856 } 857 /* 858 * invalid cookie. 859 */ 860 error = EINVAL; 861 goto out; 862 } 863 if (cdp->d_reclen == 0) { 864 struct dirent *ondp = ndp; 865 ndp->d_reclen = _DIRENT_MINSIZE(ndp); 866 ndp = _DIRENT_NEXT(ndp); 867 ondp->d_reclen = 0; 868 cdp = ecdp; 869 break; 870 } 871 if (needswap) { 872 ndp->d_type = cdp->d_namlen; 873 ndp->d_namlen = cdp->d_type; 874 } else { 875 ndp->d_type = cdp->d_type; 876 ndp->d_namlen = cdp->d_namlen; 877 } 878 ndp->d_reclen = _DIRENT_RECLEN(ndp, ndp->d_namlen); 879 if ((char *)(void *)ndp + ndp->d_reclen + 880 _DIRENT_MINSIZE(ndp) > endp) 881 break; 882 ndp->d_fileno = ulfs_rw32(cdp->d_ino, nswap); 883 (void)memcpy(ndp->d_name, cdp->d_name, ndp->d_namlen); 884 memset(&ndp->d_name[ndp->d_namlen], 0, 885 ndp->d_reclen - _DIRENT_NAMEOFF(ndp) - ndp->d_namlen); 886 off += cdp->d_reclen; 887 if (ap->a_cookies) { 888 KASSERT(ccp - *(ap->a_cookies) < ccount); 889 *(ccp++) = off; 890 } 891 ndp = _DIRENT_NEXT(ndp); 892 cdp = _DIRENT_NEXT(cdp); 893 } 894 895 count = ((char *)(void *)ndp - ndbuf); 896 error = uiomove(ndbuf, count, uio); 897 out: 898 if (ap->a_cookies) { 899 if (error) { 900 free(*(ap->a_cookies), M_TEMP); 901 *(ap->a_cookies) = NULL; 902 *(ap->a_ncookies) = 0; 903 } else { 904 *ap->a_ncookies = ccp - *(ap->a_cookies); 905 } 906 } 907 uio->uio_offset = off; 908 kmem_free(ndbuf, ndbufsz); 909 kmem_free(cdbuf, cdbufsz); 910 *ap->a_eofflag = VTOI(vp)->i_size <= uio->uio_offset; 911 return error; 912 } 913 914 /* 915 * Return target name of a symbolic link 916 */ 917 int 918 ulfs_readlink(void *v) 919 { 920 struct vop_readlink_args /* { 921 struct vnode *a_vp; 922 struct uio *a_uio; 923 kauth_cred_t a_cred; 924 } */ *ap = v; 925 struct vnode *vp = ap->a_vp; 926 struct inode *ip = VTOI(vp); 927 struct ulfsmount *ump = VFSTOULFS(vp->v_mount); 928 struct lfs *fs = ump->um_lfs; 929 int isize; 930 931 isize = ip->i_size; 932 if (isize < fs->um_maxsymlinklen || 933 (fs->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) { 934 uiomove((char *)SHORTLINK(ip), isize, ap->a_uio); 935 return (0); 936 } 937 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 938 } 939 940 /* 941 * Print out the contents of an inode. 942 */ 943 int 944 ulfs_print(void *v) 945 { 946 struct vop_print_args /* { 947 struct vnode *a_vp; 948 } */ *ap = v; 949 struct vnode *vp; 950 struct inode *ip; 951 952 vp = ap->a_vp; 953 ip = VTOI(vp); 954 printf("tag VT_ULFS, ino %llu, on dev %llu, %llu", 955 (unsigned long long)ip->i_number, 956 (unsigned long long)major(ip->i_dev), 957 (unsigned long long)minor(ip->i_dev)); 958 printf(" flags 0x%x, nlink %d\n", 959 ip->i_flag, ip->i_nlink); 960 printf("\tmode 0%o, owner %d, group %d, size %qd", 961 ip->i_mode, ip->i_uid, ip->i_gid, 962 (long long)ip->i_size); 963 if (vp->v_type == VFIFO) 964 VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v); 965 printf("\n"); 966 return (0); 967 } 968 969 /* 970 * Read wrapper for special devices. 971 */ 972 int 973 ulfsspec_read(void *v) 974 { 975 struct vop_read_args /* { 976 struct vnode *a_vp; 977 struct uio *a_uio; 978 int a_ioflag; 979 kauth_cred_t a_cred; 980 } */ *ap = v; 981 982 /* 983 * Set access flag. 984 */ 985 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0) 986 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 987 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap)); 988 } 989 990 /* 991 * Write wrapper for special devices. 992 */ 993 int 994 ulfsspec_write(void *v) 995 { 996 struct vop_write_args /* { 997 struct vnode *a_vp; 998 struct uio *a_uio; 999 int a_ioflag; 1000 kauth_cred_t a_cred; 1001 } */ *ap = v; 1002 1003 /* 1004 * Set update and change flags. 1005 */ 1006 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0) 1007 VTOI(ap->a_vp)->i_flag |= IN_MODIFY; 1008 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap)); 1009 } 1010 1011 /* 1012 * Read wrapper for fifo's 1013 */ 1014 int 1015 ulfsfifo_read(void *v) 1016 { 1017 struct vop_read_args /* { 1018 struct vnode *a_vp; 1019 struct uio *a_uio; 1020 int a_ioflag; 1021 kauth_cred_t a_cred; 1022 } */ *ap = v; 1023 1024 /* 1025 * Set access flag. 1026 */ 1027 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 1028 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap)); 1029 } 1030 1031 /* 1032 * Write wrapper for fifo's. 1033 */ 1034 int 1035 ulfsfifo_write(void *v) 1036 { 1037 struct vop_write_args /* { 1038 struct vnode *a_vp; 1039 struct uio *a_uio; 1040 int a_ioflag; 1041 kauth_cred_t a_cred; 1042 } */ *ap = v; 1043 1044 /* 1045 * Set update and change flags. 1046 */ 1047 VTOI(ap->a_vp)->i_flag |= IN_MODIFY; 1048 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap)); 1049 } 1050 1051 /* 1052 * Return POSIX pathconf information applicable to ulfs filesystems. 1053 */ 1054 int 1055 ulfs_pathconf(void *v) 1056 { 1057 struct vop_pathconf_args /* { 1058 struct vnode *a_vp; 1059 int a_name; 1060 register_t *a_retval; 1061 } */ *ap = v; 1062 1063 switch (ap->a_name) { 1064 case _PC_LINK_MAX: 1065 *ap->a_retval = LINK_MAX; 1066 return (0); 1067 case _PC_NAME_MAX: 1068 *ap->a_retval = LFS_MAXNAMLEN; 1069 return (0); 1070 case _PC_PATH_MAX: 1071 *ap->a_retval = PATH_MAX; 1072 return (0); 1073 case _PC_PIPE_BUF: 1074 *ap->a_retval = PIPE_BUF; 1075 return (0); 1076 case _PC_CHOWN_RESTRICTED: 1077 *ap->a_retval = 1; 1078 return (0); 1079 case _PC_NO_TRUNC: 1080 *ap->a_retval = 1; 1081 return (0); 1082 case _PC_SYNC_IO: 1083 *ap->a_retval = 1; 1084 return (0); 1085 case _PC_FILESIZEBITS: 1086 *ap->a_retval = 42; 1087 return (0); 1088 case _PC_SYMLINK_MAX: 1089 *ap->a_retval = MAXPATHLEN; 1090 return (0); 1091 case _PC_2_SYMLINKS: 1092 *ap->a_retval = 1; 1093 return (0); 1094 default: 1095 return (EINVAL); 1096 } 1097 /* NOTREACHED */ 1098 } 1099 1100 /* 1101 * Advisory record locking support 1102 */ 1103 int 1104 ulfs_advlock(void *v) 1105 { 1106 struct vop_advlock_args /* { 1107 struct vnode *a_vp; 1108 void * a_id; 1109 int a_op; 1110 struct flock *a_fl; 1111 int a_flags; 1112 } */ *ap = v; 1113 struct inode *ip; 1114 1115 ip = VTOI(ap->a_vp); 1116 return lf_advlock(ap, &ip->i_lockf, ip->i_size); 1117 } 1118 1119 /* 1120 * Initialize the vnode associated with a new inode, handle aliased 1121 * vnodes. 1122 */ 1123 void 1124 ulfs_vinit(struct mount *mntp, int (**specops)(void *), int (**fifoops)(void *), 1125 struct vnode **vpp) 1126 { 1127 struct timeval tv; 1128 struct inode *ip; 1129 struct vnode *vp; 1130 dev_t rdev; 1131 struct ulfsmount *ump; 1132 1133 vp = *vpp; 1134 ip = VTOI(vp); 1135 switch(vp->v_type = IFTOVT(ip->i_mode)) { 1136 case VCHR: 1137 case VBLK: 1138 vp->v_op = specops; 1139 ump = ip->i_ump; 1140 if (ump->um_fstype == ULFS1) 1141 rdev = (dev_t)ulfs_rw32(ip->i_ffs1_rdev, 1142 ULFS_MPNEEDSWAP(ump->um_lfs)); 1143 else 1144 rdev = (dev_t)ulfs_rw64(ip->i_ffs2_rdev, 1145 ULFS_MPNEEDSWAP(ump->um_lfs)); 1146 spec_node_init(vp, rdev); 1147 break; 1148 case VFIFO: 1149 vp->v_op = fifoops; 1150 break; 1151 case VNON: 1152 case VBAD: 1153 case VSOCK: 1154 case VLNK: 1155 case VDIR: 1156 case VREG: 1157 break; 1158 } 1159 if (ip->i_number == ULFS_ROOTINO) 1160 vp->v_vflag |= VV_ROOT; 1161 /* 1162 * Initialize modrev times 1163 */ 1164 getmicrouptime(&tv); 1165 ip->i_modrev = (uint64_t)(uint)tv.tv_sec << 32 1166 | tv.tv_usec * 4294u; 1167 *vpp = vp; 1168 } 1169 1170 /* 1171 * Allocate a new inode. 1172 */ 1173 int 1174 ulfs_makeinode(int mode, struct vnode *dvp, const struct ulfs_lookup_results *ulr, 1175 struct vnode **vpp, struct componentname *cnp) 1176 { 1177 struct inode *ip, *pdir; 1178 struct lfs_direct *newdir; 1179 struct vnode *tvp; 1180 int error; 1181 1182 pdir = VTOI(dvp); 1183 1184 if ((mode & LFS_IFMT) == 0) 1185 mode |= LFS_IFREG; 1186 1187 if ((error = lfs_valloc(dvp, mode, cnp->cn_cred, vpp)) != 0) { 1188 return (error); 1189 } 1190 tvp = *vpp; 1191 ip = VTOI(tvp); 1192 ip->i_gid = pdir->i_gid; 1193 DIP_ASSIGN(ip, gid, ip->i_gid); 1194 ip->i_uid = kauth_cred_geteuid(cnp->cn_cred); 1195 DIP_ASSIGN(ip, uid, ip->i_uid); 1196 #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) 1197 if ((error = lfs_chkiq(ip, 1, cnp->cn_cred, 0))) { 1198 lfs_vfree(tvp, ip->i_number, mode); 1199 vput(tvp); 1200 return (error); 1201 } 1202 #endif 1203 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1204 ip->i_mode = mode; 1205 DIP_ASSIGN(ip, mode, mode); 1206 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ 1207 ip->i_nlink = 1; 1208 DIP_ASSIGN(ip, nlink, 1); 1209 1210 /* Authorize setting SGID if needed. */ 1211 if (ip->i_mode & ISGID) { 1212 error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, 1213 tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid, 1214 ip->i_gid, mode)); 1215 if (error) { 1216 ip->i_mode &= ~ISGID; 1217 DIP_ASSIGN(ip, mode, ip->i_mode); 1218 } 1219 } 1220 1221 if (cnp->cn_flags & ISWHITEOUT) { 1222 ip->i_flags |= UF_OPAQUE; 1223 DIP_ASSIGN(ip, flags, ip->i_flags); 1224 } 1225 1226 /* 1227 * Make sure inode goes to disk before directory entry. 1228 */ 1229 if ((error = lfs_update(tvp, NULL, NULL, UPDATE_DIROP)) != 0) 1230 goto bad; 1231 newdir = pool_cache_get(ulfs_direct_cache, PR_WAITOK); 1232 ulfs_makedirentry(ip, cnp, newdir); 1233 error = ulfs_direnter(dvp, ulr, tvp, newdir, cnp, NULL); 1234 pool_cache_put(ulfs_direct_cache, newdir); 1235 if (error) 1236 goto bad; 1237 *vpp = tvp; 1238 return (0); 1239 1240 bad: 1241 /* 1242 * Write error occurred trying to update the inode 1243 * or the directory so must deallocate the inode. 1244 */ 1245 ip->i_nlink = 0; 1246 DIP_ASSIGN(ip, nlink, 0); 1247 ip->i_flag |= IN_CHANGE; 1248 /* If IN_ADIROP, account for it */ 1249 lfs_unmark_vnode(tvp); 1250 tvp->v_type = VNON; /* explodes later if VBLK */ 1251 vput(tvp); 1252 return (error); 1253 } 1254 1255 /* 1256 * Allocate len bytes at offset off. 1257 */ 1258 int 1259 ulfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, 1260 kauth_cred_t cred) 1261 { 1262 struct inode *ip = VTOI(vp); 1263 int error, delta, bshift, bsize; 1264 UVMHIST_FUNC("ulfs_gop_alloc"); UVMHIST_CALLED(ubchist); 1265 1266 error = 0; 1267 bshift = vp->v_mount->mnt_fs_bshift; 1268 bsize = 1 << bshift; 1269 1270 delta = off & (bsize - 1); 1271 off -= delta; 1272 len += delta; 1273 1274 while (len > 0) { 1275 bsize = MIN(bsize, len); 1276 1277 error = lfs_balloc(vp, off, bsize, cred, flags, NULL); 1278 if (error) { 1279 goto out; 1280 } 1281 1282 /* 1283 * increase file size now, lfs_balloc() requires that 1284 * EOF be up-to-date before each call. 1285 */ 1286 1287 if (ip->i_size < off + bsize) { 1288 UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x", 1289 vp, ip->i_size, off + bsize, 0); 1290 ip->i_size = off + bsize; 1291 DIP_ASSIGN(ip, size, ip->i_size); 1292 } 1293 1294 off += bsize; 1295 len -= bsize; 1296 } 1297 1298 out: 1299 return error; 1300 } 1301 1302 void 1303 ulfs_gop_markupdate(struct vnode *vp, int flags) 1304 { 1305 u_int32_t mask = 0; 1306 1307 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 1308 mask = IN_ACCESS; 1309 } 1310 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 1311 if (vp->v_type == VREG) { 1312 mask |= IN_CHANGE | IN_UPDATE; 1313 } else { 1314 mask |= IN_MODIFY; 1315 } 1316 } 1317 if (mask) { 1318 struct inode *ip = VTOI(vp); 1319 1320 ip->i_flag |= mask; 1321 } 1322 } 1323