Sat Apr 18 19:18:34 2020 UTC ()
Extended attribute support for ffsv2, from FreeBSD.


(christos)
diff -r1.13 -r1.14 src/sys/modules/ffs/Makefile
diff -r1.17 -r1.18 src/sys/rump/fs/lib/libffs/Makefile
diff -r1.46 -r1.47 src/sys/ufs/files.ufs
diff -r1.166 -r1.167 src/sys/ufs/ffs/ffs_alloc.c
diff -r1.63 -r1.64 src/sys/ufs/ffs/ffs_balloc.c
diff -r0 -r1.1 src/sys/ufs/ffs/ffs_extattr.c
diff -r1.85 -r1.86 src/sys/ufs/ffs/ffs_extern.h
diff -r1.126 -r1.127 src/sys/ufs/ffs/ffs_inode.c
diff -r1.151 -r1.152 src/sys/ufs/ffs/ffs_snapshot.c
diff -r1.130 -r1.131 src/sys/ufs/ffs/ffs_vnops.c
diff -r1.66 -r1.67 src/sys/ufs/ffs/fs.h
diff -r1.11 -r1.12 src/sys/ufs/ufs/extattr.h
diff -r1.76 -r1.77 src/sys/ufs/ufs/inode.h
diff -r1.84 -r1.85 src/sys/ufs/ufs/ufs_extern.h
diff -r1.109 -r1.110 src/sys/ufs/ufs/ufs_inode.c
diff -r1.251 -r1.252 src/sys/ufs/ufs/ufs_vnops.c

cvs diff -r1.13 -r1.14 src/sys/modules/ffs/Makefile (expand / switch to unified diff)

--- src/sys/modules/ffs/Makefile 2019/08/19 09:31:30 1.13
+++ src/sys/modules/ffs/Makefile 2020/04/18 19:18:33 1.14
@@ -1,19 +1,19 @@ @@ -1,19 +1,19 @@
1# $NetBSD: Makefile,v 1.13 2019/08/19 09:31:30 christos Exp $ 1# $NetBSD: Makefile,v 1.14 2020/04/18 19:18:33 christos Exp $
2 2
3.include "../Makefile.inc" 3.include "../Makefile.inc"
4 4
5.PATH: ${S}/ufs/ffs 5.PATH: ${S}/ufs/ffs
6 6
7KMOD= ffs 7KMOD= ffs
8CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2 8CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2
9CPPFLAGS+= -DUFS_EXTATTR 9CPPFLAGS+= -DUFS_EXTATTR
10 10
11CWARNFLAGS.clang= -Wno-conversion 11CWARNFLAGS.clang= -Wno-conversion
12 12
13SRCS+= ffs_alloc.c ffs_balloc.c ffs_inode.c ffs_subr.c ffs_tables.c \ 13SRCS+= ffs_alloc.c ffs_balloc.c ffs_inode.c ffs_subr.c ffs_tables.c \
14 ffs_vfsops.c ffs_vnops.c ffs_snapshot.c \ 14 ffs_vfsops.c ffs_vnops.c ffs_snapshot.c ffs_extattr.c \
15 ffs_bswap.c ffs_wapbl.c ffs_appleufs.c ffs_quota2.c 15 ffs_bswap.c ffs_wapbl.c ffs_appleufs.c ffs_quota2.c
16 16
17WARNS= 3 17WARNS= 3
18 18
19.include <bsd.kmodule.mk> 19.include <bsd.kmodule.mk>

cvs diff -r1.17 -r1.18 src/sys/rump/fs/lib/libffs/Makefile (expand / switch to unified diff)

--- src/sys/rump/fs/lib/libffs/Makefile 2020/04/12 00:04:45 1.17
+++ src/sys/rump/fs/lib/libffs/Makefile 2020/04/18 19:18:33 1.18
@@ -1,21 +1,21 @@ @@ -1,21 +1,21 @@
1# $NetBSD: Makefile,v 1.17 2020/04/12 00:04:45 christos Exp $ 1# $NetBSD: Makefile,v 1.18 2020/04/18 19:18:33 christos Exp $
2# 2#
3 3
4.PATH: ${.CURDIR}/../../../../ufs/ffs ${.CURDIR}/../../../../ufs/ufs 4.PATH: ${.CURDIR}/../../../../ufs/ffs ${.CURDIR}/../../../../ufs/ufs
5 5
6LIB= rumpfs_ffs 6LIB= rumpfs_ffs
7COMMENT=Berkeley Fast File System 7COMMENT=Berkeley Fast File System
8 8
9SRCS= ffs_alloc.c ffs_appleufs.c ffs_balloc.c ffs_bswap.c ffs_inode.c \ 9SRCS= ffs_alloc.c ffs_appleufs.c ffs_balloc.c ffs_bswap.c ffs_inode.c \
10 ffs_snapshot.c ffs_subr.c ffs_tables.c ffs_vfsops.c ffs_vnops.c \ 10 ffs_snapshot.c ffs_subr.c ffs_tables.c ffs_vfsops.c ffs_vnops.c \
11 ffs_wapbl.c ffs_quota2.c 11 ffs_wapbl.c ffs_quota2.c ffs_extattr.c
12 12
13SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ 13SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
14 ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c \ 14 ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c \
15 ufs_quota.c ufs_quota2.c quota2_subr.c 15 ufs_quota.c ufs_quota2.c quota2_subr.c
16 16
17CPPFLAGS+= -DFFS_EI -DUFS_DIRHASH -DWAPBL -DAPPLE_UFS -DUFS_EXTATTR \ 17CPPFLAGS+= -DFFS_EI -DUFS_DIRHASH -DWAPBL -DAPPLE_UFS -DUFS_EXTATTR \
18 -DQUOTA2 18 -DQUOTA2
19 19
20.include <bsd.lib.mk> 20.include <bsd.lib.mk>
21.include <bsd.klinks.mk> 21.include <bsd.klinks.mk>

cvs diff -r1.46 -r1.47 src/sys/ufs/files.ufs (expand / switch to unified diff)

--- src/sys/ufs/files.ufs 2020/04/11 17:43:54 1.46
+++ src/sys/ufs/files.ufs 2020/04/18 19:18:33 1.47
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: files.ufs,v 1.46 2020/04/11 17:43:54 jdolecek Exp $ 1# $NetBSD: files.ufs,v 1.47 2020/04/18 19:18:33 christos Exp $
2 2
3deffs FFS 3deffs FFS
4deffs EXT2FS 4deffs EXT2FS
5deffs MFS 5deffs MFS
6deffs LFS 6deffs LFS
7deffs CHFS 7deffs CHFS
8 8
9defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS 9defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS
10 UFS_DIRHASH UFS_EXTATTR 10 UFS_DIRHASH UFS_EXTATTR
11 11
12defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW 12defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW
13 LFS_DIRHASH LFS_EXTATTR 13 LFS_DIRHASH LFS_EXTATTR
14 LFS_QUOTA LFS_QUOTA2 14 LFS_QUOTA LFS_QUOTA2
@@ -42,26 +42,27 @@ file ufs/chfs/chfs_vnops.c chfs @@ -42,26 +42,27 @@ file ufs/chfs/chfs_vnops.c chfs
42file ufs/chfs/chfs_gc.c chfs 42file ufs/chfs/chfs_gc.c chfs
43file ufs/chfs/chfs_nodeops.c chfs 43file ufs/chfs/chfs_nodeops.c chfs
44file ufs/chfs/chfs_malloc.c chfs 44file ufs/chfs/chfs_malloc.c chfs
45file ufs/chfs/chfs_pool.c chfs 45file ufs/chfs/chfs_pool.c chfs
46file ufs/chfs/chfs_vnode.c chfs 46file ufs/chfs/chfs_vnode.c chfs
47file ufs/chfs/chfs_subr.c chfs 47file ufs/chfs/chfs_subr.c chfs
48file ufs/chfs/chfs_vfsops.c chfs 48file ufs/chfs/chfs_vfsops.c chfs
49file ufs/chfs/chfs_readinode.c chfs 49file ufs/chfs/chfs_readinode.c chfs
50 50
51define ffs: vfs, ufs 51define ffs: vfs, ufs
52file ufs/ffs/ffs_alloc.c ffs 52file ufs/ffs/ffs_alloc.c ffs
53file ufs/ffs/ffs_balloc.c ffs 53file ufs/ffs/ffs_balloc.c ffs
54file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei 54file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei
 55file ufs/ffs/ffs_extattr.c ffs & ufs_extattr
55file ufs/ffs/ffs_inode.c ffs 56file ufs/ffs/ffs_inode.c ffs
56file ufs/ffs/ffs_snapshot.c ffs 57file ufs/ffs/ffs_snapshot.c ffs
57file ufs/ffs/ffs_subr.c ffs 58file ufs/ffs/ffs_subr.c ffs
58file ufs/ffs/ffs_tables.c ffs 59file ufs/ffs/ffs_tables.c ffs
59file ufs/ffs/ffs_vfsops.c ffs 60file ufs/ffs/ffs_vfsops.c ffs
60file ufs/ffs/ffs_vnops.c ffs 61file ufs/ffs/ffs_vnops.c ffs
61file ufs/ffs/ffs_wapbl.c ffs & wapbl 62file ufs/ffs/ffs_wapbl.c ffs & wapbl
62file ufs/ffs/ffs_appleufs.c ffs & apple_ufs 63file ufs/ffs/ffs_appleufs.c ffs & apple_ufs
63file ufs/ffs/ffs_quota2.c quota2 & (ffs | mfs | ext2fs | chfs) 64file ufs/ffs/ffs_quota2.c quota2 & (ffs | mfs | ext2fs | chfs)
64 65
65define lfs: vfs 66define lfs: vfs
66file ufs/lfs/lfs_alloc.c lfs 67file ufs/lfs/lfs_alloc.c lfs
67file ufs/lfs/lfs_balloc.c lfs 68file ufs/lfs/lfs_balloc.c lfs

