Extended attribute support for ffsv2, from FreeBSD.diff -r1.13 -r1.14 src/sys/modules/ffs/Makefile
(christos)
--- 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 | |||
7 | KMOD= ffs | 7 | KMOD= ffs | |
8 | CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2 | 8 | CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI -DWAPBL -DAPPLE_UFS -DQUOTA -DQUOTA2 | |
9 | CPPFLAGS+= -DUFS_EXTATTR | 9 | CPPFLAGS+= -DUFS_EXTATTR | |
10 | 10 | |||
11 | CWARNFLAGS.clang= -Wno-conversion | 11 | CWARNFLAGS.clang= -Wno-conversion | |
12 | 12 | |||
13 | SRCS+= ffs_alloc.c ffs_balloc.c ffs_inode.c ffs_subr.c ffs_tables.c \ | 13 | SRCS+= 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 | |||
17 | WARNS= 3 | 17 | WARNS= 3 | |
18 | 18 | |||
19 | .include <bsd.kmodule.mk> | 19 | .include <bsd.kmodule.mk> |
--- 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 | |||
6 | LIB= rumpfs_ffs | 6 | LIB= rumpfs_ffs | |
7 | COMMENT=Berkeley Fast File System | 7 | COMMENT=Berkeley Fast File System | |
8 | 8 | |||
9 | SRCS= ffs_alloc.c ffs_appleufs.c ffs_balloc.c ffs_bswap.c ffs_inode.c \ | 9 | SRCS= 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 | |||
13 | SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ | 13 | SRCS+= 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 | |||
17 | CPPFLAGS+= -DFFS_EI -DUFS_DIRHASH -DWAPBL -DAPPLE_UFS -DUFS_EXTATTR \ | 17 | CPPFLAGS+= -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> |
--- 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 | |||
3 | deffs FFS | 3 | deffs FFS | |
4 | deffs EXT2FS | 4 | deffs EXT2FS | |
5 | deffs MFS | 5 | deffs MFS | |
6 | deffs LFS | 6 | deffs LFS | |
7 | deffs CHFS | 7 | deffs CHFS | |
8 | 8 | |||
9 | defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS | 9 | defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS | |
10 | UFS_DIRHASH UFS_EXTATTR | 10 | UFS_DIRHASH UFS_EXTATTR | |
11 | 11 | |||
12 | defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW | 12 | defflag 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 | |||
42 | file ufs/chfs/chfs_gc.c chfs | 42 | file ufs/chfs/chfs_gc.c chfs | |
43 | file ufs/chfs/chfs_nodeops.c chfs | 43 | file ufs/chfs/chfs_nodeops.c chfs | |
44 | file ufs/chfs/chfs_malloc.c chfs | 44 | file ufs/chfs/chfs_malloc.c chfs | |
45 | file ufs/chfs/chfs_pool.c chfs | 45 | file ufs/chfs/chfs_pool.c chfs | |
46 | file ufs/chfs/chfs_vnode.c chfs | 46 | file ufs/chfs/chfs_vnode.c chfs | |
47 | file ufs/chfs/chfs_subr.c chfs | 47 | file ufs/chfs/chfs_subr.c chfs | |
48 | file ufs/chfs/chfs_vfsops.c chfs | 48 | file ufs/chfs/chfs_vfsops.c chfs | |
49 | file ufs/chfs/chfs_readinode.c chfs | 49 | file ufs/chfs/chfs_readinode.c chfs | |
50 | 50 | |||
51 | define ffs: vfs, ufs | 51 | define ffs: vfs, ufs | |
52 | file ufs/ffs/ffs_alloc.c ffs | 52 | file ufs/ffs/ffs_alloc.c ffs | |
53 | file ufs/ffs/ffs_balloc.c ffs | 53 | file ufs/ffs/ffs_balloc.c ffs | |
54 | file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei | 54 | file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei | |
55 | file ufs/ffs/ffs_extattr.c ffs & ufs_extattr | |||
55 | file ufs/ffs/ffs_inode.c ffs | 56 | file ufs/ffs/ffs_inode.c ffs | |
56 | file ufs/ffs/ffs_snapshot.c ffs | 57 | file ufs/ffs/ffs_snapshot.c ffs | |
57 | file ufs/ffs/ffs_subr.c ffs | 58 | file ufs/ffs/ffs_subr.c ffs | |
58 | file ufs/ffs/ffs_tables.c ffs | 59 | file ufs/ffs/ffs_tables.c ffs | |
59 | file ufs/ffs/ffs_vfsops.c ffs | 60 | file ufs/ffs/ffs_vfsops.c ffs | |
60 | file ufs/ffs/ffs_vnops.c ffs | 61 | file ufs/ffs/ffs_vnops.c ffs | |
61 | file ufs/ffs/ffs_wapbl.c ffs & wapbl | 62 | file ufs/ffs/ffs_wapbl.c ffs & wapbl | |
62 | file ufs/ffs/ffs_appleufs.c ffs & apple_ufs | 63 | file ufs/ffs/ffs_appleufs.c ffs & apple_ufs | |
63 | file ufs/ffs/ffs_quota2.c quota2 & (ffs | mfs | ext2fs | chfs) | 64 | file ufs/ffs/ffs_quota2.c quota2 & (ffs | mfs | ext2fs | chfs) | |
64 | 65 | |||
65 | define lfs: vfs | 66 | define lfs: vfs | |
66 | file ufs/lfs/lfs_alloc.c lfs | 67 | file ufs/lfs/lfs_alloc.c lfs | |
67 | file ufs/lfs/lfs_balloc.c lfs | 68 | file ufs/lfs/lfs_balloc.c lfs |
--- 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 | */ | |
302 | int | 305 | int | |
303 | ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize, | 306 | ffs_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 | } |
--- 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 | |||
70 | static int ffs_balloc_ufs1(struct vnode *, off_t, int, kauth_cred_t, int, | 70 | static int ffs_balloc_ufs1(struct vnode *, off_t, int, kauth_cred_t, int, | |
71 | struct buf **); | 71 | struct buf **); | |
72 | static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int, | 72 | static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int, | |
73 | struct buf **); | 73 | struct buf **); | |
74 | 74 | |||
75 | static daddr_t | |||
76 | ffs_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 | |||
81 | int | 87 | int | |
82 | ffs_balloc(struct vnode *vp, off_t off, int size, kauth_cred_t cred, int flags, | 88 | ffs_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 |
/* $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;
}
--- 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 */ | |
90 | int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t, | 90 | int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t, | |
91 | daddr_t *); | 91 | daddr_t *); | |
92 | int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int , | 92 | int 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 *); | |
94 | int ffs_valloc(struct vnode *, int, kauth_cred_t, ino_t *); | 94 | int ffs_valloc(struct vnode *, int, kauth_cred_t, ino_t *); | |
95 | daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *); | 95 | daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *); | |
96 | daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *); | 96 | daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *); | |
97 | int ffs_blkalloc(struct inode *, daddr_t, long); | 97 | int ffs_blkalloc(struct inode *, daddr_t, long); | |
98 | int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long); | 98 | int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long); | |
99 | void ffs_blkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); | 99 | void ffs_blkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); | |
100 | void *ffs_discard_init(struct vnode *, struct fs *); | 100 | void *ffs_discard_init(struct vnode *, struct fs *); | |
101 | void ffs_discard_finish(void *, int); | 101 | void ffs_discard_finish(void *, int); | |
102 | void ffs_blkfree_snap(struct fs *, struct vnode *, daddr_t, long, ino_t); | 102 | void ffs_blkfree_snap(struct fs *, struct vnode *, daddr_t, long, ino_t); | |
103 | int ffs_vfree(struct vnode *, ino_t, int); | 103 | int ffs_vfree(struct vnode *, ino_t, int); | |
104 | int ffs_checkfreefile(struct fs *, struct vnode *, ino_t); | 104 | int ffs_checkfreefile(struct fs *, struct vnode *, ino_t); | |
105 | int ffs_freefile(struct mount *, ino_t, int); | 105 | int ffs_freefile(struct mount *, ino_t, int); | |
106 | int ffs_freefile_snap(struct fs *, struct vnode *, ino_t, int); | 106 | int 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 */ | |
127 | int ffs_read(void *); | 127 | int ffs_read(void *); | |
128 | int ffs_write(void *); | 128 | int ffs_write(void *); | |
129 | int ffs_bufio(enum uio_rw, struct vnode *, void *, size_t, off_t, int, | 129 | int 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 *); | |
131 | int ffs_bufrd(struct vnode *, struct uio *, int, kauth_cred_t); | 131 | int ffs_bufrd(struct vnode *, struct uio *, int, kauth_cred_t); | |
132 | int ffs_bufwr(struct vnode *, struct uio *, int, kauth_cred_t); | 132 | int ffs_bufwr(struct vnode *, struct uio *, int, kauth_cred_t); | |
133 | int ffs_fsync(void *); | 133 | int ffs_fsync(void *); | |
134 | int ffs_spec_fsync(void *); | 134 | int ffs_spec_fsync(void *); | |
135 | int ffs_reclaim(void *); | 135 | int ffs_reclaim(void *); | |
136 | int ffs_getpages(void *); | 136 | int ffs_getpages(void *); | |
137 | void ffs_gop_size(struct vnode *, off_t, off_t *, int); | 137 | void ffs_gop_size(struct vnode *, off_t, off_t *, int); | |
138 | int ffs_lock(void *); | |||
139 | int ffs_unlock(void *); | |||
140 | int ffs_islocked(void *); | |||
141 | int ffs_full_fsync(struct vnode *, int); | |||
142 | ||||
143 | /* ffs_extattr.c */ | |||
144 | #ifdef UFS_EXTATTR | |||
138 | int ffs_openextattr(void *); | 145 | int ffs_openextattr(void *); | |
139 | int ffs_closeextattr(void *); | 146 | int ffs_closeextattr(void *); | |
140 | int ffs_getextattr(void *); | 147 | int ffs_getextattr(void *); | |
141 | int ffs_setextattr(void *); | 148 | int ffs_setextattr(void *); | |
142 | int ffs_listextattr(void *); | 149 | int ffs_listextattr(void *); | |
143 | int ffs_deleteextattr(void *); | 150 | int ffs_deleteextattr(void *); | |
144 | int ffs_lock(void *); | 151 | int ffsext_strategy(void *); | |
145 | int ffs_unlock(void *); | 152 | #else | |
146 | int ffs_islocked(void *); | 153 | #define ffs_openextattr genfs_eopnotsupp | |
147 | int 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 | */ | |
152 | int ffs_snapshot_init(struct ufsmount *); | 165 | int ffs_snapshot_init(struct ufsmount *); | |
153 | void ffs_snapshot_fini(struct ufsmount *); | 166 | void ffs_snapshot_fini(struct ufsmount *); | |
154 | int ffs_snapblkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); | 167 | int ffs_snapblkfree(struct fs *, struct vnode *, daddr_t, long, ino_t); | |
155 | void ffs_snapremove(struct vnode *); | 168 | void ffs_snapremove(struct vnode *); | |
156 | int ffs_snapshot(struct mount *, struct vnode *, struct timespec *); | 169 | int ffs_snapshot(struct mount *, struct vnode *, struct timespec *); | |
157 | void ffs_snapshot_mount(struct mount *); | 170 | void ffs_snapshot_mount(struct mount *); | |
158 | void ffs_snapshot_unmount(struct mount *); | 171 | void ffs_snapshot_unmount(struct mount *); | |
159 | void ffs_snapgone(struct vnode *); | 172 | void ffs_snapgone(struct vnode *); | |
160 | int ffs_snapshot_read(struct vnode *, struct uio *, int); | 173 | int ffs_snapshot_read(struct vnode *, struct uio *, int); |
--- 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 | */ | |
206 | int | 206 | int | |
207 | ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred) | 207 | ffs_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 | |||
529 | done: | 555 | done: | |
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 | |||
544 | out: | 570 | out: | |
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 | } |
--- 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); |
--- 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 | ||||
616 | int | |||
617 | ffs_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 | ||||
635 | int | |||
636 | ffs_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 | ||||
655 | int | |||
656 | ffs_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 | ||||
686 | int | |||
687 | ffs_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 | ||||
716 | int | |||
717 | ffs_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 | ||||
745 | int | |||
746 | ffs_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 | } |
--- 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 | */ |
--- 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 @@ | |||
62 | struct ufs_extattr_fileheader { | 62 | struct 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 | |||
68 | struct ufs_extattr_header { | 68 | struct 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 | */ | |||
78 | struct 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 | |
78 | MALLOC_DECLARE(M_EXTATTR); | 111 | MALLOC_DECLARE(M_EXTATTR); | |
79 | #endif | 112 | #endif | |
80 | 113 | |||
81 | struct vnode; | 114 | struct vnode; | |
82 | LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry); | 115 | LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry); | |
83 | struct ufs_extattr_list_entry { | 116 | struct 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]; |
--- 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 { \ |
--- 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 *); | |||
101 | int ufsfifo_write(void *); | 101 | int ufsfifo_write(void *); | |
102 | int ufsfifo_close(void *); | 102 | int ufsfifo_close(void *); | |
103 | 103 | |||
104 | /* ufs_bmap.c */ | 104 | /* ufs_bmap.c */ | |
105 | typedef bool (*ufs_issequential_callback_t)(const struct ufsmount *, | 105 | typedef bool (*ufs_issequential_callback_t)(const struct ufsmount *, | |
106 | daddr_t, daddr_t); | 106 | daddr_t, daddr_t); | |
107 | int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *, | 107 | int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *, | |
108 | int *, int *, ufs_issequential_callback_t); | 108 | int *, int *, ufs_issequential_callback_t); | |
109 | int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *); | 109 | int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *); | |
110 | 110 | |||
111 | /* ufs_inode.c */ | 111 | /* ufs_inode.c */ | |
112 | int ufs_reclaim(struct vnode *); | 112 | int ufs_reclaim(struct vnode *); | |
113 | int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int); | 113 | int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int); | |
114 | int ufs_truncate_retry(struct vnode *, uint64_t, kauth_cred_t); | 114 | int ufs_truncate_all(struct vnode *); | |
115 | int ufs_truncate_retry(struct vnode *, int, uint64_t, kauth_cred_t); | |||
115 | 116 | |||
116 | /* ufs_lookup.c */ | 117 | /* ufs_lookup.c */ | |
117 | void ufs_dirbad(struct inode *, doff_t, const char *); | 118 | void ufs_dirbad(struct inode *, doff_t, const char *); | |
118 | const char *ufs_dirbadentry(const struct vnode *, const struct direct *, int); | 119 | const char *ufs_dirbadentry(const struct vnode *, const struct direct *, int); | |
119 | void ufs_makedirentry(struct inode *, struct componentname *, | 120 | void ufs_makedirentry(struct inode *, struct componentname *, | |
120 | struct direct *); | 121 | struct direct *); | |
121 | int ufs_direnter(struct vnode *, const struct ufs_lookup_results *, | 122 | int 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 *); | |
124 | int ufs_dirremove(struct vnode *, const struct ufs_lookup_results *, | 125 | int ufs_dirremove(struct vnode *, const struct ufs_lookup_results *, | |
125 | struct inode *, int, int); | 126 | struct inode *, int, int); | |
126 | int ufs_dirrewrite(struct inode *, off_t, | 127 | int ufs_dirrewrite(struct inode *, off_t, | |
127 | struct inode *, ino_t, int, int, int); | 128 | struct inode *, ino_t, int, int, int); |
--- 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 | |||
294 | int | 289 | int | |
295 | ufs_truncate_retry(struct vnode *vp, uint64_t newsize, kauth_cred_t cred) | 290 | ufs_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 */ | |||
319 | int | |||
320 | ufs_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 | } |
--- 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; |