cvs diff -r1.166 -r1.167 src/sys/ufs/ffs/ffs_alloc.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_alloc.c 2020/02/23 15:46:42 1.166
+++ src/sys/ufs/ffs/ffs_alloc.c 2020/04/18 19:18:34 1.167
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_alloc.c,v 1.166 2020/02/23 15:46:42 ad Exp $ */ 1/* $NetBSD: ffs_alloc.c,v 1.167 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc. 8 * by Wasabi Systems, Inc.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -60,27 +60,27 @@ @@ -60,27 +60,27 @@
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SUCH DAMAGE. 67 * SUCH DAMAGE.
68 * 68 *
69 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95 69 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
70 */ 70 */
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.166 2020/02/23 15:46:42 ad Exp $"); 73__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.167 2020/04/18 19:18:34 christos Exp $");
74 74
75#if defined(_KERNEL_OPT) 75#if defined(_KERNEL_OPT)
76#include "opt_ffs.h" 76#include "opt_ffs.h"
77#include "opt_quota.h" 77#include "opt_quota.h"
78#include "opt_uvm_page_trkown.h" 78#include "opt_uvm_page_trkown.h"
79#endif 79#endif
80 80
81#include <sys/param.h> 81#include <sys/param.h>
82#include <sys/systm.h> 82#include <sys/systm.h>
83#include <sys/buf.h> 83#include <sys/buf.h>
84#include <sys/cprng.h> 84#include <sys/cprng.h>
85#include <sys/kauth.h> 85#include <sys/kauth.h>
86#include <sys/kernel.h> 86#include <sys/kernel.h>
@@ -247,27 +247,30 @@ ffs_alloc(struct inode *ip, daddr_t lbn, @@ -247,27 +247,30 @@ ffs_alloc(struct inode *ip, daddr_t lbn,
247 return (error); 247 return (error);
248 mutex_enter(&ump->um_lock); 248 mutex_enter(&ump->um_lock);
249#endif 249#endif
250 250
251 if (bpref >= fs->fs_size) 251 if (bpref >= fs->fs_size)
252 bpref = 0; 252 bpref = 0;
253 if (bpref == 0) 253 if (bpref == 0)
254 cg = ino_to_cg(fs, ip->i_number); 254 cg = ino_to_cg(fs, ip->i_number);
255 else 255 else
256 cg = dtog(fs, bpref); 256 cg = dtog(fs, bpref);
257 bno = ffs_hashalloc(ip, cg, bpref, size, 0, flags, ffs_alloccg); 257 bno = ffs_hashalloc(ip, cg, bpref, size, 0, flags, ffs_alloccg);
258 if (bno > 0) { 258 if (bno > 0) {
259 DIP_ADD(ip, blocks, btodb(size)); 259 DIP_ADD(ip, blocks, btodb(size));
260 ip->i_flag |= IN_CHANGE | IN_UPDATE; 260 if (flags & IO_EXT)
 261 ip->i_flag |= IN_CHANGE;
 262 else
 263 ip->i_flag |= IN_CHANGE | IN_UPDATE;
261 *bnp = bno; 264 *bnp = bno;
262 return (0); 265 return (0);
263 } 266 }
264#if defined(QUOTA) || defined(QUOTA2) 267#if defined(QUOTA) || defined(QUOTA2)
265 /* 268 /*
266 * Restore user's disk quota because allocation failed. 269 * Restore user's disk quota because allocation failed.
267 */ 270 */
268 (void) chkdq(ip, -btodb(size), cred, FORCE); 271 (void) chkdq(ip, -btodb(size), cred, FORCE);
269#endif 272#endif
270 if (flags & B_CONTIG) { 273 if (flags & B_CONTIG) {
271 /* 274 /*
272 * XXX ump->um_lock handling is "suspect" at best. 275 * XXX ump->um_lock handling is "suspect" at best.
273 * For the case where ffs_hashalloc() fails early 276 * For the case where ffs_hashalloc() fails early
@@ -290,34 +293,35 @@ nospace: @@ -290,34 +293,35 @@ nospace:
290 293
291/* 294/*
292 * Reallocate a fragment to a bigger size 295 * Reallocate a fragment to a bigger size
293 * 296 *
294 * The number and size of the old block is given, and a preference 297 * The number and size of the old block is given, and a preference
295 * and new size is also specified. The allocator attempts to extend 298 * and new size is also specified. The allocator attempts to extend
296 * the original block. Failing that, the regular block allocator is 299 * the original block. Failing that, the regular block allocator is
297 * invoked to get an appropriate block. 300 * invoked to get an appropriate block.
298 * 301 *
299 * => called with um_lock held 302 * => called with um_lock held
300 * => return with um_lock released 303 * => return with um_lock released
301 */ 304 */
302int 305int
303ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize, 306ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bprev, daddr_t bpref,
304 int nsize, kauth_cred_t cred, struct buf **bpp, daddr_t *blknop) 307 int osize, int nsize, int flags, kauth_cred_t cred, struct buf **bpp,
 308 daddr_t *blknop)
305{ 309{
306 struct ufsmount *ump; 310 struct ufsmount *ump;
307 struct fs *fs; 311 struct fs *fs;
308 struct buf *bp; 312 struct buf *bp;
309 int cg, request, error; 313 int cg, request, error;
310 daddr_t bprev, bno; 314 daddr_t bno;
311 315
312 fs = ip->i_fs; 316 fs = ip->i_fs;
313 ump = ip->i_ump; 317 ump = ip->i_ump;
314 318
315 KASSERT(mutex_owned(&ump->um_lock)); 319 KASSERT(mutex_owned(&ump->um_lock));
316 320
317#ifdef UVM_PAGE_TRKOWN 321#ifdef UVM_PAGE_TRKOWN
318 322
319 /* 323 /*
320 * Sanity-check that allocations within the file size 324 * Sanity-check that allocations within the file size
321 * do not allow other threads to read the stale contents 325 * do not allow other threads to read the stale contents
322 * of newly allocated blocks. 326 * of newly allocated blocks.
323 * Unlike in ffs_alloc(), here pages must always exist 327 * Unlike in ffs_alloc(), here pages must always exist
@@ -358,30 +362,26 @@ ffs_realloccg(struct inode *ip, daddr_t  @@ -358,30 +362,26 @@ ffs_realloccg(struct inode *ip, daddr_t
358 (unsigned long long)ip->i_dev, fs->fs_bsize, osize, nsize, 362 (unsigned long long)ip->i_dev, fs->fs_bsize, osize, nsize,
359 fs->fs_fsmnt); 363 fs->fs_fsmnt);
360 KASSERTMSG((ffs_fragoff(fs, nsize) == 0), 364 KASSERTMSG((ffs_fragoff(fs, nsize) == 0),
361 "bad size: dev=0x%llx, bsize=%d, osize=%d, nsize=%d, fs=%s", 365 "bad size: dev=0x%llx, bsize=%d, osize=%d, nsize=%d, fs=%s",
362 (unsigned long long)ip->i_dev, fs->fs_bsize, osize, nsize, 366 (unsigned long long)ip->i_dev, fs->fs_bsize, osize, nsize,
363 fs->fs_fsmnt); 367 fs->fs_fsmnt);
364 368
365 if (freespace(fs, fs->fs_minfree) <= 0 && 369 if (freespace(fs, fs->fs_minfree) <= 0 &&
366 kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL, 370 kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL,
367 NULL, NULL) != 0) { 371 NULL, NULL) != 0) {
368 mutex_exit(&ump->um_lock); 372 mutex_exit(&ump->um_lock);
369 goto nospace; 373 goto nospace;
370 } 374 }
371 if (fs->fs_magic == FS_UFS2_MAGIC) 
372 bprev = ufs_rw64(ip->i_ffs2_db[lbprev], UFS_FSNEEDSWAP(fs)); 
373 else 
374 bprev = ufs_rw32(ip->i_ffs1_db[lbprev], UFS_FSNEEDSWAP(fs)); 
375 375
376 if (bprev == 0) { 376 if (bprev == 0) {
377 panic("%s: bad bprev: dev = 0x%llx, bsize = %d, bprev = %" 377 panic("%s: bad bprev: dev = 0x%llx, bsize = %d, bprev = %"
378 PRId64 ", fs = %s", __func__, 378 PRId64 ", fs = %s", __func__,
379 (unsigned long long)ip->i_dev, fs->fs_bsize, bprev, 379 (unsigned long long)ip->i_dev, fs->fs_bsize, bprev,
380 fs->fs_fsmnt); 380 fs->fs_fsmnt);
381 } 381 }
382 mutex_exit(&ump->um_lock); 382 mutex_exit(&ump->um_lock);
383 383
384 /* 384 /*
385 * Allocate the extra space in the buffer. 385 * Allocate the extra space in the buffer.
386 */ 386 */
387 if (bpp != NULL && 387 if (bpp != NULL &&
@@ -393,27 +393,30 @@ ffs_realloccg(struct inode *ip, daddr_t  @@ -393,27 +393,30 @@ ffs_realloccg(struct inode *ip, daddr_t
393 if (bpp != NULL) { 393 if (bpp != NULL) {
394 brelse(bp, 0); 394 brelse(bp, 0);
395 } 395 }
396 return (error); 396 return (error);
397 } 397 }
398#endif 398#endif
399 /* 399 /*
400 * Check for extension in the existing location. 400 * Check for extension in the existing location.
401 */ 401 */
402 cg = dtog(fs, bprev); 402 cg = dtog(fs, bprev);
403 mutex_enter(&ump->um_lock); 403 mutex_enter(&ump->um_lock);
404 if ((bno = ffs_fragextend(ip, cg, bprev, osize, nsize)) != 0) { 404 if ((bno = ffs_fragextend(ip, cg, bprev, osize, nsize)) != 0) {
405 DIP_ADD(ip, blocks, btodb(nsize - osize)); 405 DIP_ADD(ip, blocks, btodb(nsize - osize));
406 ip->i_flag |= IN_CHANGE | IN_UPDATE; 406 if (flags & IO_EXT)
 407 ip->i_flag |= IN_CHANGE;
 408 else
 409 ip->i_flag |= IN_CHANGE | IN_UPDATE;
407 410
408 if (bpp != NULL) { 411 if (bpp != NULL) {
409 if (bp->b_blkno != FFS_FSBTODB(fs, bno)) { 412 if (bp->b_blkno != FFS_FSBTODB(fs, bno)) {
410 panic("%s: bad blockno %#llx != %#llx", 413 panic("%s: bad blockno %#llx != %#llx",
411 __func__, (unsigned long long) bp->b_blkno, 414 __func__, (unsigned long long) bp->b_blkno,
412 (unsigned long long)FFS_FSBTODB(fs, bno)); 415 (unsigned long long)FFS_FSBTODB(fs, bno));
413 } 416 }
414 allocbuf(bp, nsize, 1); 417 allocbuf(bp, nsize, 1);
415 memset((char *)bp->b_data + osize, 0, nsize - osize); 418 memset((char *)bp->b_data + osize, 0, nsize - osize);
416 mutex_enter(bp->b_objlock); 419 mutex_enter(bp->b_objlock);
417 KASSERT(!cv_has_waiters(&bp->b_done)); 420 KASSERT(!cv_has_waiters(&bp->b_done));
418 bp->b_oflags |= BO_DONE; 421 bp->b_oflags |= BO_DONE;
419 mutex_exit(bp->b_objlock); 422 mutex_exit(bp->b_objlock);
@@ -493,27 +496,30 @@ ffs_realloccg(struct inode *ip, daddr_t  @@ -493,27 +496,30 @@ ffs_realloccg(struct inode *ip, daddr_t
493 if ((ip->i_ump->um_mountp->mnt_wapbl) && 496 if ((ip->i_ump->um_mountp->mnt_wapbl) &&
494 (ITOV(ip)->v_type != VREG)) { 497 (ITOV(ip)->v_type != VREG)) {
495 /* this should never fail */ 498 /* this should never fail */
496 error = UFS_WAPBL_REGISTER_DEALLOCATION_FORCE( 499 error = UFS_WAPBL_REGISTER_DEALLOCATION_FORCE(
497 ip->i_ump->um_mountp, FFS_FSBTODB(fs, bprev), 500 ip->i_ump->um_mountp, FFS_FSBTODB(fs, bprev),
498 osize); 501 osize);
499 if (error) 502 if (error)
500 panic("ffs_realloccg: dealloc registration failed"); 503 panic("ffs_realloccg: dealloc registration failed");
501 } else { 504 } else {
502 ffs_blkfree(fs, ip->i_devvp, bprev, (long)osize, 505 ffs_blkfree(fs, ip->i_devvp, bprev, (long)osize,
503 ip->i_number); 506 ip->i_number);
504 } 507 }
505 DIP_ADD(ip, blocks, btodb(nsize - osize)); 508 DIP_ADD(ip, blocks, btodb(nsize - osize));
506 ip->i_flag |= IN_CHANGE | IN_UPDATE; 509 if (flags & IO_EXT)
 510 ip->i_flag |= IN_CHANGE;
 511 else
 512 ip->i_flag |= IN_CHANGE | IN_UPDATE;
507 if (bpp != NULL) { 513 if (bpp != NULL) {
508 bp->b_blkno = FFS_FSBTODB(fs, bno); 514 bp->b_blkno = FFS_FSBTODB(fs, bno);
509 allocbuf(bp, nsize, 1); 515 allocbuf(bp, nsize, 1);
510 memset((char *)bp->b_data + osize, 0, (u_int)nsize - osize); 516 memset((char *)bp->b_data + osize, 0, (u_int)nsize - osize);
511 mutex_enter(bp->b_objlock); 517 mutex_enter(bp->b_objlock);
512 KASSERT(!cv_has_waiters(&bp->b_done)); 518 KASSERT(!cv_has_waiters(&bp->b_done));
513 bp->b_oflags |= BO_DONE; 519 bp->b_oflags |= BO_DONE;
514 mutex_exit(bp->b_objlock); 520 mutex_exit(bp->b_objlock);
515 *bpp = bp; 521 *bpp = bp;
516 } 522 }
517 if (blknop != NULL) { 523 if (blknop != NULL) {
518 *blknop = bno; 524 *blknop = bno;
519 } 525 }

cvs diff -r1.63 -r1.64 src/sys/ufs/ffs/ffs_balloc.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_balloc.c 2017/10/28 00:37:13 1.63
+++ src/sys/ufs/ffs/ffs_balloc.c 2020/04/18 19:18:34 1.64
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_balloc.c,v 1.63 2017/10/28 00:37:13 pgoyette Exp $ */ 1/* $NetBSD: ffs_balloc.c,v 1.64 2020/04/18 19:18:34 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Networks Associates Technology, Inc. 4 * Copyright (c) 2002 Networks Associates Technology, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This software was developed for the FreeBSD Project by Marshall 7 * This software was developed for the FreeBSD Project by Marshall
8 * Kirk McKusick and Network Associates Laboratories, the Security 8 * Kirk McKusick and Network Associates Laboratories, the Security
9 * Research Division of Network Associates, Inc. under DARPA/SPAWAR 9 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
10 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 10 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
11 * research program 11 * research program
12 * 12 *
13 * Copyright (c) 1982, 1986, 1989, 1993 13 * Copyright (c) 1982, 1986, 1989, 1993
14 * The Regents of the University of California. All rights reserved. 14 * The Regents of the University of California. All rights reserved.
@@ -31,27 +31,27 @@ @@ -31,27 +31,27 @@
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE. 38 * SUCH DAMAGE.
39 * 39 *
40 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 40 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
41 */ 41 */
42 42
43#include <sys/cdefs.h> 43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.63 2017/10/28 00:37:13 pgoyette Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.64 2020/04/18 19:18:34 christos Exp $");
45 45
46#if defined(_KERNEL_OPT) 46#if defined(_KERNEL_OPT)
47#include "opt_quota.h" 47#include "opt_quota.h"
48#endif 48#endif
49 49
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/systm.h> 51#include <sys/systm.h>
52#include <sys/buf.h> 52#include <sys/buf.h>
53#include <sys/file.h> 53#include <sys/file.h>
54#include <sys/mount.h> 54#include <sys/mount.h>
55#include <sys/vnode.h> 55#include <sys/vnode.h>
56#include <sys/kauth.h> 56#include <sys/kauth.h>
57#include <sys/fstrans.h> 57#include <sys/fstrans.h>
@@ -62,26 +62,32 @@ __KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c @@ -62,26 +62,32 @@ __KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c
62#include <ufs/ufs/ufs_extern.h> 62#include <ufs/ufs/ufs_extern.h>
63#include <ufs/ufs/ufs_bswap.h> 63#include <ufs/ufs/ufs_bswap.h>
64 64
65#include <ufs/ffs/fs.h> 65#include <ufs/ffs/fs.h>
66#include <ufs/ffs/ffs_extern.h> 66#include <ufs/ffs/ffs_extern.h>
67 67
68#include <uvm/uvm.h> 68#include <uvm/uvm.h>
69 69
70static int ffs_balloc_ufs1(struct vnode *, off_t, int, kauth_cred_t, int, 70static int ffs_balloc_ufs1(struct vnode *, off_t, int, kauth_cred_t, int,
71 struct buf **); 71 struct buf **);
72static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int, 72static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int,
73 struct buf **); 73 struct buf **);
74 74
 75static daddr_t
 76ffs_extb(struct fs *fs, struct ufs2_dinode *dp, daddr_t nb)
 77{
 78 return ufs_rw64(dp->di_extb[nb], UFS_FSNEEDSWAP(fs));
 79}
 80
75/* 81/*
76 * Balloc defines the structure of file system storage 82 * Balloc defines the structure of file system storage
77 * by allocating the physical blocks on a device given 83 * by allocating the physical blocks on a device given
78 * the inode and the logical block number in a file. 84 * the inode and the logical block number in a file.
79 */ 85 */
80 86
81int 87int
82ffs_balloc(struct vnode *vp, off_t off, int size, kauth_cred_t cred, int flags, 88ffs_balloc(struct vnode *vp, off_t off, int size, kauth_cred_t cred, int flags,
83 struct buf **bpp) 89 struct buf **bpp)
84{ 90{
85 int error; 91 int error;
86 92
87 if (VTOI(vp)->i_fs->fs_magic == FS_UFS2_MAGIC) 93 if (VTOI(vp)->i_fs->fs_magic == FS_UFS2_MAGIC)
@@ -129,30 +135,31 @@ ffs_balloc_ufs1(struct vnode *vp, off_t  @@ -129,30 +135,31 @@ ffs_balloc_ufs1(struct vnode *vp, off_t
129 135
130 /* 136 /*
131 * If the next write will extend the file into a new block, 137 * If the next write will extend the file into a new block,
132 * and the file is currently composed of a fragment 138 * and the file is currently composed of a fragment
133 * this fragment has to be extended to be a full block. 139 * this fragment has to be extended to be a full block.
134 */ 140 */
135 141
136 lastlbn = ffs_lblkno(fs, ip->i_size); 142 lastlbn = ffs_lblkno(fs, ip->i_size);
137 if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 143 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
138 nb = lastlbn; 144 nb = lastlbn;
139 osize = ffs_blksize(fs, ip, nb); 145 osize = ffs_blksize(fs, ip, nb);
140 if (osize < fs->fs_bsize && osize > 0) { 146 if (osize < fs->fs_bsize && osize > 0) {
141 mutex_enter(&ump->um_lock); 147 mutex_enter(&ump->um_lock);
142 error = ffs_realloccg(ip, nb, 148 error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, nb),
143 ffs_blkpref_ufs1(ip, lastlbn, nb, flags, 149 ffs_blkpref_ufs1(ip, lastlbn, nb, flags,
144 &ip->i_ffs1_db[0]), 150 &ip->i_ffs1_db[0]),
145 osize, (int)fs->fs_bsize, cred, bpp, &newb); 151 osize, (int)fs->fs_bsize, flags, cred, bpp,
 152 &newb);
146 if (error) 153 if (error)
147 return (error); 154 return (error);
148 ip->i_size = ffs_lblktosize(fs, nb + 1); 155 ip->i_size = ffs_lblktosize(fs, nb + 1);
149 ip->i_ffs1_size = ip->i_size; 156 ip->i_ffs1_size = ip->i_size;
150 uvm_vnp_setsize(vp, ip->i_ffs1_size); 157 uvm_vnp_setsize(vp, ip->i_ffs1_size);
151 ip->i_ffs1_db[nb] = ufs_rw32((u_int32_t)newb, needswap); 158 ip->i_ffs1_db[nb] = ufs_rw32((u_int32_t)newb, needswap);
152 ip->i_flag |= IN_CHANGE | IN_UPDATE; 159 ip->i_flag |= IN_CHANGE | IN_UPDATE;
153 if (bpp && *bpp) { 160 if (bpp && *bpp) {
154 if (flags & B_SYNC) 161 if (flags & B_SYNC)
155 bwrite(*bpp); 162 bwrite(*bpp);
156 else 163 else
157 bawrite(*bpp); 164 bawrite(*bpp);
158 } 165 }
@@ -205,29 +212,30 @@ ffs_balloc_ufs1(struct vnode *vp, off_t  @@ -205,29 +212,30 @@ ffs_balloc_ufs1(struct vnode *vp, off_t
205 if (error) { 212 if (error) {
206 return (error); 213 return (error);
207 } 214 }
208 } 215 }
209 return 0; 216 return 0;
210 } else { 217 } else {
211 218
212 /* 219 /*
213 * The existing block is smaller than we want, 220 * The existing block is smaller than we want,
214 * grow it. 221 * grow it.
215 */ 222 */
216 mutex_enter(&ump->um_lock); 223 mutex_enter(&ump->um_lock);
217 error = ffs_realloccg(ip, lbn, 224 error = ffs_realloccg(ip, lbn,
 225 ffs_getdb(fs, ip, lbn),
218 ffs_blkpref_ufs1(ip, lbn, (int)lbn, flags, 226 ffs_blkpref_ufs1(ip, lbn, (int)lbn, flags,
219 &ip->i_ffs1_db[0]), 227 &ip->i_ffs1_db[0]),
220 osize, nsize, cred, bpp, &newb); 228 osize, nsize, flags, cred, bpp, &newb);
221 if (error) 229 if (error)
222 return (error); 230 return (error);
223 } 231 }
224 } else { 232 } else {
225 233
226 /* 234 /*
227 * the block was not previously allocated, 235 * the block was not previously allocated,
228 * allocate a new block or fragment. 236 * allocate a new block or fragment.
229 */ 237 */
230 238
231 if (ip->i_size < ffs_lblktosize(fs, lbn + 1)) 239 if (ip->i_size < ffs_lblktosize(fs, lbn + 1))
232 nsize = ffs_fragroundup(fs, size); 240 nsize = ffs_fragroundup(fs, size);
233 else 241 else
@@ -533,148 +541,141 @@ ffs_balloc_ufs2(struct vnode *vp, off_t  @@ -533,148 +541,141 @@ ffs_balloc_ufs2(struct vnode *vp, off_t
533 lbn = ffs_lblkno(fs, off); 541 lbn = ffs_lblkno(fs, off);
534 size = ffs_blkoff(fs, off) + size; 542 size = ffs_blkoff(fs, off) + size;
535 if (size > fs->fs_bsize) 543 if (size > fs->fs_bsize)
536 panic("ffs_balloc: blk too big"); 544 panic("ffs_balloc: blk too big");
537 if (bpp != NULL) { 545 if (bpp != NULL) {
538 *bpp = NULL; 546 *bpp = NULL;
539 } 547 }
540 UVMHIST_LOG(ubchist, "vp %#jx lbn 0x%jx size 0x%jx", (uintptr_t)vp, 548 UVMHIST_LOG(ubchist, "vp %#jx lbn 0x%jx size 0x%jx", (uintptr_t)vp,
541 lbn, size, 0); 549 lbn, size, 0);
542 550
543 if (lbn < 0) 551 if (lbn < 0)
544 return (EFBIG); 552 return (EFBIG);
545 553
546#ifdef notyet 
547 /* 554 /*
548 * Check for allocating external data. 555 * Check for allocating external data.
549 */ 556 */
550 if (flags & IO_EXT) { 557 if (flags & IO_EXT) {
 558 struct ufs2_dinode *dp = ip->i_din.ffs2_din;
551 if (lbn >= UFS_NXADDR) 559 if (lbn >= UFS_NXADDR)
552 return (EFBIG); 560 return (EFBIG);
553 /* 561 /*
554 * If the next write will extend the data into a new block, 562 * If the next write will extend the data into a new block,
555 * and the data is currently composed of a fragment 563 * and the data is currently composed of a fragment
556 * this fragment has to be extended to be a full block. 564 * this fragment has to be extended to be a full block.
557 */ 565 */
558 lastlbn = ffs_lblkno(fs, dp->di_extsize); 566 lastlbn = ffs_lblkno(fs, dp->di_extsize);
559 if (lastlbn < lbn) { 567 if (lastlbn < lbn) {
560 nb = lastlbn; 568 nb = lastlbn;
561 osize = ffs_sblksize(fs, dp->di_extsize, nb); 569 osize = ffs_sblksize(fs, dp->di_extsize, nb);
562 if (osize < fs->fs_bsize && osize > 0) { 570 if (osize < fs->fs_bsize && osize > 0) {
563 mutex_enter(&ump->um_lock); 571 mutex_enter(&ump->um_lock);
564 error = ffs_realloccg(ip, -1 - nb, 572 error = ffs_realloccg(ip, -1 - nb,
565 dp->di_extb[nb], 573 ffs_extb(fs, dp, nb),
566 ffs_blkpref_ufs2(ip, lastlbn, (int)nb, 574 ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
567 flags, &dp->di_extb[0]), 575 flags, &dp->di_extb[0]),
568 osize, 576 osize, (int)fs->fs_bsize, flags, cred,
569 (int)fs->fs_bsize, cred, &bp); 577 &bp, &newb);
570 if (error) 578 if (error)
571 return (error); 579 return (error);
572 dp->di_extsize = smalllblktosize(fs, nb + 1); 580 dp->di_extsize = ffs_lblktosize(fs, nb + 1);
573 dp->di_extb[nb] = FFS_DBTOFSB(fs, bp->b_blkno); 581 dp->di_extb[nb] = FFS_DBTOFSB(fs, bp->b_blkno);
574 bp->b_xflags |= BX_ALTDATA; 
575 ip->i_flag |= IN_CHANGE | IN_UPDATE; 582 ip->i_flag |= IN_CHANGE | IN_UPDATE;
576 if (flags & IO_SYNC) 583 if (flags & IO_SYNC)
577 bwrite(bp); 584 bwrite(bp);
578 else 585 else
579 bawrite(bp); 586 bawrite(bp);
580 } 587 }
581 } 588 }
582 /* 589 /*
583 * All blocks are direct blocks 590 * All blocks are direct blocks
584 */ 591 */
585 if (flags & BA_METAONLY) 
586 panic("ffs_balloc_ufs2: BA_METAONLY for ext block"); 
587 nb = dp->di_extb[lbn]; 592 nb = dp->di_extb[lbn];
588 if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) { 593 if (nb != 0 && dp->di_extsize >= ffs_lblktosize(fs, lbn + 1)) {
589 error = bread(vp, -1 - lbn, fs->fs_bsize, 594 error = bread(vp, -1 - lbn, fs->fs_bsize,
590 0, &bp); 595 0, &bp);
591 if (error) { 596 if (error) {
592 return (error); 597 return (error);
593 } 598 }
594 mutex_enter(&bp->b_interlock); 599 mutex_enter(bp->b_objlock);
595 bp->b_blkno = FFS_FSBTODB(fs, nb); 600 bp->b_blkno = FFS_FSBTODB(fs, nb);
596 bp->b_xflags |= BX_ALTDATA; 601 mutex_exit(bp->b_objlock);
597 mutex_exit(&bp->b_interlock); 
598 *bpp = bp; 602 *bpp = bp;
599 return (0); 603 return (0);
600 } 604 }
601 if (nb != 0) { 605 if (nb != 0) {
602 /* 606 /*
603 * Consider need to reallocate a fragment. 607 * Consider need to reallocate a fragment.
604 */ 608 */
605 osize = ffs_fragroundup(fs, ffs_blkoff(fs, dp->di_extsize)); 609 osize = ffs_fragroundup(fs, ffs_blkoff(fs, dp->di_extsize));
606 nsize = ffs_fragroundup(fs, size); 610 nsize = ffs_fragroundup(fs, size);
607 if (nsize <= osize) { 611 if (nsize <= osize) {
608 error = bread(vp, -1 - lbn, osize, 612 error = bread(vp, -1 - lbn, osize,
609 0, &bp); 613 0, &bp);
610 if (error) { 614 if (error) {
611 return (error); 615 return (error);
612 } 616 }
613 mutex_enter(&bp->b_interlock); 617 mutex_enter(bp->b_objlock);
614 bp->b_blkno = FFS_FSBTODB(fs, nb); 618 bp->b_blkno = FFS_FSBTODB(fs, nb);
615 bp->b_xflags |= BX_ALTDATA; 619 mutex_exit(bp->b_objlock);
616 mutex_exit(&bp->b_interlock); 
617 } else { 620 } else {
618 mutex_enter(&ump->um_lock); 621 mutex_enter(&ump->um_lock);
619 error = ffs_realloccg(ip, -1 - lbn, 622 error = ffs_realloccg(ip, -1 - lbn,
620 dp->di_extb[lbn], 623 ffs_extb(fs, dp, lbn),
621 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 624 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags,
622 &dp->di_extb[0]), 625 &dp->di_extb[0]),
623 osize, nsize, cred, &bp); 626 osize, nsize, flags, cred, &bp, &newb);
624 if (error) 627 if (error)
625 return (error); 628 return (error);
626 bp->b_xflags |= BX_ALTDATA; 
627 } 629 }
628 } else { 630 } else {
629 if (dp->di_extsize < smalllblktosize(fs, lbn + 1)) 631 if (dp->di_extsize < ffs_lblktosize(fs, lbn + 1))
630 nsize = ffs_fragroundup(fs, size); 632 nsize = ffs_fragroundup(fs, size);
631 else 633 else
632 nsize = fs->fs_bsize; 634 nsize = fs->fs_bsize;
633 mutex_enter(&ump->um_lock); 635 mutex_enter(&ump->um_lock);
634 error = ffs_alloc(ip, lbn, 636 error = ffs_alloc(ip, lbn,
635 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 637 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags,
636 &dp->di_extb[0]), 638 &dp->di_extb[0]),
637 nsize, flags, cred, &newb); 639 nsize, flags, cred, &newb);
638 if (error) 640 if (error)
639 return (error); 641 return (error);
640 error = ffs_getblk(vp, -1 - lbn, FFS_FSBTODB(fs, newb), 642 error = ffs_getblk(vp, -1 - lbn, FFS_FSBTODB(fs, newb),
641 nsize, (flags & B_CLRBUF) != 0, &bp); 643 nsize, (flags & B_CLRBUF) != 0, &bp);
642 if (error) 644 if (error)
643 return error; 645 return error;
644 bp->b_xflags |= BX_ALTDATA; 
645 } 646 }
646 dp->di_extb[lbn] = FFS_DBTOFSB(fs, bp->b_blkno); 647 dp->di_extb[lbn] = FFS_DBTOFSB(fs, bp->b_blkno);
647 ip->i_flag |= IN_CHANGE | IN_UPDATE; 648 ip->i_flag |= IN_CHANGE | IN_UPDATE;
648 *bpp = bp; 649 *bpp = bp;
649 return (0); 650 return (0);
650 } 651 }
651#endif 
652 /* 652 /*
653 * If the next write will extend the file into a new block, 653 * If the next write will extend the file into a new block,
654 * and the file is currently composed of a fragment 654 * and the file is currently composed of a fragment
655 * this fragment has to be extended to be a full block. 655 * this fragment has to be extended to be a full block.
656 */ 656 */
657 657
658 lastlbn = ffs_lblkno(fs, ip->i_size); 658 lastlbn = ffs_lblkno(fs, ip->i_size);
659 if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 659 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
660 nb = lastlbn; 660 nb = lastlbn;
661 osize = ffs_blksize(fs, ip, nb); 661 osize = ffs_blksize(fs, ip, nb);
662 if (osize < fs->fs_bsize && osize > 0) { 662 if (osize < fs->fs_bsize && osize > 0) {
663 mutex_enter(&ump->um_lock); 663 mutex_enter(&ump->um_lock);
664 error = ffs_realloccg(ip, nb, 664 error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, lbn),
665 ffs_blkpref_ufs2(ip, lastlbn, nb, flags, 665 ffs_blkpref_ufs2(ip, lastlbn, nb, flags,
666 &ip->i_ffs2_db[0]), 666 &ip->i_ffs2_db[0]),
667 osize, (int)fs->fs_bsize, cred, bpp, &newb); 667 osize, (int)fs->fs_bsize, flags, cred, bpp,
 668 &newb);
668 if (error) 669 if (error)
669 return (error); 670 return (error);
670 ip->i_size = ffs_lblktosize(fs, nb + 1); 671 ip->i_size = ffs_lblktosize(fs, nb + 1);
671 ip->i_ffs2_size = ip->i_size; 672 ip->i_ffs2_size = ip->i_size;
672 uvm_vnp_setsize(vp, ip->i_size); 673 uvm_vnp_setsize(vp, ip->i_size);
673 ip->i_ffs2_db[nb] = ufs_rw64(newb, needswap); 674 ip->i_ffs2_db[nb] = ufs_rw64(newb, needswap);
674 ip->i_flag |= IN_CHANGE | IN_UPDATE; 675 ip->i_flag |= IN_CHANGE | IN_UPDATE;
675 if (bpp) { 676 if (bpp) {
676 if (flags & B_SYNC) 677 if (flags & B_SYNC)
677 bwrite(*bpp); 678 bwrite(*bpp);
678 else 679 else
679 bawrite(*bpp); 680 bawrite(*bpp);
680 } 681 }
@@ -727,29 +728,30 @@ ffs_balloc_ufs2(struct vnode *vp, off_t  @@ -727,29 +728,30 @@ ffs_balloc_ufs2(struct vnode *vp, off_t
727 if (error) { 728 if (error) {
728 return (error); 729 return (error);
729 } 730 }
730 } 731 }
731 return 0; 732 return 0;
732 } else { 733 } else {
733 734
734 /* 735 /*
735 * The existing block is smaller than we want, 736 * The existing block is smaller than we want,
736 * grow it. 737 * grow it.
737 */ 738 */
738 mutex_enter(&ump->um_lock); 739 mutex_enter(&ump->um_lock);
739 error = ffs_realloccg(ip, lbn, 740 error = ffs_realloccg(ip, lbn,
 741 ffs_getdb(fs, ip, lbn),
740 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags, 742 ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags,
741 &ip->i_ffs2_db[0]), 743 &ip->i_ffs2_db[0]),
742 osize, nsize, cred, bpp, &newb); 744 osize, nsize, flags, cred, bpp, &newb);
743 if (error) 745 if (error)
744 return (error); 746 return (error);
745 } 747 }
746 } else { 748 } else {
747 749
748 /* 750 /*
749 * the block was not previously allocated, 751 * the block was not previously allocated,
750 * allocate a new block or fragment. 752 * allocate a new block or fragment.
751 */ 753 */
752 754
753 if (ip->i_size < ffs_lblktosize(fs, lbn + 1)) 755 if (ip->i_size < ffs_lblktosize(fs, lbn + 1))
754 nsize = ffs_fragroundup(fs, size); 756 nsize = ffs_fragroundup(fs, size);
755 else 757 else

File Added: src/sys/ufs/ffs/ffs_extattr.c
/*	$NetBSD: ffs_extattr.c,v 1.1 2020/04/18 19:18:34 christos Exp $	*/

/*-
 * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-3-Clause)
 *
 * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * This software was developed for the FreeBSD Project by Marshall
 * Kirk McKusick and Network Associates Laboratories, the Security
 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
 * research program
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * Copyright (c) 1982, 1986, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)ufs_readwrite.c	8.11 (Berkeley) 5/8/95
 * from: $FreeBSD: .../ufs/ufs_readwrite.c,v 1.96 2002/08/12 09:22:11 phk ...
 *	@(#)ffs_vnops.c	8.15 (Berkeley) 5/14/95
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_extattr.c,v 1.1 2020/04/18 19:18:34 christos Exp $");

#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
#include "opt_wapbl.h"
#endif

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
#include <sys/kernel.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/buf.h>
#include <sys/event.h>
#include <sys/extattr.h>
#include <sys/kauth.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/pool.h>
#include <sys/signalvar.h>
#include <sys/kauth.h>
#include <sys/wapbl.h>

#include <miscfs/fifofs/fifo.h>
#include <miscfs/genfs/genfs.h>
#include <miscfs/specfs/specdev.h>

#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_wapbl.h>

#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>

#include <uvm/uvm.h>

#define ALIGNED_TO(ptr, s)  \
    (((uintptr_t)(ptr) & (_Alignof(s) - 1)) == 0)
#define uoff_t uintmax_t
#define ITOFS(ip) (ip)->i_fs
#define i_din2 i_din.ffs2_din
#define VI_LOCK(vp)		mutex_enter((vp)->v_interlock)
#define VI_UNLOCK(vp)		mutex_exit((vp)->v_interlock)
#define UFS_INODE_SET_FLAG(ip, f)	((ip)->i_flag |= (f))
#define ASSERT_VOP_ELOCKED(vp, m)	KASSERT(VOP_ISLOCKED(vp))
#define I_IS_UFS2(ip)		(ITOFS(ip)->fs_magic == FS_UFS2_MAGIC)
#define	lblktosize(fs, o)	ffs_lblktosize(fs, o)
#define	lblkno(fs, o)		ffs_lblkno(fs, o)
#define	blkoff(fs, o)		ffs_blkoff(fs, o)
#define	sblksize(fs, o, lbn)	ffs_sblksize(fs, o, lbn)
typedef mode_t accmode_t;	/* so that it breaks soon */
typedef daddr_t ufs_lbn_t;
#define msleep(chan, mtx, pri, wmesg, timeo) \
    mtsleep((chan), (pri), (wmesg), (timeo), *(mtx))
#define vm_page_count_severe()		0
#define buf_dirty_count_severe()	0
#define BA_CLRBUF B_CLRBUF
#define IO_ASYNC 0
#define vfs_bio_brelse(bp, ioflag) 	brelse(bp, 0)
#define vfs_bio_clrbuf(bp) 		clrbuf(bp)
#define vfs_bio_set_flags(bp, ioflag) 	__nothing

/*
 * Credential check based on process requesting service, and per-attribute
 * permissions.
 */
static int
ffs_extattr_check_cred(struct vnode *vp, int attrnamespace, kauth_cred_t cred,
    accmode_t accmode)
{
	/*
	 * Kernel-invoked always succeeds.
	 */
	if (cred == NOCRED)
		return 0;

	/*
	 * Do not allow privileged processes in jail to directly manipulate
	 * system attributes.
	 */
	switch (attrnamespace) {
	case EXTATTR_NAMESPACE_SYSTEM:
		/* Potentially with privs */
		return EPERM;
	case EXTATTR_NAMESPACE_USER:
		return VOP_ACCESS(vp, accmode, cred);
	default:
		return EPERM;
	}
}
/*
 * Extended attribute area reading.
 */
static int
ffs_extread(struct vnode *vp, struct uio *uio, int ioflag)
{
	struct inode *ip;
	struct ufs2_dinode *dp;
	struct fs *fs;
	struct buf *bp;
	ufs_lbn_t lbn, nextlbn;
	off_t bytesinfile;
	long size, xfersize, blkoffset;
	ssize_t orig_resid;
	int error;

	ip = VTOI(vp);
	fs = ITOFS(ip);
	dp = ip->i_din2;

#ifdef INVARIANTS
	if (uio->uio_rw != UIO_READ || fs->fs_magic != FS_UFS2_MAGIC)
		panic("ffs_extread: mode");

#endif
	orig_resid = uio->uio_resid;
	KASSERT(orig_resid >= 0);
	if (orig_resid == 0)
		return (0);
	KASSERT(uio->uio_offset >= 0);

	for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
		if ((bytesinfile = dp->di_extsize - uio->uio_offset) <= 0)
			break;
		lbn = lblkno(fs, uio->uio_offset);
		nextlbn = lbn + 1;

		/*
		 * size of buffer.  The buffer representing the
		 * end of the file is rounded up to the size of
		 * the block type ( fragment or full block,
		 * depending ).
		 */
		size = sblksize(fs, dp->di_extsize, lbn);
		blkoffset = blkoff(fs, uio->uio_offset);

		/*
		 * The amount we want to transfer in this iteration is
		 * one FS block less the amount of the data before
		 * our startpoint (duh!)
		 */
		xfersize = fs->fs_bsize - blkoffset;

		/*
		 * But if we actually want less than the block,
		 * or the file doesn't have a whole block more of data,
		 * then use the lesser number.
		 */
		if (uio->uio_resid < xfersize)
			xfersize = uio->uio_resid;
		if (bytesinfile < xfersize)
			xfersize = bytesinfile;

		if (lblktosize(fs, nextlbn) >= dp->di_extsize) {
			/*
			 * Don't do readahead if this is the end of the info.
			 */
			error = bread(vp, -1 - lbn, size, 0, &bp);
		} else {
			/*
			 * If we have a second block, then
			 * fire off a request for a readahead
			 * as well as a read. Note that the 4th and 5th
			 * arguments point to arrays of the size specified in
			 * the 6th argument.
			 */
			u_int nextsize = sblksize(fs, dp->di_extsize, nextlbn);

			nextlbn = -1 - nextlbn;
			error = breadn(vp, -1 - lbn,
			    size, &nextlbn, &nextsize, 1, 0, &bp);
		}
		if (error) {
			brelse(bp, 0);
			bp = NULL;
			break;
		}

		/*
		 * We should only get non-zero b_resid when an I/O error
		 * has occurred, which should cause us to break above.
		 * However, if the short read did not cause an error,
		 * then we want to ensure that we do not uiomove bad
		 * or uninitialized data.
		 */
		size -= bp->b_resid;
		if (size < xfersize) {
			if (size == 0)
				break;
			xfersize = size;
		}

		error = uiomove((char *)bp->b_data + blkoffset,
					(int)xfersize, uio);
		if (error)
			break;
		vfs_bio_brelse(bp, ioflag);
	}

	/*
	 * This can only happen in the case of an error
	 * because the loop above resets bp to NULL on each iteration
	 * and on normal completion has not set a new value into it.
	 * so it must have come from a 'break' statement
	 */
	if (bp != NULL)
		vfs_bio_brelse(bp, ioflag);
	return (error);
}
/*
 * Extended attribute area writing.
 */
static int
ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, kauth_cred_t ucred)
{
	struct inode *ip;
	struct ufs2_dinode *dp;
	struct fs *fs;
	struct buf *bp;
	ufs_lbn_t lbn;
	off_t osize;
	ssize_t resid;
	int blkoffset, error, flags, size, xfersize;

	ip = VTOI(vp);
	fs = ITOFS(ip);
	dp = ip->i_din2;

#ifdef INVARIANTS
	if (uio->uio_rw != UIO_WRITE || fs->fs_magic != FS_UFS2_MAGIC)
		panic("ffs_extwrite: mode");
#endif

	if (ioflag & IO_APPEND)
		uio->uio_offset = dp->di_extsize;
	KASSERT(uio->uio_offset >= 0);
	if ((uoff_t)uio->uio_offset + uio->uio_resid >
	    UFS_NXADDR * fs->fs_bsize)
		return (EFBIG);

	resid = uio->uio_resid;
	osize = dp->di_extsize;
	flags = IO_EXT;
	if (ioflag & IO_SYNC)
		flags |= IO_SYNC;

	if ((error = UFS_WAPBL_BEGIN(vp->v_mount)) != 0)
		return error;

	for (error = 0; uio->uio_resid > 0;) {
		lbn = lblkno(fs, uio->uio_offset);
		blkoffset = blkoff(fs, uio->uio_offset);
		xfersize = fs->fs_bsize - blkoffset;
		if (uio->uio_resid < xfersize)
			xfersize = uio->uio_resid;

		/*
		 * We must perform a read-before-write if the transfer size
		 * does not cover the entire buffer.
		 */
		if (fs->fs_bsize > xfersize)
			flags |= BA_CLRBUF;
		else
			flags &= ~BA_CLRBUF;
		error = UFS_BALLOC(vp, uio->uio_offset, xfersize,
		    ucred, flags, &bp);
		if (error != 0)
			break;
		/*
		 * If the buffer is not valid we have to clear out any
		 * garbage data from the pages instantiated for the buffer.
		 * If we do not, a failed uiomove() during a write can leave
		 * the prior contents of the pages exposed to a userland
		 * mmap().  XXX deal with uiomove() errors a better way.
		 */
		if ((bp->b_flags & BC_NOCACHE) && fs->fs_bsize <= xfersize)
			vfs_bio_clrbuf(bp);

		if (uio->uio_offset + xfersize > dp->di_extsize)
			dp->di_extsize = uio->uio_offset + xfersize;

		size = sblksize(fs, dp->di_extsize, lbn) - bp->b_resid;
		if (size < xfersize)
			xfersize = size;

		error =
		    uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);

		vfs_bio_set_flags(bp, ioflag);

		/*
		 * If IO_SYNC each buffer is written synchronously.  Otherwise
		 * if we have a severe page deficiency write the buffer
		 * asynchronously.  Otherwise try to cluster, and if that
		 * doesn't do it then either do an async write (if O_DIRECT),
		 * or a delayed write (if not).
		 */
		if (ioflag & IO_SYNC) {
			(void)bwrite(bp);
		} else if (vm_page_count_severe() ||
			    buf_dirty_count_severe() ||
			    xfersize + blkoffset == fs->fs_bsize ||
			    (ioflag & (IO_ASYNC | IO_DIRECT)))
			bawrite(bp);
		else
			bdwrite(bp);
		if (error || xfersize == 0)
			break;
		UFS_INODE_SET_FLAG(ip, IN_CHANGE);
	}
	/*
	 * If we successfully wrote any data, and we are not the superuser
	 * we clear the setuid and setgid bits as a precaution against
	 * tampering.
	 */
	if ((ip->i_mode & (ISUID | ISGID)) && resid > uio->uio_resid && ucred) {
		ip->i_mode &= ~(ISUID | ISGID);
		dp->di_mode = ip->i_mode;
	}
	if (error) {
		if (ioflag & IO_UNIT) {
			(void)ffs_truncate(vp, osize,
			    IO_EXT | (ioflag&IO_SYNC), ucred);
			uio->uio_offset -= resid - uio->uio_resid;
			uio->uio_resid = resid;
		}
	} else if (resid > uio->uio_resid && (ioflag & IO_SYNC))
		error = ffs_update(vp, NULL, NULL, UPDATE_WAIT);
	UFS_WAPBL_END(vp->v_mount);
	return (error);
}

/*
 * Vnode operating to retrieve a named extended attribute.
 *
 * Locate a particular EA (nspace:name) in the area (ptr:length), and return
 * the length of the EA, and possibly the pointer to the entry and to the data.
 */
static int
ffs_findextattr(u_char *ptr, u_int length, int nspace, const char *name,
    struct extattr **eapp, u_char **eac)
{
	struct extattr *eap, *eaend;
	size_t nlen;

	nlen = strlen(name);
	KASSERT(ALIGNED_TO(ptr, struct extattr));
	eap = (struct extattr *)ptr;
	eaend = (struct extattr *)(ptr + length);
	for (; eap < eaend; eap = EXTATTR_NEXT(eap)) {
		/* make sure this entry is complete */
		if (EXTATTR_NEXT(eap) > eaend)
			break;
		if (eap->ea_namespace != nspace || eap->ea_namelength != nlen
		    || memcmp(eap->ea_name, name, nlen) != 0)
			continue;
		if (eapp != NULL)
			*eapp = eap;
		if (eac != NULL)
			*eac = EXTATTR_CONTENT(eap);
		return (EXTATTR_CONTENT_SIZE(eap));
	}
	return (-1);
}

static int
ffs_rdextattr(u_char **p, struct vnode *vp, int extra)
{
	struct inode *ip;
	struct ufs2_dinode *dp;
	struct fs *fs;
	struct uio luio;
	struct iovec liovec;
	u_int easize;
	int error;
	u_char *eae;

	ip = VTOI(vp);
	fs = ITOFS(ip);
	dp = ip->i_din2;
	easize = dp->di_extsize;
	if ((uoff_t)easize + extra > UFS_NXADDR * fs->fs_bsize)
		return (EFBIG);

	eae = malloc(easize + extra, M_TEMP, M_WAITOK);

	liovec.iov_base = eae;
	liovec.iov_len = easize;
	luio.uio_iov = &liovec;
	luio.uio_iovcnt = 1;
	luio.uio_offset = 0;
	luio.uio_resid = easize;
	luio.uio_vmspace = vmspace_kernel();
	luio.uio_rw = UIO_READ;

	error = ffs_extread(vp, &luio, IO_EXT | IO_SYNC);
	if (error) {
		free(eae, M_TEMP);
		return(error);
	}
	*p = eae;
	return (0);
}

static void
ffs_lock_ea(struct vnode *vp)
{
#if 0
	struct inode *ip;

	ip = VTOI(vp);
	VI_LOCK(vp);
	while (ip->i_flag & IN_EA_LOCKED) {
		UFS_INODE_SET_FLAG(ip, IN_EA_LOCKWAIT);
		msleep(&ip->i_ea_refs, &vp->v_interlock, PINOD + 2, "ufs_ea",
		    0);
	}
	UFS_INODE_SET_FLAG(ip, IN_EA_LOCKED);
	VI_UNLOCK(vp);
#endif
}

static void
ffs_unlock_ea(struct vnode *vp)
{
#if 0
	struct inode *ip;

	ip = VTOI(vp);
	VI_LOCK(vp);
	if (ip->i_flag & IN_EA_LOCKWAIT)
		wakeup(&ip->i_ea_refs);
	ip->i_flag &= ~(IN_EA_LOCKED | IN_EA_LOCKWAIT);
	VI_UNLOCK(vp);
#endif
}

static int
ffs_open_ea(struct vnode *vp, kauth_cred_t cred)
{
	struct inode *ip;
	struct ufs2_dinode *dp;
	int error;

	ip = VTOI(vp);

	ffs_lock_ea(vp);
	if (ip->i_ea_area != NULL) {
		ip->i_ea_refs++;
		ffs_unlock_ea(vp);
		return (0);
	}
	dp = ip->i_din2;
	error = ffs_rdextattr(&ip->i_ea_area, vp, 0);
	if (error) {
		ffs_unlock_ea(vp);
		return (error);
	}
	ip->i_ea_len = dp->di_extsize;
	ip->i_ea_error = 0;
	ip->i_ea_refs++;
	ffs_unlock_ea(vp);
	return (0);
}

/*
 * Vnode extattr transaction commit/abort
 */
static int
ffs_close_ea(struct vnode *vp, int commit, kauth_cred_t cred)
{
	struct inode *ip;
	struct uio luio;
	struct iovec liovec;
	int error;
	struct ufs2_dinode *dp;

	ip = VTOI(vp);

	if (commit)
		KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
	else
		KASSERT(VOP_ISLOCKED(vp));
	ffs_lock_ea(vp);
	if (ip->i_ea_area == NULL) {
		ffs_unlock_ea(vp);
		return (EINVAL);
	}
	dp = ip->i_din2;
	error = ip->i_ea_error;
	if (commit && error == 0) {
		ASSERT_VOP_ELOCKED(vp, "ffs_close_ea commit");
		if (cred == NOCRED)
			cred =  lwp0.l_cred;
		liovec.iov_base = ip->i_ea_area;
		liovec.iov_len = ip->i_ea_len;
		luio.uio_iov = &liovec;
		luio.uio_iovcnt = 1;
		luio.uio_offset = 0;
		luio.uio_resid = ip->i_ea_len;
		luio.uio_vmspace = vmspace_kernel();
		luio.uio_rw = UIO_WRITE;
		if ((error = UFS_WAPBL_BEGIN(vp->v_mount)) != 0) {
			ffs_unlock_ea(vp);
			return error;
		}

		/* XXX: I'm not happy about truncating to zero size */
		if (ip->i_ea_len < dp->di_extsize)
			error = ffs_truncate(vp, 0, IO_EXT, cred);
		error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC, cred);
		UFS_WAPBL_END(vp->v_mount);
	}
	if (--ip->i_ea_refs == 0) {
		free(ip->i_ea_area, M_TEMP);
		ip->i_ea_area = NULL;
		ip->i_ea_len = 0;
		ip->i_ea_error = 0;
	}
	ffs_unlock_ea(vp);
	return (error);
}

/*
 * Vnode extattr strategy routine for fifos.
 *
 * We need to check for a read or write of the external attributes.
 * Otherwise we just fall through and do the usual thing.
 */
int
ffsext_strategy(void *v)
{
	struct vop_strategy_args /* {
		struct vnodeop_desc *a_desc;
		struct vnode *a_vp;
		struct buf *a_bp;
	} */ *ap = v;
	struct vnode *vp;
	daddr_t lbn;

	vp = ap->a_vp;
	lbn = ap->a_bp->b_lblkno;
	if (I_IS_UFS2(VTOI(vp)) && lbn < 0 && lbn >= -UFS_NXADDR)
		return ufs_strategy(ap);
	if (vp->v_type == VFIFO)
		return vn_fifo_bypass(ap);
	panic("spec nodes went here");
}

/*
 * Vnode extattr transaction commit/abort
 */
int
ffs_openextattr(void *v)
{
	struct vop_openextattr_args /* {
		struct vnode *a_vp;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct inode *ip = VTOI(ap->a_vp);
	struct fs *fs = ip->i_fs;

	/* Not supported for UFS1 file systems. */
	if (fs->fs_magic == FS_UFS1_MAGIC)
		return (EOPNOTSUPP);

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	return (ffs_open_ea(ap->a_vp, ap->a_cred));
}

/*
 * Vnode extattr transaction commit/abort
 */
int
ffs_closeextattr(void *v)
{
	struct vop_closeextattr_args /* {
		struct vnode *a_vp;
		int a_commit;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct inode *ip = VTOI(ap->a_vp);
	struct fs *fs = ip->i_fs;

	/* Not supported for UFS1 file systems. */
	if (fs->fs_magic == FS_UFS1_MAGIC)
		return (EOPNOTSUPP);

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	if (ap->a_commit && (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY))
		return (EROFS);

	return (ffs_close_ea(ap->a_vp, ap->a_commit, ap->a_cred));
}

/*
 * Vnode operation to retrieve a named extended attribute.
 */
int
ffs_getextattr(void *v)
{
	struct vop_getextattr_args /* {
		struct vnode *a_vp;
		int a_attrnamespace;
		const char *a_name;
		struct uio *a_uio;
		size_t *a_size;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	struct fs *fs = ip->i_fs;

	KASSERT(VOP_ISLOCKED(vp));
	if (fs->fs_magic == FS_UFS1_MAGIC) {
		return ufs_getextattr(ap);
	}

	u_char *eae, *p;
	unsigned easize;
	int error, ealen;

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, VREAD);
	if (error)
		return (error);

	error = ffs_open_ea(ap->a_vp, ap->a_cred);
	if (error)
		return (error);

	eae = ip->i_ea_area;
	easize = ip->i_ea_len;

	ealen = ffs_findextattr(eae, easize, ap->a_attrnamespace, ap->a_name,
	    NULL, &p);
	if (ealen >= 0) {
		error = 0;
		if (ap->a_size != NULL)
			*ap->a_size = ealen;
		else if (ap->a_uio != NULL)
			error = uiomove(p, ealen, ap->a_uio);
	} else
		error = ENOATTR;

	ffs_close_ea(ap->a_vp, 0, ap->a_cred);
	return (error);
}

/*
 * Vnode operation to set a named attribute.
 */
int
ffs_setextattr(void *v)
{
	struct vop_setextattr_args /* {
		struct vnode *a_vp;
		int a_attrnamespace;
		const char *a_name;
		struct uio *a_uio;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	struct fs *fs = ip->i_fs;

	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
	if (fs->fs_magic == FS_UFS1_MAGIC) {
		return ufs_setextattr(ap);
	}

	struct extattr *eap;
	uint32_t ealength, ul;
	ssize_t ealen;
	int olen, eapad1, eapad2, error, i, easize;
	u_char *eae;
	void *tmp;

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	if (strlen(ap->a_name) == 0)
		return (EINVAL);

	/* XXX Now unsupported API to delete EAs using NULL uio. */
	if (ap->a_uio == NULL)
		return (EOPNOTSUPP);

	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
		return (EROFS);

	ealen = ap->a_uio->uio_resid;
	if (ealen < 0 || ealen > lblktosize(fs, UFS_NXADDR))
		return (EINVAL);

	error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, VWRITE);
	if (error) {

		/*
		 * ffs_lock_ea is not needed there, because the vnode
		 * must be exclusively locked.
		 */
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = error;
		return (error);
	}

	error = ffs_open_ea(ap->a_vp, ap->a_cred);
	if (error)
		return (error);

	ealength = sizeof(uint32_t) + 3 + strlen(ap->a_name);
	eapad1 = roundup2(ealength, 8) - ealength;
	eapad2 = roundup2(ealen, 8) - ealen;
	ealength += eapad1 + ealen + eapad2;

	/*
	 * CEM: rewrites of the same size or smaller could be done in-place
	 * instead.  (We don't acquire any fine-grained locks in here either,
	 * so we could also do bigger writes in-place.)
	 */
	eae = malloc(ip->i_ea_len + ealength, M_TEMP, M_WAITOK);
	bcopy(ip->i_ea_area, eae, ip->i_ea_len);
	easize = ip->i_ea_len;

	olen = ffs_findextattr(eae, easize, ap->a_attrnamespace, ap->a_name,
	    &eap, NULL);
        if (olen == -1) {
		/* new, append at end */
		KASSERT(ALIGNED_TO(eae + easize, struct extattr));
		eap = (struct extattr *)(eae + easize);
		easize += ealength;
	} else {
		ul = eap->ea_length;
		i = (u_char *)EXTATTR_NEXT(eap) - eae;
		if (ul != ealength) {
			bcopy(EXTATTR_NEXT(eap), (u_char *)eap + ealength,
			    easize - i);
			easize += (ealength - ul);
		}
	}
	if (easize > lblktosize(fs, UFS_NXADDR)) {
		free(eae, M_TEMP);
		ffs_close_ea(ap->a_vp, 0, ap->a_cred);
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = ENOSPC;
		return (ENOSPC);
	}
	eap->ea_length = ealength;
	eap->ea_namespace = ap->a_attrnamespace;
	eap->ea_contentpadlen = eapad2;
	eap->ea_namelength = strlen(ap->a_name);
	memcpy(eap->ea_name, ap->a_name, strlen(ap->a_name));
	bzero(&eap->ea_name[strlen(ap->a_name)], eapad1);
	error = uiomove(EXTATTR_CONTENT(eap), ealen, ap->a_uio);
	if (error) {
		free(eae, M_TEMP);
		ffs_close_ea(ap->a_vp, 0, ap->a_cred);
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = error;
		return (error);
	}
	bzero((u_char *)EXTATTR_CONTENT(eap) + ealen, eapad2);

	tmp = ip->i_ea_area;
	ip->i_ea_area = eae;
	ip->i_ea_len = easize;
	free(tmp, M_TEMP);
	error = ffs_close_ea(ap->a_vp, 1, ap->a_cred);
	return (error);
}

/*
 * Vnode operation to retrieve extended attributes on a vnode.
 */
int
ffs_listextattr(void *v)
{
	struct vop_listextattr_args /* {
		struct vnode *a_vp;
		int a_attrnamespace;
		struct uio *a_uio;
		size_t *a_size;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct inode *ip = VTOI(ap->a_vp);
	struct fs *fs = ip->i_fs;

	if (fs->fs_magic == FS_UFS1_MAGIC) {
		return ufs_listextattr(ap);
	}

	struct extattr *eap, *eaend;
	int error, ealen;

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, VREAD);
	if (error)
		return (error);

	error = ffs_open_ea(ap->a_vp, ap->a_cred);
	if (error)
		return (error);

	error = 0;
	if (ap->a_size != NULL)
		*ap->a_size = 0;

	KASSERT(ALIGNED_TO(ip->i_ea_area, struct extattr));
	eap = (struct extattr *)ip->i_ea_area;
	eaend = (struct extattr *)(ip->i_ea_area + ip->i_ea_len);
	for (; error == 0 && eap < eaend; eap = EXTATTR_NEXT(eap)) {
		/* make sure this entry is complete */
		if (EXTATTR_NEXT(eap) > eaend)
			break;
		if (eap->ea_namespace != ap->a_attrnamespace)
			continue;

		ealen = eap->ea_namelength;
		if (ap->a_size != NULL)
			*ap->a_size += ealen + 1;
		else if (ap->a_uio != NULL)
			error = uiomove(&eap->ea_namelength, ealen + 1,
			    ap->a_uio);
	}

	ffs_close_ea(ap->a_vp, 0, ap->a_cred);
	return (error);
}

/*
 * Vnode operation to remove a named attribute.
 */
int
ffs_deleteextattr(void *v)
{
	struct vop_deleteextattr_args /* {
		struct vnode *a_vp;
		int a_attrnamespace;
		kauth_cred_t a_cred;
		struct proc *a_p;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	struct fs *fs = ip->i_fs;

	if (fs->fs_magic == FS_UFS1_MAGIC) {
		return ufs_deleteextattr(ap);
	}

	struct extattr *eap;
	uint32_t ul;
	int olen, error, i, easize;
	u_char *eae;
	void *tmp;

	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);

	if (strlen(ap->a_name) == 0)
		return (EINVAL);

	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
		return (EROFS);

	error = ffs_extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, VWRITE);
	if (error) {

		/*
		 * ffs_lock_ea is not needed there, because the vnode
		 * must be exclusively locked.
		 */
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = error;
		return (error);
	}

	error = ffs_open_ea(ap->a_vp, ap->a_cred);
	if (error)
		return (error);

	/* CEM: delete could be done in-place instead */
	eae = malloc(ip->i_ea_len, M_TEMP, M_WAITOK);
	bcopy(ip->i_ea_area, eae, ip->i_ea_len);
	easize = ip->i_ea_len;

	olen = ffs_findextattr(eae, easize, ap->a_attrnamespace, ap->a_name,
	    &eap, NULL);
	if (olen == -1) {
		/* delete but nonexistent */
		free(eae, M_TEMP);
		ffs_close_ea(ap->a_vp, 0, ap->a_cred);
		return (ENOATTR);
	}
	ul = eap->ea_length;
	i = (u_char *)EXTATTR_NEXT(eap) - eae;
	bcopy(EXTATTR_NEXT(eap), eap, easize - i);
	easize -= ul;

	tmp = ip->i_ea_area;
	ip->i_ea_area = eae;
	ip->i_ea_len = easize;
	free(tmp, M_TEMP);
	error = ffs_close_ea(ap->a_vp, 1, ap->a_cred);
	return error;
}

cvs diff -r1.85 -r1.86 src/sys/ufs/ffs/ffs_extern.h (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_extern.h 2018/08/22 01:05:24 1.85
+++ src/sys/ufs/ffs/ffs_extern.h 2020/04/18 19:18:34 1.86
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_extern.h,v 1.85 2018/08/22 01:05:24 msaitoh Exp $ */ 1/* $NetBSD: ffs_extern.h,v 1.86 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993, 1994 4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -79,28 +79,28 @@ extern pool_cache_t ffs_dinode2_cache; / @@ -79,28 +79,28 @@ extern pool_cache_t ffs_dinode2_cache; /
79#endif /* defined(_KERNEL) */ 79#endif /* defined(_KERNEL) */
80 80
81__BEGIN_DECLS 81__BEGIN_DECLS
82 82
83#if defined(_KERNEL) 83#if defined(_KERNEL)
84 84
85#include <sys/param.h> 85#include <sys/param.h>
86#include <sys/mount.h> 86#include <sys/mount.h>
87#include <sys/wapbl.h> 87#include <sys/wapbl.h>
88 88
89/* ffs_alloc.c */ 89/* ffs_alloc.c */
90int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t, 90int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t,
91 daddr_t *); 91 daddr_t *);
92int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int , 92int ffs_realloccg(struct inode *, daddr_t, daddr_t, daddr_t, int, int,
93 kauth_cred_t, struct buf **, daddr_t *); 93 int, kauth_cred_t, struct buf **, daddr_t *);
94int ffs_valloc(struct vnode *, int, kauth_cred_t, ino_t *); 94int ffs_valloc(struct vnode *, int, kauth_cred_t, ino_t *);
95daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *); 95daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *);
96daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *); 96daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *);
97int ffs_blkalloc(struct inode *, daddr_t, long); 97int ffs_blkalloc(struct inode *, daddr_t, long);
98int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long); 98int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long);
99void ffs_blkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); 99void ffs_blkfree(struct fs *, struct vnode *, daddr_t, long, ino_t);
100void *ffs_discard_init(struct vnode *, struct fs *); 100void *ffs_discard_init(struct vnode *, struct fs *);
101void ffs_discard_finish(void *, int); 101void ffs_discard_finish(void *, int);
102void ffs_blkfree_snap(struct fs *, struct vnode *, daddr_t, long, ino_t); 102void ffs_blkfree_snap(struct fs *, struct vnode *, daddr_t, long, ino_t);
103int ffs_vfree(struct vnode *, ino_t, int); 103int ffs_vfree(struct vnode *, ino_t, int);
104int ffs_checkfreefile(struct fs *, struct vnode *, ino_t); 104int ffs_checkfreefile(struct fs *, struct vnode *, ino_t);
105int ffs_freefile(struct mount *, ino_t, int); 105int ffs_freefile(struct mount *, ino_t, int);
106int ffs_freefile_snap(struct fs *, struct vnode *, ino_t, int); 106int ffs_freefile_snap(struct fs *, struct vnode *, ino_t, int);
@@ -125,36 +125,49 @@ int ffs_cgupdate(struct ufsmount *, int) @@ -125,36 +125,49 @@ int ffs_cgupdate(struct ufsmount *, int)
125 125
126/* ffs_vnops.c */ 126/* ffs_vnops.c */
127int ffs_read(void *); 127int ffs_read(void *);
128int ffs_write(void *); 128int ffs_write(void *);
129int ffs_bufio(enum uio_rw, struct vnode *, void *, size_t, off_t, int, 129int ffs_bufio(enum uio_rw, struct vnode *, void *, size_t, off_t, int,
130 kauth_cred_t, size_t *, struct lwp *); 130 kauth_cred_t, size_t *, struct lwp *);
131int ffs_bufrd(struct vnode *, struct uio *, int, kauth_cred_t); 131int ffs_bufrd(struct vnode *, struct uio *, int, kauth_cred_t);
132int ffs_bufwr(struct vnode *, struct uio *, int, kauth_cred_t); 132int ffs_bufwr(struct vnode *, struct uio *, int, kauth_cred_t);
133int ffs_fsync(void *); 133int ffs_fsync(void *);
134int ffs_spec_fsync(void *); 134int ffs_spec_fsync(void *);
135int ffs_reclaim(void *); 135int ffs_reclaim(void *);
136int ffs_getpages(void *); 136int ffs_getpages(void *);
137void ffs_gop_size(struct vnode *, off_t, off_t *, int); 137void ffs_gop_size(struct vnode *, off_t, off_t *, int);
 138int ffs_lock(void *);
 139int ffs_unlock(void *);
 140int ffs_islocked(void *);
 141int ffs_full_fsync(struct vnode *, int);
 142
 143/* ffs_extattr.c */
 144#ifdef UFS_EXTATTR
138int ffs_openextattr(void *); 145int ffs_openextattr(void *);
139int ffs_closeextattr(void *); 146int ffs_closeextattr(void *);
140int ffs_getextattr(void *); 147int ffs_getextattr(void *);
141int ffs_setextattr(void *); 148int ffs_setextattr(void *);
142int ffs_listextattr(void *); 149int ffs_listextattr(void *);
143int ffs_deleteextattr(void *); 150int ffs_deleteextattr(void *);
144int ffs_lock(void *); 151int ffsext_strategy(void *);
145int ffs_unlock(void *); 152#else
146int ffs_islocked(void *); 153#define ffs_openextattr genfs_eopnotsupp
147int ffs_full_fsync(struct vnode *, int); 154#define ffs_closeextattr genfs_eopnotsupp
 155#define ffs_getextattr genfs_eopnotsupp
 156#define ffs_setextattr genfs_eopnotsupp
 157#define ffs_listextattr genfs_eopnotsupp
 158#define ffs_deleteextattr genfs_eopnotsupp
 159#define ffsext_strategy vn_fifo_bypass
 160#endif
148 161
149/* 162/*
150 * Snapshot function prototypes. 163 * Snapshot function prototypes.
151 */ 164 */
152int ffs_snapshot_init(struct ufsmount *); 165int ffs_snapshot_init(struct ufsmount *);
153void ffs_snapshot_fini(struct ufsmount *); 166void ffs_snapshot_fini(struct ufsmount *);
154int ffs_snapblkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); 167int ffs_snapblkfree(struct fs *, struct vnode *, daddr_t, long, ino_t);
155void ffs_snapremove(struct vnode *); 168void ffs_snapremove(struct vnode *);
156int ffs_snapshot(struct mount *, struct vnode *, struct timespec *); 169int ffs_snapshot(struct mount *, struct vnode *, struct timespec *);
157void ffs_snapshot_mount(struct mount *); 170void ffs_snapshot_mount(struct mount *);
158void ffs_snapshot_unmount(struct mount *); 171void ffs_snapshot_unmount(struct mount *);
159void ffs_snapgone(struct vnode *); 172void ffs_snapgone(struct vnode *);
160int ffs_snapshot_read(struct vnode *, struct uio *, int); 173int ffs_snapshot_read(struct vnode *, struct uio *, int);

cvs diff -r1.126 -r1.127 src/sys/ufs/ffs/ffs_inode.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_inode.c 2020/02/23 15:46:42 1.126
+++ src/sys/ufs/ffs/ffs_inode.c 2020/04/18 19:18:34 1.127
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_inode.c,v 1.126 2020/02/23 15:46:42 ad Exp $ */ 1/* $NetBSD: ffs_inode.c,v 1.127 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc. 8 * by Wasabi Systems, Inc.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95 60 * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.126 2020/02/23 15:46:42 ad Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.127 2020/04/18 19:18:34 christos Exp $");
65 65
66#if defined(_KERNEL_OPT) 66#if defined(_KERNEL_OPT)
67#include "opt_ffs.h" 67#include "opt_ffs.h"
68#include "opt_quota.h" 68#include "opt_quota.h"
69#endif 69#endif
70 70
71#include <sys/param.h> 71#include <sys/param.h>
72#include <sys/systm.h> 72#include <sys/systm.h>
73#include <sys/buf.h> 73#include <sys/buf.h>
74#include <sys/file.h> 74#include <sys/file.h>
75#include <sys/fstrans.h> 75#include <sys/fstrans.h>
76#include <sys/kauth.h> 76#include <sys/kauth.h>
77#include <sys/kernel.h> 77#include <sys/kernel.h>
@@ -199,65 +199,100 @@ ffs_update(struct vnode *vp, const struc @@ -199,65 +199,100 @@ ffs_update(struct vnode *vp, const struc
199#define SINGLE 0 /* index of single indirect block */ 199#define SINGLE 0 /* index of single indirect block */
200#define DOUBLE 1 /* index of double indirect block */ 200#define DOUBLE 1 /* index of double indirect block */
201#define TRIPLE 2 /* index of triple indirect block */ 201#define TRIPLE 2 /* index of triple indirect block */
202/* 202/*
203 * Truncate the inode oip to at most length size, freeing the 203 * Truncate the inode oip to at most length size, freeing the
204 * disk blocks. 204 * disk blocks.
205 */ 205 */
206int 206int
207ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) 207ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred)
208{ 208{
209 daddr_t lastblock; 209 daddr_t lastblock;
210 struct inode *oip = VTOI(ovp); 210 struct inode *oip = VTOI(ovp);
211 daddr_t bn, lastiblock[UFS_NIADDR], indir_lbn[UFS_NIADDR]; 211 daddr_t bn, lastiblock[UFS_NIADDR], indir_lbn[UFS_NIADDR];
212 daddr_t blks[UFS_NDADDR + UFS_NIADDR]; 212 daddr_t blks[UFS_NDADDR + UFS_NIADDR], oldblks[UFS_NDADDR + UFS_NIADDR];
213 struct fs *fs; 213 struct fs *fs;
 214 int extblocks;
214 int offset, pgoffset, level; 215 int offset, pgoffset, level;
215 int64_t blocksreleased = 0; 216 int64_t blocksreleased = 0, datablocks;
216 int i, aflag, nblocks; 217 int i, aflag, nblocks;
217 int error, allerror = 0; 218 int error, allerror = 0;
218 off_t osize; 219 off_t osize;
219 int sync; 220 int sync;
220 struct ufsmount *ump = oip->i_ump; 221 struct ufsmount *ump = oip->i_ump;
221 void *dcookie; 222 void *dcookie;
222 223
223 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp); 224 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp);
224 225
225 if (ovp->v_type == VCHR || ovp->v_type == VBLK || 226 if (ovp->v_type == VCHR || ovp->v_type == VBLK ||
226 ovp->v_type == VFIFO || ovp->v_type == VSOCK) { 227 ovp->v_type == VFIFO || ovp->v_type == VSOCK) {
227 KASSERT(oip->i_size == 0); 228 KASSERT(oip->i_size == 0);
228 return 0; 229 return 0;
229 } 230 }
230 231
231 if (length < 0) 232 if (length < 0)
232 return (EINVAL); 233 return (EINVAL);
233 234
 235 fs = oip->i_fs;
 236#define i_din2 i_din.ffs2_din
 237 extblocks = 0;
 238 datablocks = DIP(oip, blocks);
 239 if (fs->fs_magic == FS_UFS2_MAGIC && oip->i_din2->di_extsize > 0) {
 240 extblocks = btodb(ffs_fragroundup(fs, oip->i_din2->di_extsize));
 241 datablocks -= extblocks;
 242 }
 243 if ((ioflag & IO_EXT) && extblocks > 0) {
 244 if (length != 0)
 245 panic("ffs_truncate: partial trunc of extdata");
 246 {
 247#ifdef QUOTA
 248 (void) chkdq(oip, -extblocks, NOCRED, FORCE);
 249#endif
 250 vinvalbuf(ovp, 0, cred, curlwp, 0, 0);
 251 osize = oip->i_din2->di_extsize;
 252 oip->i_din2->di_blocks -= extblocks;
 253 oip->i_din2->di_extsize = 0;
 254 for (i = 0; i < UFS_NXADDR; i++) {
 255 oldblks[i] = oip->i_din2->di_extb[i];
 256 oip->i_din2->di_extb[i] = 0;
 257 }
 258 oip->i_flag |= IN_CHANGE;
 259 if ((error = ffs_update(ovp, NULL, NULL, 0)))
 260 return (error);
 261 for (i = 0; i < UFS_NXADDR; i++) {
 262 if (oldblks[i] == 0)
 263 continue;
 264 ffs_blkfree(fs, oip->i_devvp, oldblks[i],
 265 ffs_sblksize(fs, osize, i), oip->i_number);
 266 }
 267 extblocks = 0;
 268 }
 269 }
234 if (ovp->v_type == VLNK && 270 if (ovp->v_type == VLNK &&
235 (oip->i_size < ump->um_maxsymlinklen || 271 (oip->i_size < ump->um_maxsymlinklen ||
236 (ump->um_maxsymlinklen == 0 && DIP(oip, blocks) == 0))) { 272 (ump->um_maxsymlinklen == 0 && datablocks == 0))) {
237 KDASSERT(length == 0); 273 KDASSERT(length == 0);
238 memset(SHORTLINK(oip), 0, (size_t)oip->i_size); 274 memset(SHORTLINK(oip), 0, (size_t)oip->i_size);
239 oip->i_size = 0; 275 oip->i_size = 0;
240 DIP_ASSIGN(oip, size, 0); 276 DIP_ASSIGN(oip, size, 0);
241 oip->i_flag |= IN_CHANGE | IN_UPDATE; 277 oip->i_flag |= IN_CHANGE | IN_UPDATE;
242 return (ffs_update(ovp, NULL, NULL, 0)); 278 return (ffs_update(ovp, NULL, NULL, 0));
243 } 279 }
244 if (oip->i_size == length) { 280 if (oip->i_size == length) {
245 /* still do a uvm_vnp_setsize() as writesize may be larger */ 281 /* still do a uvm_vnp_setsize() as writesize may be larger */
246 uvm_vnp_setsize(ovp, length); 282 uvm_vnp_setsize(ovp, length);
247 oip->i_flag |= IN_CHANGE | IN_UPDATE; 283 oip->i_flag |= IN_CHANGE | IN_UPDATE;
248 return (ffs_update(ovp, NULL, NULL, 0)); 284 return (ffs_update(ovp, NULL, NULL, 0));
249 } 285 }
250 fs = oip->i_fs; 
251 if (length > ump->um_maxfilesize) 286 if (length > ump->um_maxfilesize)
252 return (EFBIG); 287 return (EFBIG);
253 288
254 if ((oip->i_flags & SF_SNAPSHOT) != 0) 289 if ((oip->i_flags & SF_SNAPSHOT) != 0)
255 ffs_snapremove(ovp); 290 ffs_snapremove(ovp);
256 291
257 osize = oip->i_size; 292 osize = oip->i_size;
258 aflag = ioflag & IO_SYNC ? B_SYNC : 0; 293 aflag = ioflag & IO_SYNC ? B_SYNC : 0;
259 294
260 /* 295 /*
261 * Lengthen the size of the file. We must ensure that the 296 * Lengthen the size of the file. We must ensure that the
262 * last byte of the file is allocated. Since the smallest 297 * last byte of the file is allocated. Since the smallest
263 * value of osize is 0, length will be at least 1. 298 * value of osize is 0, length will be at least 1.
@@ -405,30 +440,27 @@ ffs_truncate(struct vnode *ovp, off_t le @@ -405,30 +440,27 @@ ffs_truncate(struct vnode *ovp, off_t le
405 oip->i_size = osize; 440 oip->i_size = osize;
406 DIP_ASSIGN(oip, size, osize); 441 DIP_ASSIGN(oip, size, osize);
407 error = vtruncbuf(ovp, lastblock + 1, 0, 0); 442 error = vtruncbuf(ovp, lastblock + 1, 0, 0);
408 if (error && !allerror) 443 if (error && !allerror)
409 allerror = error; 444 allerror = error;
410 445
411 /* 446 /*
412 * Indirect blocks first. 447 * Indirect blocks first.
413 */ 448 */
414 indir_lbn[SINGLE] = -UFS_NDADDR; 449 indir_lbn[SINGLE] = -UFS_NDADDR;
415 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - FFS_NINDIR(fs) - 1; 450 indir_lbn[DOUBLE] = indir_lbn[SINGLE] - FFS_NINDIR(fs) - 1;
416 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - FFS_NINDIR(fs) * FFS_NINDIR(fs) - 1; 451 indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - FFS_NINDIR(fs) * FFS_NINDIR(fs) - 1;
417 for (level = TRIPLE; level >= SINGLE; level--) { 452 for (level = TRIPLE; level >= SINGLE; level--) {
418 if (oip->i_ump->um_fstype == UFS1) 453 bn = ffs_getib(fs, oip, level);
419 bn = ufs_rw32(oip->i_ffs1_ib[level],UFS_FSNEEDSWAP(fs)); 
420 else 
421 bn = ufs_rw64(oip->i_ffs2_ib[level],UFS_FSNEEDSWAP(fs)); 
422 if (bn != 0) { 454 if (bn != 0) {
423 if (lastiblock[level] < 0 && 455 if (lastiblock[level] < 0 &&
424 oip->i_ump->um_mountp->mnt_wapbl) { 456 oip->i_ump->um_mountp->mnt_wapbl) {
425 error = UFS_WAPBL_REGISTER_DEALLOCATION( 457 error = UFS_WAPBL_REGISTER_DEALLOCATION(
426 oip->i_ump->um_mountp, 458 oip->i_ump->um_mountp,
427 FFS_FSBTODB(fs, bn), fs->fs_bsize, 459 FFS_FSBTODB(fs, bn), fs->fs_bsize,
428 &dcookie); 460 &dcookie);
429 if (error) 461 if (error)
430 goto out; 462 goto out;
431 } else { 463 } else {
432 dcookie = NULL; 464 dcookie = NULL;
433 } 465 }
434  466
@@ -451,57 +483,51 @@ ffs_truncate(struct vnode *ovp, off_t le @@ -451,57 +483,51 @@ ffs_truncate(struct vnode *ovp, off_t le
451 blocksreleased += nblocks; 483 blocksreleased += nblocks;
452 } 484 }
453 } 485 }
454 if (lastiblock[level] >= 0) 486 if (lastiblock[level] >= 0)
455 goto done; 487 goto done;
456 } 488 }
457 489
458 /* 490 /*
459 * All whole direct blocks or frags. 491 * All whole direct blocks or frags.
460 */ 492 */
461 for (i = UFS_NDADDR - 1; i > lastblock; i--) { 493 for (i = UFS_NDADDR - 1; i > lastblock; i--) {
462 long bsize; 494 long bsize;
463 495
464 if (oip->i_ump->um_fstype == UFS1) 496 bn = ffs_getdb(fs, oip, i);
465 bn = ufs_rw32(oip->i_ffs1_db[i], UFS_FSNEEDSWAP(fs)); 
466 else 
467 bn = ufs_rw64(oip->i_ffs2_db[i], UFS_FSNEEDSWAP(fs)); 
468 if (bn == 0) 497 if (bn == 0)
469 continue; 498 continue;
470 499
471 bsize = ffs_blksize(fs, oip, i); 500 bsize = ffs_blksize(fs, oip, i);
472 if ((oip->i_ump->um_mountp->mnt_wapbl) && 501 if ((oip->i_ump->um_mountp->mnt_wapbl) &&
473 (ovp->v_type != VREG)) { 502 (ovp->v_type != VREG)) {
474 error = UFS_WAPBL_REGISTER_DEALLOCATION( 503 error = UFS_WAPBL_REGISTER_DEALLOCATION(
475 oip->i_ump->um_mountp, 504 oip->i_ump->um_mountp,
476 FFS_FSBTODB(fs, bn), bsize, NULL); 505 FFS_FSBTODB(fs, bn), bsize, NULL);
477 if (error) 506 if (error)
478 goto out; 507 goto out;
479 } else 508 } else
480 ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number); 509 ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number);
481 DIP_ASSIGN(oip, db[i], 0); 510 DIP_ASSIGN(oip, db[i], 0);
482 blocksreleased += btodb(bsize); 511 blocksreleased += btodb(bsize);
483 } 512 }
484 if (lastblock < 0) 513 if (lastblock < 0)
485 goto done; 514 goto done;
486 515
487 /* 516 /*
488 * Finally, look for a change in size of the 517 * Finally, look for a change in size of the
489 * last direct block; release any frags. 518 * last direct block; release any frags.
490 */ 519 */
491 if (oip->i_ump->um_fstype == UFS1) 520 bn = ffs_getdb(fs, oip, lastblock);
492 bn = ufs_rw32(oip->i_ffs1_db[lastblock], UFS_FSNEEDSWAP(fs)); 
493 else 
494 bn = ufs_rw64(oip->i_ffs2_db[lastblock], UFS_FSNEEDSWAP(fs)); 
495 if (bn != 0) { 521 if (bn != 0) {
496 long oldspace, newspace; 522 long oldspace, newspace;
497 523
498 /* 524 /*
499 * Calculate amount of space we're giving 525 * Calculate amount of space we're giving
500 * back as old block size minus new block size. 526 * back as old block size minus new block size.
501 */ 527 */
502 oldspace = ffs_blksize(fs, oip, lastblock); 528 oldspace = ffs_blksize(fs, oip, lastblock);
503 oip->i_size = length; 529 oip->i_size = length;
504 DIP_ASSIGN(oip, size, length); 530 DIP_ASSIGN(oip, size, length);
505 newspace = ffs_blksize(fs, oip, lastblock); 531 newspace = ffs_blksize(fs, oip, lastblock);
506 if (newspace == 0) 532 if (newspace == 0)
507 panic("itrunc: newspace"); 533 panic("itrunc: newspace");
@@ -526,29 +552,29 @@ ffs_truncate(struct vnode *ovp, off_t le @@ -526,29 +552,29 @@ ffs_truncate(struct vnode *ovp, off_t le
526 } 552 }
527 } 553 }
528 554
529done: 555done:
530 for (level = SINGLE; level <= TRIPLE; level++) 556 for (level = SINGLE; level <= TRIPLE; level++)
531 KASSERTMSG((blks[UFS_NDADDR + level] == DIP(oip, ib[level])), 557 KASSERTMSG((blks[UFS_NDADDR + level] == DIP(oip, ib[level])),
532 "itrunc1 blk mismatch: %jx != %jx", 558 "itrunc1 blk mismatch: %jx != %jx",
533 (uintmax_t)blks[UFS_NDADDR + level], 559 (uintmax_t)blks[UFS_NDADDR + level],
534 (uintmax_t)DIP(oip, ib[level])); 560 (uintmax_t)DIP(oip, ib[level]));
535 for (i = 0; i < UFS_NDADDR; i++) 561 for (i = 0; i < UFS_NDADDR; i++)
536 KASSERTMSG((blks[i] == DIP(oip, db[i])), 562 KASSERTMSG((blks[i] == DIP(oip, db[i])),
537 "itrunc2 blk mismatch: %jx != %jx", 563 "itrunc2 blk mismatch: %jx != %jx",
538 (uintmax_t)blks[i], (uintmax_t)DIP(oip, db[i])); 564 (uintmax_t)blks[i], (uintmax_t)DIP(oip, db[i]));
539 KASSERTMSG((length != 0 || LIST_EMPTY(&ovp->v_cleanblkhd)), 565 KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_cleanblkhd)),
540 "itrunc3: zero length and nonempty cleanblkhd"); 566 "itrunc3: zero length and nonempty cleanblkhd");
541 KASSERTMSG((length != 0 || LIST_EMPTY(&ovp->v_dirtyblkhd)), 567 KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_dirtyblkhd)),
542 "itrunc3: zero length and nonempty dirtyblkhd"); 568 "itrunc3: zero length and nonempty dirtyblkhd");
543 569
544out: 570out:
545 /* 571 /*
546 * Set length back to old size if deallocation failed. Some indirect 572 * Set length back to old size if deallocation failed. Some indirect
547 * blocks were deallocated creating a hole, but that is okay. 573 * blocks were deallocated creating a hole, but that is okay.
548 */ 574 */
549 if (error == EAGAIN) { 575 if (error == EAGAIN) {
550 if (!allerror) 576 if (!allerror)
551 allerror = error; 577 allerror = error;
552 length = osize; 578 length = osize;
553 uvm_vnp_setsize(ovp, length); 579 uvm_vnp_setsize(ovp, length);
554 } 580 }

cvs diff -r1.151 -r1.152 src/sys/ufs/ffs/ffs_snapshot.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_snapshot.c 2020/02/23 15:46:42 1.151
+++ src/sys/ufs/ffs/ffs_snapshot.c 2020/04/18 19:18:34 1.152
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_snapshot.c,v 1.151 2020/02/23 15:46:42 ad Exp $ */ 1/* $NetBSD: ffs_snapshot.c,v 1.152 2020/04/18 19:18:34 christos Exp $ */
2 2
3/* 3/*
4 * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved. 4 * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved.
5 * 5 *
6 * Further information about snapshots can be obtained from: 6 * Further information about snapshots can be obtained from:
7 * 7 *
8 * Marshall Kirk McKusick http://www.mckusick.com/softdep/ 8 * Marshall Kirk McKusick http://www.mckusick.com/softdep/
9 * 1614 Oxford Street mckusick@mckusick.com 9 * 1614 Oxford Street mckusick@mckusick.com
10 * Berkeley, CA 94709-1608 +1-510-843-9542 10 * Berkeley, CA 94709-1608 +1-510-843-9542
11 * USA 11 * USA
12 * 12 *
13 * Redistribution and use in source and binary forms, with or without 13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions 14 * modification, are permitted provided that the following conditions
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 33 * SUCH DAMAGE.
34 * 34 *
35 * @(#)ffs_snapshot.c 8.11 (McKusick) 7/23/00 35 * @(#)ffs_snapshot.c 8.11 (McKusick) 7/23/00
36 * 36 *
37 * from FreeBSD: ffs_snapshot.c,v 1.79 2004/02/13 02:02:06 kuriyama Exp 37 * from FreeBSD: ffs_snapshot.c,v 1.79 2004/02/13 02:02:06 kuriyama Exp
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.151 2020/02/23 15:46:42 ad Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.152 2020/04/18 19:18:34 christos Exp $");
42 42
43#if defined(_KERNEL_OPT) 43#if defined(_KERNEL_OPT)
44#include "opt_ffs.h" 44#include "opt_ffs.h"
45#include "opt_quota.h" 45#include "opt_quota.h"
46#endif 46#endif
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/kernel.h> 49#include <sys/kernel.h>
50#include <sys/systm.h> 50#include <sys/systm.h>
51#include <sys/conf.h> 51#include <sys/conf.h>
52#include <sys/buf.h> 52#include <sys/buf.h>
53#include <sys/proc.h> 53#include <sys/proc.h>
54#include <sys/namei.h> 54#include <sys/namei.h>
@@ -433,36 +433,34 @@ snapshot_setup(struct mount *mp, struct  @@ -433,36 +433,34 @@ snapshot_setup(struct mount *mp, struct
433 433
434 /* 434 /*
435 * Check mount, readonly reference and owner. 435 * Check mount, readonly reference and owner.
436 */ 436 */
437 if (vp->v_mount != mp) 437 if (vp->v_mount != mp)
438 return EXDEV; 438 return EXDEV;
439 if (vp->v_writecount != 0) 439 if (vp->v_writecount != 0)
440 return EBUSY; 440 return EBUSY;
441 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_SNAPSHOT, 441 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_SNAPSHOT,
442 0, mp, vp, NULL); 442 0, mp, vp, NULL);
443 if (error) 443 if (error)
444 return EACCES; 444 return EACCES;
445 445
446 if (vp->v_size != 0) { 446 /*
447 /* 447 * Must completely truncate the file here. Allocated
448 * Must completely truncate the file here. Allocated 448 * blocks on a snapshot mean that block has been copied
449 * blocks on a snapshot mean that block has been copied 449 * on write, see ffs_copyonwrite() testing "blkno != 0"
450 * on write, see ffs_copyonwrite() testing "blkno != 0" 450 */
451 */ 451 error = ufs_truncate_all(vp);
452 error = ufs_truncate_retry(vp, 0, NOCRED); 452 if (error)
453 if (error) 453 return error;
454 return error; 
455 } 
456 454
457 /* Change inode to snapshot type file. */ 455 /* Change inode to snapshot type file. */
458 error = UFS_WAPBL_BEGIN(mp); 456 error = UFS_WAPBL_BEGIN(mp);
459 if (error) 457 if (error)
460 return error; 458 return error;
461#if defined(QUOTA) || defined(QUOTA2) 459#if defined(QUOTA) || defined(QUOTA2)
462 /* shapshot inodes are not accounted in quotas */ 460 /* shapshot inodes are not accounted in quotas */
463 chkiq(ip, -1, l->l_cred, 0); 461 chkiq(ip, -1, l->l_cred, 0);
464#endif 462#endif
465 ip->i_flags |= (SF_SNAPSHOT | SF_SNAPINVAL); 463 ip->i_flags |= (SF_SNAPSHOT | SF_SNAPINVAL);
466 DIP_ASSIGN(ip, flags, ip->i_flags); 464 DIP_ASSIGN(ip, flags, ip->i_flags);
467 ip->i_flag |= IN_CHANGE | IN_UPDATE; 465 ip->i_flag |= IN_CHANGE | IN_UPDATE;
468 ffs_update(vp, NULL, NULL, UPDATE_WAIT); 466 ffs_update(vp, NULL, NULL, UPDATE_WAIT);

cvs diff -r1.130 -r1.131 src/sys/ufs/ffs/ffs_vnops.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_vnops.c 2020/02/23 15:46:42 1.130
+++ src/sys/ufs/ffs/ffs_vnops.c 2020/04/18 19:18:34 1.131
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_vnops.c,v 1.130 2020/02/23 15:46:42 ad Exp $ */ 1/* $NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc, and by Andrew Doran. 8 * by Wasabi Systems, Inc, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 60 * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.130 2020/02/23 15:46:42 ad Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $");
65 65
66#if defined(_KERNEL_OPT) 66#if defined(_KERNEL_OPT)
67#include "opt_ffs.h" 67#include "opt_ffs.h"
68#include "opt_wapbl.h" 68#include "opt_wapbl.h"
69#endif 69#endif
70 70
71#include <sys/param.h> 71#include <sys/param.h>
72#include <sys/systm.h> 72#include <sys/systm.h>
73#include <sys/resourcevar.h> 73#include <sys/resourcevar.h>
74#include <sys/kernel.h> 74#include <sys/kernel.h>
75#include <sys/file.h> 75#include <sys/file.h>
76#include <sys/stat.h> 76#include <sys/stat.h>
77#include <sys/buf.h> 77#include <sys/buf.h>
@@ -602,170 +602,13 @@ ffs_gop_size(struct vnode *vp, off_t siz @@ -602,170 +602,13 @@ ffs_gop_size(struct vnode *vp, off_t siz
602{ 602{
603 struct inode *ip = VTOI(vp); 603 struct inode *ip = VTOI(vp);
604 struct fs *fs = ip->i_fs; 604 struct fs *fs = ip->i_fs;
605 daddr_t olbn, nlbn; 605 daddr_t olbn, nlbn;
606 606
607 olbn = ffs_lblkno(fs, ip->i_size); 607 olbn = ffs_lblkno(fs, ip->i_size);
608 nlbn = ffs_lblkno(fs, size); 608 nlbn = ffs_lblkno(fs, size);
609 if (nlbn < UFS_NDADDR && olbn <= nlbn) { 609 if (nlbn < UFS_NDADDR && olbn <= nlbn) {
610 *eobp = ffs_fragroundup(fs, size); 610 *eobp = ffs_fragroundup(fs, size);
611 } else { 611 } else {
612 *eobp = ffs_blkroundup(fs, size); 612 *eobp = ffs_blkroundup(fs, size);
613 } 613 }
614} 614}
615 
616int 
617ffs_openextattr(void *v) 
618{ 
619 struct vop_openextattr_args /* { 
620 struct vnode *a_vp; 
621 kauth_cred_t a_cred; 
622 struct proc *a_p; 
623 } */ *ap = v; 
624 struct inode *ip = VTOI(ap->a_vp); 
625 struct fs *fs = ip->i_fs; 
626 
627 /* Not supported for UFS1 file systems. */ 
628 if (fs->fs_magic == FS_UFS1_MAGIC) 
629 return (EOPNOTSUPP); 
630 
631 /* XXX Not implemented for UFS2 file systems. */ 
632 return (EOPNOTSUPP); 
633} 
634 
635int 
636ffs_closeextattr(void *v) 
637{ 
638 struct vop_closeextattr_args /* { 
639 struct vnode *a_vp; 
640 int a_commit; 
641 kauth_cred_t a_cred; 
642 struct proc *a_p; 
643 } */ *ap = v; 
644 struct inode *ip = VTOI(ap->a_vp); 
645 struct fs *fs = ip->i_fs; 
646 
647 /* Not supported for UFS1 file systems. */ 
648 if (fs->fs_magic == FS_UFS1_MAGIC) 
649 return (EOPNOTSUPP); 
650 
651 /* XXX Not implemented for UFS2 file systems. */ 
652 return (EOPNOTSUPP); 
653} 
654 
655int 
656ffs_getextattr(void *v) 
657{ 
658 struct vop_getextattr_args /* { 
659 struct vnode *a_vp; 
660 int a_attrnamespace; 
661 const char *a_name; 
662 struct uio *a_uio; 
663 size_t *a_size; 
664 kauth_cred_t a_cred; 
665 struct proc *a_p; 
666 } */ *ap = v; 
667 struct vnode *vp = ap->a_vp; 
668 struct inode *ip = VTOI(vp); 
669 struct fs *fs = ip->i_fs; 
670 
671 if (fs->fs_magic == FS_UFS1_MAGIC) { 
672#ifdef UFS_EXTATTR 
673 int error; 
674 
675 error = ufs_getextattr(ap); 
676 return error; 
677#else 
678 return (EOPNOTSUPP); 
679#endif 
680 } 
681 
682 /* XXX Not implemented for UFS2 file systems. */ 
683 return (EOPNOTSUPP); 
684} 
685 
686int 
687ffs_setextattr(void *v) 
688{ 
689 struct vop_setextattr_args /* { 
690 struct vnode *a_vp; 
691 int a_attrnamespace; 
692 const char *a_name; 
693 struct uio *a_uio; 
694 kauth_cred_t a_cred; 
695 struct proc *a_p; 
696 } */ *ap = v; 
697 struct vnode *vp = ap->a_vp; 
698 struct inode *ip = VTOI(vp); 
699 struct fs *fs = ip->i_fs; 
700 
701 if (fs->fs_magic == FS_UFS1_MAGIC) { 
702#ifdef UFS_EXTATTR 
703 int error; 
704 
705 error = ufs_setextattr(ap); 
706 return error; 
707#else 
708 return (EOPNOTSUPP); 
709#endif 
710 } 
711 
712 /* XXX Not implemented for UFS2 file systems. */ 
713 return (EOPNOTSUPP); 
714} 
715 
716int 
717ffs_listextattr(void *v) 
718{ 
719 struct vop_listextattr_args /* { 
720 struct vnode *a_vp; 
721 int a_attrnamespace; 
722 struct uio *a_uio; 
723 size_t *a_size; 
724 kauth_cred_t a_cred; 
725 struct proc *a_p; 
726 } */ *ap = v; 
727 struct inode *ip = VTOI(ap->a_vp); 
728 struct fs *fs = ip->i_fs; 
729 
730 if (fs->fs_magic == FS_UFS1_MAGIC) { 
731#ifdef UFS_EXTATTR 
732 int error; 
733 
734 error = ufs_listextattr(ap); 
735 return error; 
736#else 
737 return (EOPNOTSUPP); 
738#endif 
739 } 
740 
741 /* XXX Not implemented for UFS2 file systems. */ 
742 return (EOPNOTSUPP); 
743} 
744 
745int 
746ffs_deleteextattr(void *v) 
747{ 
748 struct vop_deleteextattr_args /* { 
749 struct vnode *a_vp; 
750 int a_attrnamespace; 
751 kauth_cred_t a_cred; 
752 struct proc *a_p; 
753 } */ *ap = v; 
754 struct vnode *vp = ap->a_vp; 
755 struct inode *ip = VTOI(vp); 
756 struct fs *fs = ip->i_fs; 
757 
758 if (fs->fs_magic == FS_UFS1_MAGIC) { 
759#ifdef UFS_EXTATTR 
760 int error; 
761 
762 error = ufs_deleteextattr(ap); 
763 return error; 
764#else 
765 return (EOPNOTSUPP); 
766#endif 
767 } 
768 
769 /* XXX Not implemented for UFS2 file systems. */ 
770 return (EOPNOTSUPP); 
771} 

cvs diff -r1.66 -r1.67 src/sys/ufs/ffs/fs.h (expand / switch to unified diff)

--- src/sys/ufs/ffs/fs.h 2015/02/14 09:06:11 1.66
+++ src/sys/ufs/ffs/fs.h 2020/04/18 19:18:34 1.67
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fs.h,v 1.66 2015/02/14 09:06:11 maxv Exp $ */ 1/* $NetBSD: fs.h,v 1.67 2020/04/18 19:18:34 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1993 4 * Copyright (c) 1982, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -682,26 +682,34 @@ struct ocg { @@ -682,26 +682,34 @@ struct ocg {
682 ((loc) >> (fs)->fs_fshift) 682 ((loc) >> (fs)->fs_fshift)
683#define ffs_blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ 683#define ffs_blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
684 (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) 684 (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
685#define ffs_fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ 685#define ffs_fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
686 (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) 686 (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
687#define ffs_fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ 687#define ffs_fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
688 ((frags) >> (fs)->fs_fragshift) 688 ((frags) >> (fs)->fs_fragshift)
689#define ffs_blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ 689#define ffs_blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
690 ((blks) << (fs)->fs_fragshift) 690 ((blks) << (fs)->fs_fragshift)
691#define ffs_fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ 691#define ffs_fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
692 ((fsb) & ((fs)->fs_frag - 1)) 692 ((fsb) & ((fs)->fs_frag - 1))
693#define ffs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ 693#define ffs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
694 ((fsb) &~ ((fs)->fs_frag - 1)) 694 ((fsb) &~ ((fs)->fs_frag - 1))
 695#define ffs_getdb(fs, ip, lb) \
 696 ((fs)->fs_magic == FS_UFS2_MAGIC ? \
 697 (daddr_t)ufs_rw64((ip)->i_ffs2_db[lb], UFS_FSNEEDSWAP(fs)) : \
 698 (daddr_t)ufs_rw32((ip)->i_ffs1_db[lb], UFS_FSNEEDSWAP(fs)))
 699#define ffs_getib(fs, ip, lb) \
 700 ((fs)->fs_magic == FS_UFS2_MAGIC ? \
 701 (daddr_t)ufs_rw64((ip)->i_ffs2_ib[lb], UFS_FSNEEDSWAP(fs)) : \
 702 (daddr_t)ufs_rw32((ip)->i_ffs1_ib[lb], UFS_FSNEEDSWAP(fs)))
695 703
696/* 704/*
697 * Determine the number of available frags given a 705 * Determine the number of available frags given a
698 * percentage to hold in reserve. 706 * percentage to hold in reserve.
699 */ 707 */
700#define freespace(fs, percentreserved) \ 708#define freespace(fs, percentreserved) \
701 (ffs_blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ 709 (ffs_blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
702 (fs)->fs_cstotal.cs_nffree - \ 710 (fs)->fs_cstotal.cs_nffree - \
703 (((off_t)((fs)->fs_dsize)) * (percentreserved) / 100)) 711 (((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))
704 712
705/* 713/*
706 * Determining the size of a file block in the file system. 714 * Determining the size of a file block in the file system.
707 */ 715 */

cvs diff -r1.11 -r1.12 src/sys/ufs/ufs/extattr.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/extattr.h 2014/12/19 10:59:21 1.11
+++ src/sys/ufs/ufs/extattr.h 2020/04/18 19:18:34 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: extattr.h,v 1.11 2014/12/19 10:59:21 manu Exp $ */ 1/* $NetBSD: extattr.h,v 1.12 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999-2001 Robert N. M. Watson 4 * Copyright (c) 1999-2001 Robert N. M. Watson
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project. 7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -62,26 +62,59 @@ @@ -62,26 +62,59 @@
62struct ufs_extattr_fileheader { 62struct ufs_extattr_fileheader {
63 uint32_t uef_magic; /* magic number for sanity checking */ 63 uint32_t uef_magic; /* magic number for sanity checking */
64 uint32_t uef_version; /* version of attribute file */ 64 uint32_t uef_version; /* version of attribute file */
65 uint32_t uef_size; /* size of attributes, w/o header */ 65 uint32_t uef_size; /* size of attributes, w/o header */
66}; 66};
67 67
68struct ufs_extattr_header { 68struct ufs_extattr_header {
69 uint32_t ueh_flags; /* flags for attribute */ 69 uint32_t ueh_flags; /* flags for attribute */
70 uint32_t ueh_len; /* local defined length; <= uef_size */ 70 uint32_t ueh_len; /* local defined length; <= uef_size */
71 uint32_t ueh_i_gen; /* generation number for sanity */ 71 uint32_t ueh_i_gen; /* generation number for sanity */
72 /* data follows the header */ 72 /* data follows the header */
73}; 73};
74 74
 75/*
 76 * This structure defines the required fields of an extended-attribute header.
 77 */
 78struct extattr {
 79 uint32_t ea_length; /* length of this attribute */
 80 uint8_t ea_namespace; /* name space of this attribute */
 81 uint8_t ea_contentpadlen; /* bytes of padding at end of attribute */
 82 uint8_t ea_namelength; /* length of attribute name */
 83 char ea_name[1]; /* attribute name (NOT nul-terminated) */
 84 /* padding, if any, to align attribute content to 8 byte boundary */
 85 /* extended attribute content follows */
 86};
 87
 88/*
 89 * These macros are used to access and manipulate an extended attribute:
 90 *
 91 * EXTATTR_NEXT(eap) returns a pointer to the next extended attribute
 92 * following eap.
 93 * EXTATTR_CONTENT(eap) returns a pointer to the extended attribute
 94 * content referenced by eap.
 95 * EXTATTR_CONTENT_SIZE(eap) returns the size of the extended attribute
 96 * content referenced by eap.
 97 */
 98#define EXTATTR_NEXT(eap) \
 99 ((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length))
 100#define EXTATTR_CONTENT(eap) \
 101 (void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap))
 102#define EXTATTR_CONTENT_SIZE(eap) \
 103 ((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
 104/* -1 below compensates for ea_name[1] */
 105#define EXTATTR_BASE_LENGTH(eap) \
 106 roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8)
 107
75#ifdef _KERNEL 108#ifdef _KERNEL
76 109
77#ifdef MALLOC_DECLARE 110#ifdef MALLOC_DECLARE
78MALLOC_DECLARE(M_EXTATTR); 111MALLOC_DECLARE(M_EXTATTR);
79#endif 112#endif
80 113
81struct vnode; 114struct vnode;
82LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry); 115LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry);
83struct ufs_extattr_list_entry { 116struct ufs_extattr_list_entry {
84 LIST_ENTRY(ufs_extattr_list_entry) uele_entries; 117 LIST_ENTRY(ufs_extattr_list_entry) uele_entries;
85 struct ufs_extattr_fileheader uele_fileheader; 118 struct ufs_extattr_fileheader uele_fileheader;
86 int uele_attrnamespace; 119 int uele_attrnamespace;
87 char uele_attrname[UFS_EXTATTR_MAXEXTATTRNAME]; 120 char uele_attrname[UFS_EXTATTR_MAXEXTATTRNAME];

cvs diff -r1.76 -r1.77 src/sys/ufs/ufs/inode.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/inode.h 2017/08/20 12:09:06 1.76
+++ src/sys/ufs/ufs/inode.h 2020/04/18 19:18:34 1.77
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: inode.h,v 1.76 2017/08/20 12:09:06 maya Exp $ */ 1/* $NetBSD: inode.h,v 1.77 2020/04/18 19:18:34 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1989, 1993 4 * Copyright (c) 1982, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -146,26 +146,34 @@ struct inode { @@ -146,26 +146,34 @@ struct inode {
146 */ 146 */
147 u_int16_t i_mode; /* IFMT, permissions; see dinode.h. */ 147 u_int16_t i_mode; /* IFMT, permissions; see dinode.h. */
148 int16_t i_nlink; /* File link count. */ 148 int16_t i_nlink; /* File link count. */
149 u_int64_t i_size; /* File byte count. */ 149 u_int64_t i_size; /* File byte count. */
150 u_int32_t i_flags; /* Status flags (chflags). */ 150 u_int32_t i_flags; /* Status flags (chflags). */
151 int32_t i_gen; /* Generation number. */ 151 int32_t i_gen; /* Generation number. */
152 u_int32_t i_uid; /* File owner. */ 152 u_int32_t i_uid; /* File owner. */
153 u_int32_t i_gid; /* File group. */ 153 u_int32_t i_gid; /* File group. */
154 u_int16_t i_omode; /* Old mode, for ufs_reclaim. */ 154 u_int16_t i_omode; /* Old mode, for ufs_reclaim. */
155 155
156 struct dirhash *i_dirhash; /* Hashing for large directories */ 156 struct dirhash *i_dirhash; /* Hashing for large directories */
157 157
158 /* 158 /*
 159 * Data for extended attribute modification.
 160 */
 161 u_char *i_ea_area; /* Pointer to malloced copy of EA area */
 162 unsigned i_ea_len; /* Length of i_ea_area */
 163 int i_ea_error; /* First errno in transaction */
 164 int i_ea_refs; /* Number of users of EA area */
 165
 166 /*
159 * The on-disk dinode itself. 167 * The on-disk dinode itself.
160 */ 168 */
161 union { 169 union {
162 struct ufs1_dinode *ffs1_din; /* 128 bytes of the on-disk dinode. */ 170 struct ufs1_dinode *ffs1_din; /* 128 bytes of the on-disk dinode. */
163 struct ufs2_dinode *ffs2_din; 171 struct ufs2_dinode *ffs2_din;
164 struct ext2fs_dinode *e2fs_din; /* 128 bytes of the on-disk 172 struct ext2fs_dinode *e2fs_din; /* 128 bytes of the on-disk
165 dinode. */ 173 dinode. */
166 } i_din; 174 } i_din;
167}; 175};
168 176
169#define i_ffs1_atime i_din.ffs1_din->di_atime 177#define i_ffs1_atime i_din.ffs1_din->di_atime
170#define i_ffs1_atimensec i_din.ffs1_din->di_atimensec 178#define i_ffs1_atimensec i_din.ffs1_din->di_atimensec
171#define i_ffs1_blocks i_din.ffs1_din->di_blocks 179#define i_ffs1_blocks i_din.ffs1_din->di_blocks
@@ -206,36 +214,36 @@ struct inode { @@ -206,36 +214,36 @@ struct inode {
206#define i_ffs2_rdev i_din.ffs2_din->di_rdev 214#define i_ffs2_rdev i_din.ffs2_din->di_rdev
207#define i_ffs2_size i_din.ffs2_din->di_size 215#define i_ffs2_size i_din.ffs2_din->di_size
208#define i_ffs2_uid i_din.ffs2_din->di_uid 216#define i_ffs2_uid i_din.ffs2_din->di_uid
209#define i_ffs2_kernflags i_din.ffs2_din->di_kernflags 217#define i_ffs2_kernflags i_din.ffs2_din->di_kernflags
210#define i_ffs2_extsize i_din.ffs2_din->di_extsize 218#define i_ffs2_extsize i_din.ffs2_din->di_extsize
211#define i_ffs2_extb i_din.ffs2_din->di_extb 219#define i_ffs2_extb i_din.ffs2_din->di_extb
212 220
213/* These flags are kept in i_flag. */ 221/* These flags are kept in i_flag. */
214#define IN_ACCESS 0x0001 /* Access time update request. */ 222#define IN_ACCESS 0x0001 /* Access time update request. */
215#define IN_CHANGE 0x0002 /* Inode change time update request. */ 223#define IN_CHANGE 0x0002 /* Inode change time update request. */
216#define IN_UPDATE 0x0004 /* Inode written to; update mtime. */ 224#define IN_UPDATE 0x0004 /* Inode written to; update mtime. */
217#define IN_MODIFIED 0x0008 /* Inode has been modified. */ 225#define IN_MODIFIED 0x0008 /* Inode has been modified. */
218#define IN_ACCESSED 0x0010 /* Inode has been accessed. */ 226#define IN_ACCESSED 0x0010 /* Inode has been accessed. */
219/* unused 0x0020 */ /* was IN_RENAME */ 227/* unused 0x0020 */ /* was IN_RENAME */
220#define IN_SHLOCK 0x0040 /* File has shared lock. */ 228#define IN_SHLOCK 0x0040 /* File has shared lock. */
221#define IN_EXLOCK 0x0080 /* File has exclusive lock. */ 229#define IN_EXLOCK 0x0080 /* File has exclusive lock. */
222/* unused 0x0100 */ /* was LFS-only IN_CLEANING */ 230/* unused 0x0100 */ /* was LFS-only IN_CLEANING */
223/* unused 0x0200 */ /* was LFS-only IN_ADIROP */ 231/* unused 0x0200 */ /* was LFS-only IN_ADIROP */
224#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */ 232#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */
225/* unused 0x0800 */ /* what was that? */ 233/* unused 0x0800 */ /* what was that? */
226/* unused 0x1000 */ /* was LFS-only IN_PAGING */ 234/* unused 0x1000 */ /* was LFS-only IN_PAGING */
227#define IN_MODIFY 0x2000 /* Modification time update request. */ 235#define IN_MODIFY 0x2000 /* Modification time update request. */
228/* unused 0x4000 */ /* was LFS-only IN_CDIROP */ 236/* unused 0x4000 */ /* was LFS-only IN_CDIROP */
229 237
230#if defined(_KERNEL) 238#if defined(_KERNEL)
231 239
232/* 240/*
233 * The DIP macro is used to access fields in the dinode that are 241 * The DIP macro is used to access fields in the dinode that are
234 * not cached in the inode itself. 242 * not cached in the inode itself.
235 */ 243 */
236#define DIP(ip, field) \ 244#define DIP(ip, field) \
237 (((ip)->i_ump->um_fstype == UFS1) ? \ 245 (((ip)->i_ump->um_fstype == UFS1) ? \
238 (ip)->i_ffs1_##field : (ip)->i_ffs2_##field) 246 (ip)->i_ffs1_##field : (ip)->i_ffs2_##field)
239 247
240#define DIP_ASSIGN(ip, field, value) \ 248#define DIP_ASSIGN(ip, field, value) \
241 do { \ 249 do { \

cvs diff -r1.84 -r1.85 src/sys/ufs/ufs/ufs_extern.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_extern.h 2020/01/17 20:08:10 1.84
+++ src/sys/ufs/ufs/ufs_extern.h 2020/04/18 19:18:34 1.85
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_extern.h,v 1.84 2020/01/17 20:08:10 ad Exp $ */ 1/* $NetBSD: ufs_extern.h,v 1.85 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993, 1994 4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -101,27 +101,28 @@ int ufsfifo_read(void *); @@ -101,27 +101,28 @@ int ufsfifo_read(void *);
101int ufsfifo_write(void *); 101int ufsfifo_write(void *);
102int ufsfifo_close(void *); 102int ufsfifo_close(void *);
103 103
104/* ufs_bmap.c */ 104/* ufs_bmap.c */
105typedef bool (*ufs_issequential_callback_t)(const struct ufsmount *, 105typedef bool (*ufs_issequential_callback_t)(const struct ufsmount *,
106 daddr_t, daddr_t); 106 daddr_t, daddr_t);
107int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *, 107int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *,
108 int *, int *, ufs_issequential_callback_t); 108 int *, int *, ufs_issequential_callback_t);
109int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *); 109int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *);
110 110
111/* ufs_inode.c */ 111/* ufs_inode.c */
112int ufs_reclaim(struct vnode *); 112int ufs_reclaim(struct vnode *);
113int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int); 113int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int);
114int ufs_truncate_retry(struct vnode *, uint64_t, kauth_cred_t); 114int ufs_truncate_all(struct vnode *);
 115int ufs_truncate_retry(struct vnode *, int, uint64_t, kauth_cred_t);
115 116
116/* ufs_lookup.c */ 117/* ufs_lookup.c */
117void ufs_dirbad(struct inode *, doff_t, const char *); 118void ufs_dirbad(struct inode *, doff_t, const char *);
118const char *ufs_dirbadentry(const struct vnode *, const struct direct *, int); 119const char *ufs_dirbadentry(const struct vnode *, const struct direct *, int);
119void ufs_makedirentry(struct inode *, struct componentname *, 120void ufs_makedirentry(struct inode *, struct componentname *,
120 struct direct *); 121 struct direct *);
121int ufs_direnter(struct vnode *, const struct ufs_lookup_results *, 122int ufs_direnter(struct vnode *, const struct ufs_lookup_results *,
122 struct vnode *, struct direct *, 123 struct vnode *, struct direct *,
123 struct componentname *, struct buf *); 124 struct componentname *, struct buf *);
124int ufs_dirremove(struct vnode *, const struct ufs_lookup_results *, 125int ufs_dirremove(struct vnode *, const struct ufs_lookup_results *,
125 struct inode *, int, int); 126 struct inode *, int, int);
126int ufs_dirrewrite(struct inode *, off_t, 127int ufs_dirrewrite(struct inode *, off_t,
127 struct inode *, ino_t, int, int, int); 128 struct inode *, ino_t, int, int, int);

cvs diff -r1.109 -r1.110 src/sys/ufs/ufs/ufs_inode.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_inode.c 2020/02/23 15:46:43 1.109
+++ src/sys/ufs/ufs/ufs_inode.c 2020/04/18 19:18:34 1.110
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_inode.c,v 1.109 2020/02/23 15:46:43 ad Exp $ */ 1/* $NetBSD: ufs_inode.c,v 1.110 2020/04/18 19:18:34 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95 36 * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.109 2020/02/23 15:46:43 ad Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.110 2020/04/18 19:18:34 christos Exp $");
41 41
42#if defined(_KERNEL_OPT) 42#if defined(_KERNEL_OPT)
43#include "opt_ffs.h" 43#include "opt_ffs.h"
44#include "opt_quota.h" 44#include "opt_quota.h"
45#include "opt_wapbl.h" 45#include "opt_wapbl.h"
46#endif 46#endif
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/systm.h> 49#include <sys/systm.h>
50#include <sys/proc.h> 50#include <sys/proc.h>
51#include <sys/vnode.h> 51#include <sys/vnode.h>
52#include <sys/mount.h> 52#include <sys/mount.h>
53#include <sys/kernel.h> 53#include <sys/kernel.h>
@@ -88,36 +88,31 @@ ufs_inactive(void *v) @@ -88,36 +88,31 @@ ufs_inactive(void *v)
88 88
89 UFS_WAPBL_JUNLOCK_ASSERT(mp); 89 UFS_WAPBL_JUNLOCK_ASSERT(mp);
90 90
91 /* 91 /*
92 * Ignore inodes related to stale file handles. 92 * Ignore inodes related to stale file handles.
93 */ 93 */
94 if (ip->i_mode == 0) 94 if (ip->i_mode == 0)
95 goto out; 95 goto out;
96 96
97 if (ip->i_nlink <= 0 && (mp->mnt_flag & MNT_RDONLY) == 0) { 97 if (ip->i_nlink <= 0 && (mp->mnt_flag & MNT_RDONLY) == 0) {
98#ifdef UFS_EXTATTR 98#ifdef UFS_EXTATTR
99 ufs_extattr_vnode_inactive(vp, curlwp); 99 ufs_extattr_vnode_inactive(vp, curlwp);
100#endif 100#endif
101 
102 /* 101 /*
103 * All file blocks must be freed before we can let the vnode 102 * All file blocks must be freed before we can let the vnode
104 * be reclaimed, so can't postpone full truncating any further. 103 * be reclaimed, so can't postpone full truncating any further.
105 */ 104 */
106 if (ip->i_size != 0) { 105 ufs_truncate_all(vp);
107 allerror = ufs_truncate_retry(vp, 0, NOCRED); 
108 if (allerror) 
109 goto out; 
110 } 
111 106
112#if defined(QUOTA) || defined(QUOTA2) 107#if defined(QUOTA) || defined(QUOTA2)
113 error = UFS_WAPBL_BEGIN(mp); 108 error = UFS_WAPBL_BEGIN(mp);
114 if (error) { 109 if (error) {
115 allerror = error; 110 allerror = error;
116 } else { 111 } else {
117 wapbl_locked = true; 112 wapbl_locked = true;
118 (void)chkiq(ip, -1, NOCRED, 0); 113 (void)chkiq(ip, -1, NOCRED, 0);
119 } 114 }
120#endif 115#endif
121 DIP_ASSIGN(ip, rdev, 0); 116 DIP_ASSIGN(ip, rdev, 0);
122 mode = ip->i_mode; 117 mode = ip->i_mode;
123 ip->i_mode = 0; 118 ip->i_mode = 0;
@@ -282,39 +277,55 @@ ufs_balloc_range(struct vnode *vp, off_t @@ -282,39 +277,55 @@ ufs_balloc_range(struct vnode *vp, off_t
282 uvm_pagelock(pgs[i]); 277 uvm_pagelock(pgs[i]);
283 uvm_pageactivate(pgs[i]); 278 uvm_pageactivate(pgs[i]);
284 uvm_pageunlock(pgs[i]); 279 uvm_pageunlock(pgs[i]);
285 } 280 }
286 uvm_page_unbusy(pgs, npages); 281 uvm_page_unbusy(pgs, npages);
287 rw_exit(uobj->vmobjlock); 282 rw_exit(uobj->vmobjlock);
288 283
289 out: 284 out:
290 kmem_free(pgs, pgssize); 285 kmem_free(pgs, pgssize);
291 return error; 286 return error;
292} 287}
293 288
294int 289int
295ufs_truncate_retry(struct vnode *vp, uint64_t newsize, kauth_cred_t cred) 290ufs_truncate_retry(struct vnode *vp, int ioflag, uint64_t newsize,
 291 kauth_cred_t cred)
296{ 292{
297 struct inode *ip = VTOI(vp); 293 struct inode *ip = VTOI(vp);
298 struct mount *mp = vp->v_mount; 294 struct mount *mp = vp->v_mount;
299 int error = 0; 295 int error = 0;
300 296
301 UFS_WAPBL_JUNLOCK_ASSERT(mp); 297 UFS_WAPBL_JUNLOCK_ASSERT(mp);
302 298
303 /* 299 /*
304 * Truncate might temporarily fail, loop until done. 300 * Truncate might temporarily fail, loop until done.
305 */ 301 */
306 do { 302 do {
307 error = UFS_WAPBL_BEGIN(mp); 303 error = UFS_WAPBL_BEGIN(mp);
308 if (error) 304 if (error)
309 goto out; 305 goto out;
310 306
311 error = UFS_TRUNCATE(vp, newsize, 0, cred); 307 error = UFS_TRUNCATE(vp, newsize, ioflag, cred);
312 UFS_WAPBL_END(mp); 308 UFS_WAPBL_END(mp);
313 309
314 if (error != 0 && error != EAGAIN) 310 if (error != 0 && error != EAGAIN)
315 goto out; 311 goto out;
316 } while (ip->i_size != newsize); 312 } while (ip->i_size != newsize);
317 313
318 out: 314 out:
319 return error; 315 return error;
320} 316}
 317
 318/* truncate all the data of the inode including extended attributes */
 319int
 320ufs_truncate_all(struct vnode *vp)
 321{
 322 struct inode *ip = VTOI(vp);
 323 off_t isize = ip->i_size;
 324
 325 if (ip->i_ump->um_fstype == UFS2)
 326 isize += ip->i_ffs2_extsize;
 327
 328 if (isize == 0)
 329 return 0;
 330 return ufs_truncate_retry(vp, IO_EXT, 0, NOCRED);
 331}

cvs diff -r1.251 -r1.252 src/sys/ufs/ufs/ufs_vnops.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_vnops.c 2020/04/13 19:23:20 1.251
+++ src/sys/ufs/ufs/ufs_vnops.c 2020/04/18 19:18:34 1.252
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_vnops.c,v 1.251 2020/04/13 19:23:20 ad Exp $ */ 1/* $NetBSD: ufs_vnops.c,v 1.252 2020/04/18 19:18:34 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc. 8 * by Wasabi Systems, Inc.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -56,27 +56,27 @@ @@ -56,27 +56,27 @@
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95 65 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95
66 */ 66 */
67 67
68#include <sys/cdefs.h> 68#include <sys/cdefs.h>
69__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.251 2020/04/13 19:23:20 ad Exp $"); 69__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.252 2020/04/18 19:18:34 christos Exp $");
70 70
71#if defined(_KERNEL_OPT) 71#if defined(_KERNEL_OPT)
72#include "opt_ffs.h" 72#include "opt_ffs.h"
73#include "opt_quota.h" 73#include "opt_quota.h"
74#endif 74#endif
75 75
76#include <sys/param.h> 76#include <sys/param.h>
77#include <sys/systm.h> 77#include <sys/systm.h>
78#include <sys/namei.h> 78#include <sys/namei.h>
79#include <sys/resourcevar.h> 79#include <sys/resourcevar.h>
80#include <sys/kernel.h> 80#include <sys/kernel.h>
81#include <sys/file.h> 81#include <sys/file.h>
82#include <sys/stat.h> 82#include <sys/stat.h>
@@ -546,27 +546,27 @@ ufs_setattr(void *v) @@ -546,27 +546,27 @@ ufs_setattr(void *v)
546 case VCHR: 546 case VCHR:
547 case VBLK: 547 case VBLK:
548 case VFIFO: 548 case VFIFO:
549 break; 549 break;
550 case VREG: 550 case VREG:
551 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 551 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
552 error = EROFS; 552 error = EROFS;
553 goto out; 553 goto out;
554 } 554 }
555 if ((ip->i_flags & SF_SNAPSHOT) != 0) { 555 if ((ip->i_flags & SF_SNAPSHOT) != 0) {
556 error = EPERM; 556 error = EPERM;
557 goto out; 557 goto out;
558 } 558 }
559 error = ufs_truncate_retry(vp, vap->va_size, cred); 559 error = ufs_truncate_retry(vp, 0, vap->va_size, cred);
560 if (error) 560 if (error)
561 goto out; 561 goto out;
562 break; 562 break;
563 default: 563 default:
564 error = EOPNOTSUPP; 564 error = EOPNOTSUPP;
565 goto out; 565 goto out;
566 } 566 }
567 } 567 }
568 ip = VTOI(vp); 568 ip = VTOI(vp);
569 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || 569 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
570 vap->va_birthtime.tv_sec != VNOVAL) { 570 vap->va_birthtime.tv_sec != VNOVAL) {
571 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 571 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
572 error = EROFS; 572 error = EROFS;