Sat Apr 18 19:18:34 2020 UTC ()
Extended attribute support for ffsv2, from FreeBSD.
(christos)
diff -r1.13 -r1.14 src/sys/modules/ffs/Makefile
diff -r1.17 -r1.18 src/sys/rump/fs/lib/libffs/Makefile
diff -r1.46 -r1.47 src/sys/ufs/files.ufs
diff -r1.166 -r1.167 src/sys/ufs/ffs/ffs_alloc.c
diff -r1.63 -r1.64 src/sys/ufs/ffs/ffs_balloc.c
diff -r0 -r1.1 src/sys/ufs/ffs/ffs_extattr.c
diff -r1.85 -r1.86 src/sys/ufs/ffs/ffs_extern.h
diff -r1.126 -r1.127 src/sys/ufs/ffs/ffs_inode.c
diff -r1.151 -r1.152 src/sys/ufs/ffs/ffs_snapshot.c
diff -r1.130 -r1.131 src/sys/ufs/ffs/ffs_vnops.c
diff -r1.66 -r1.67 src/sys/ufs/ffs/fs.h
diff -r1.11 -r1.12 src/sys/ufs/ufs/extattr.h
diff -r1.76 -r1.77 src/sys/ufs/ufs/inode.h
diff -r1.84 -r1.85 src/sys/ufs/ufs/ufs_extern.h
diff -r1.109 -r1.110 src/sys/ufs/ufs/ufs_inode.c
diff -r1.251 -r1.252 src/sys/ufs/ufs/ufs_vnops.c
--- 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,4 +1,4 @@
-# $NetBSD: Makefile,v 1.13 2019/08/19 09:31:30 christos Exp $
+# $NetBSD: Makefile,v 1.14 2020/04/18 19:18:33 christos Exp $
.include "../Makefile.inc"
@@ -11,7 +11,7 @@
CWARNFLAGS.clang= -Wno-conversion
SRCS+= ffs_alloc.c ffs_balloc.c ffs_inode.c ffs_subr.c ffs_tables.c \
- ffs_vfsops.c ffs_vnops.c ffs_snapshot.c \
+ ffs_vfsops.c ffs_vnops.c ffs_snapshot.c ffs_extattr.c \
ffs_bswap.c ffs_wapbl.c ffs_appleufs.c ffs_quota2.c
WARNS= 3
--- 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,4 +1,4 @@
-# $NetBSD: Makefile,v 1.17 2020/04/12 00:04:45 christos Exp $
+# $NetBSD: Makefile,v 1.18 2020/04/18 19:18:33 christos Exp $
#
.PATH: ${.CURDIR}/../../../../ufs/ffs ${.CURDIR}/../../../../ufs/ufs
@@ -8,7 +8,7 @@
SRCS= ffs_alloc.c ffs_appleufs.c ffs_balloc.c ffs_bswap.c ffs_inode.c \
ffs_snapshot.c ffs_subr.c ffs_tables.c ffs_vfsops.c ffs_vnops.c \
- ffs_wapbl.c ffs_quota2.c
+ ffs_wapbl.c ffs_quota2.c ffs_extattr.c
SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \
ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c \
--- 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,4 +1,4 @@
-# $NetBSD: files.ufs,v 1.46 2020/04/11 17:43:54 jdolecek Exp $
+# $NetBSD: files.ufs,v 1.47 2020/04/18 19:18:33 christos Exp $
deffs FFS
deffs EXT2FS
@@ -52,6 +52,7 @@
file ufs/ffs/ffs_alloc.c ffs
file ufs/ffs/ffs_balloc.c ffs
file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei
+file ufs/ffs/ffs_extattr.c ffs & ufs_extattr
file ufs/ffs/ffs_inode.c ffs
file ufs/ffs/ffs_snapshot.c ffs
file ufs/ffs/ffs_subr.c ffs
--- 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,4 +1,4 @@
-/* $NetBSD: ffs_alloc.c,v 1.166 2020/02/23 15:46:42 ad Exp $ */
+/* $NetBSD: ffs_alloc.c,v 1.167 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.166 2020/02/23 15:46:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.167 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -257,7 +257,10 @@
bno = ffs_hashalloc(ip, cg, bpref, size, 0, flags, ffs_alloccg);
if (bno > 0) {
DIP_ADD(ip, blocks, btodb(size));
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (flags & IO_EXT)
+ ip->i_flag |= IN_CHANGE;
+ else
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bnp = bno;
return (0);
}
@@ -300,14 +303,15 @@
* => return with um_lock released
*/
int
-ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize,
- int nsize, kauth_cred_t cred, struct buf **bpp, daddr_t *blknop)
+ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bprev, daddr_t bpref,
+ int osize, int nsize, int flags, kauth_cred_t cred, struct buf **bpp,
+ daddr_t *blknop)
{
struct ufsmount *ump;
struct fs *fs;
struct buf *bp;
int cg, request, error;
- daddr_t bprev, bno;
+ daddr_t bno;
fs = ip->i_fs;
ump = ip->i_ump;
@@ -368,10 +372,6 @@
mutex_exit(&ump->um_lock);
goto nospace;
}
- if (fs->fs_magic == FS_UFS2_MAGIC)
- bprev = ufs_rw64(ip->i_ffs2_db[lbprev], UFS_FSNEEDSWAP(fs));
- else
- bprev = ufs_rw32(ip->i_ffs1_db[lbprev], UFS_FSNEEDSWAP(fs));
if (bprev == 0) {
panic("%s: bad bprev: dev = 0x%llx, bsize = %d, bprev = %"
@@ -403,7 +403,10 @@
mutex_enter(&ump->um_lock);
if ((bno = ffs_fragextend(ip, cg, bprev, osize, nsize)) != 0) {
DIP_ADD(ip, blocks, btodb(nsize - osize));
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (flags & IO_EXT)
+ ip->i_flag |= IN_CHANGE;
+ else
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (bpp != NULL) {
if (bp->b_blkno != FFS_FSBTODB(fs, bno)) {
@@ -503,7 +506,10 @@
ip->i_number);
}
DIP_ADD(ip, blocks, btodb(nsize - osize));
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ if (flags & IO_EXT)
+ ip->i_flag |= IN_CHANGE;
+ else
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (bpp != NULL) {
bp->b_blkno = FFS_FSBTODB(fs, bno);
allocbuf(bp, nsize, 1);
--- 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,4 +1,4 @@
-/* $NetBSD: ffs_balloc.c,v 1.63 2017/10/28 00:37:13 pgoyette Exp $ */
+/* $NetBSD: ffs_balloc.c,v 1.64 2020/04/18 19:18:34 christos Exp $ */
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.63 2017/10/28 00:37:13 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.64 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -72,6 +72,12 @@
static int ffs_balloc_ufs2(struct vnode *, off_t, int, kauth_cred_t, int,
struct buf **);
+static daddr_t
+ffs_extb(struct fs *fs, struct ufs2_dinode *dp, daddr_t nb)
+{
+ return ufs_rw64(dp->di_extb[nb], UFS_FSNEEDSWAP(fs));
+}
+
/*
* Balloc defines the structure of file system storage
* by allocating the physical blocks on a device given
@@ -139,10 +145,11 @@
osize = ffs_blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
mutex_enter(&ump->um_lock);
- error = ffs_realloccg(ip, nb,
+ error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, nb),
ffs_blkpref_ufs1(ip, lastlbn, nb, flags,
&ip->i_ffs1_db[0]),
- osize, (int)fs->fs_bsize, cred, bpp, &newb);
+ osize, (int)fs->fs_bsize, flags, cred, bpp,
+ &newb);
if (error)
return (error);
ip->i_size = ffs_lblktosize(fs, nb + 1);
@@ -215,9 +222,10 @@
*/
mutex_enter(&ump->um_lock);
error = ffs_realloccg(ip, lbn,
+ ffs_getdb(fs, ip, lbn),
ffs_blkpref_ufs1(ip, lbn, (int)lbn, flags,
&ip->i_ffs1_db[0]),
- osize, nsize, cred, bpp, &newb);
+ osize, nsize, flags, cred, bpp, &newb);
if (error)
return (error);
}
@@ -543,11 +551,11 @@
if (lbn < 0)
return (EFBIG);
-#ifdef notyet
/*
* Check for allocating external data.
*/
if (flags & IO_EXT) {
+ struct ufs2_dinode *dp = ip->i_din.ffs2_din;
if (lbn >= UFS_NXADDR)
return (EFBIG);
/*
@@ -562,16 +570,15 @@
if (osize < fs->fs_bsize && osize > 0) {
mutex_enter(&ump->um_lock);
error = ffs_realloccg(ip, -1 - nb,
- dp->di_extb[nb],
+ ffs_extb(fs, dp, nb),
ffs_blkpref_ufs2(ip, lastlbn, (int)nb,
flags, &dp->di_extb[0]),
- osize,
- (int)fs->fs_bsize, cred, &bp);
+ osize, (int)fs->fs_bsize, flags, cred,
+ &bp, &newb);
if (error)
return (error);
- dp->di_extsize = smalllblktosize(fs, nb + 1);
+ dp->di_extsize = ffs_lblktosize(fs, nb + 1);
dp->di_extb[nb] = FFS_DBTOFSB(fs, bp->b_blkno);
- bp->b_xflags |= BX_ALTDATA;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (flags & IO_SYNC)
bwrite(bp);
@@ -582,19 +589,16 @@
/*
* All blocks are direct blocks
*/
- if (flags & BA_METAONLY)
- panic("ffs_balloc_ufs2: BA_METAONLY for ext block");
nb = dp->di_extb[lbn];
- if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
+ if (nb != 0 && dp->di_extsize >= ffs_lblktosize(fs, lbn + 1)) {
error = bread(vp, -1 - lbn, fs->fs_bsize,
0, &bp);
if (error) {
return (error);
}
- mutex_enter(&bp->b_interlock);
+ mutex_enter(bp->b_objlock);
bp->b_blkno = FFS_FSBTODB(fs, nb);
- bp->b_xflags |= BX_ALTDATA;
- mutex_exit(&bp->b_interlock);
+ mutex_exit(bp->b_objlock);
*bpp = bp;
return (0);
}
@@ -610,23 +614,21 @@
if (error) {
return (error);
}
- mutex_enter(&bp->b_interlock);
+ mutex_enter(bp->b_objlock);
bp->b_blkno = FFS_FSBTODB(fs, nb);
- bp->b_xflags |= BX_ALTDATA;
- mutex_exit(&bp->b_interlock);
+ mutex_exit(bp->b_objlock);
} else {
mutex_enter(&ump->um_lock);
error = ffs_realloccg(ip, -1 - lbn,
- dp->di_extb[lbn],
+ ffs_extb(fs, dp, lbn),
ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags,
&dp->di_extb[0]),
- osize, nsize, cred, &bp);
+ osize, nsize, flags, cred, &bp, &newb);
if (error)
return (error);
- bp->b_xflags |= BX_ALTDATA;
}
} else {
- if (dp->di_extsize < smalllblktosize(fs, lbn + 1))
+ if (dp->di_extsize < ffs_lblktosize(fs, lbn + 1))
nsize = ffs_fragroundup(fs, size);
else
nsize = fs->fs_bsize;
@@ -641,14 +643,12 @@
nsize, (flags & B_CLRBUF) != 0, &bp);
if (error)
return error;
- bp->b_xflags |= BX_ALTDATA;
}
dp->di_extb[lbn] = FFS_DBTOFSB(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bpp = bp;
return (0);
}
-#endif
/*
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
@@ -661,10 +661,11 @@
osize = ffs_blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
mutex_enter(&ump->um_lock);
- error = ffs_realloccg(ip, nb,
+ error = ffs_realloccg(ip, nb, ffs_getdb(fs, ip, lbn),
ffs_blkpref_ufs2(ip, lastlbn, nb, flags,
&ip->i_ffs2_db[0]),
- osize, (int)fs->fs_bsize, cred, bpp, &newb);
+ osize, (int)fs->fs_bsize, flags, cred, bpp,
+ &newb);
if (error)
return (error);
ip->i_size = ffs_lblktosize(fs, nb + 1);
@@ -737,9 +738,10 @@
*/
mutex_enter(&ump->um_lock);
error = ffs_realloccg(ip, lbn,
+ ffs_getdb(fs, ip, lbn),
ffs_blkpref_ufs2(ip, lbn, (int)lbn, flags,
&ip->i_ffs2_db[0]),
- osize, nsize, cred, bpp, &newb);
+ osize, nsize, flags, cred, bpp, &newb);
if (error)
return (error);
}
/* $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,4 +1,4 @@
-/* $NetBSD: ffs_extern.h,v 1.85 2018/08/22 01:05:24 msaitoh Exp $ */
+/* $NetBSD: ffs_extern.h,v 1.86 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -89,8 +89,8 @@
/* ffs_alloc.c */
int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t,
daddr_t *);
-int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int ,
- kauth_cred_t, struct buf **, daddr_t *);
+int ffs_realloccg(struct inode *, daddr_t, daddr_t, daddr_t, int, int,
+ int, kauth_cred_t, struct buf **, daddr_t *);
int ffs_valloc(struct vnode *, int, kauth_cred_t, ino_t *);
daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *);
daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *);
@@ -135,16 +135,29 @@
int ffs_reclaim(void *);
int ffs_getpages(void *);
void ffs_gop_size(struct vnode *, off_t, off_t *, int);
+int ffs_lock(void *);
+int ffs_unlock(void *);
+int ffs_islocked(void *);
+int ffs_full_fsync(struct vnode *, int);
+
+/* ffs_extattr.c */
+#ifdef UFS_EXTATTR
int ffs_openextattr(void *);
int ffs_closeextattr(void *);
int ffs_getextattr(void *);
int ffs_setextattr(void *);
int ffs_listextattr(void *);
int ffs_deleteextattr(void *);
-int ffs_lock(void *);
-int ffs_unlock(void *);
-int ffs_islocked(void *);
-int ffs_full_fsync(struct vnode *, int);
+int ffsext_strategy(void *);
+#else
+#define ffs_openextattr genfs_eopnotsupp
+#define ffs_closeextattr genfs_eopnotsupp
+#define ffs_getextattr genfs_eopnotsupp
+#define ffs_setextattr genfs_eopnotsupp
+#define ffs_listextattr genfs_eopnotsupp
+#define ffs_deleteextattr genfs_eopnotsupp
+#define ffsext_strategy vn_fifo_bypass
+#endif
/*
* Snapshot function prototypes.
--- 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,4 +1,4 @@
-/* $NetBSD: ffs_inode.c,v 1.126 2020/02/23 15:46:42 ad Exp $ */
+/* $NetBSD: ffs_inode.c,v 1.127 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.126 2020/02/23 15:46:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.127 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -209,10 +209,11 @@
daddr_t lastblock;
struct inode *oip = VTOI(ovp);
daddr_t bn, lastiblock[UFS_NIADDR], indir_lbn[UFS_NIADDR];
- daddr_t blks[UFS_NDADDR + UFS_NIADDR];
+ daddr_t blks[UFS_NDADDR + UFS_NIADDR], oldblks[UFS_NDADDR + UFS_NIADDR];
struct fs *fs;
+ int extblocks;
int offset, pgoffset, level;
- int64_t blocksreleased = 0;
+ int64_t blocksreleased = 0, datablocks;
int i, aflag, nblocks;
int error, allerror = 0;
off_t osize;
@@ -231,9 +232,44 @@
if (length < 0)
return (EINVAL);
+ fs = oip->i_fs;
+#define i_din2 i_din.ffs2_din
+ extblocks = 0;
+ datablocks = DIP(oip, blocks);
+ if (fs->fs_magic == FS_UFS2_MAGIC && oip->i_din2->di_extsize > 0) {
+ extblocks = btodb(ffs_fragroundup(fs, oip->i_din2->di_extsize));
+ datablocks -= extblocks;
+ }
+ if ((ioflag & IO_EXT) && extblocks > 0) {
+ if (length != 0)
+ panic("ffs_truncate: partial trunc of extdata");
+ {
+#ifdef QUOTA
+ (void) chkdq(oip, -extblocks, NOCRED, FORCE);
+#endif
+ vinvalbuf(ovp, 0, cred, curlwp, 0, 0);
+ osize = oip->i_din2->di_extsize;
+ oip->i_din2->di_blocks -= extblocks;
+ oip->i_din2->di_extsize = 0;
+ for (i = 0; i < UFS_NXADDR; i++) {
+ oldblks[i] = oip->i_din2->di_extb[i];
+ oip->i_din2->di_extb[i] = 0;
+ }
+ oip->i_flag |= IN_CHANGE;
+ if ((error = ffs_update(ovp, NULL, NULL, 0)))
+ return (error);
+ for (i = 0; i < UFS_NXADDR; i++) {
+ if (oldblks[i] == 0)
+ continue;
+ ffs_blkfree(fs, oip->i_devvp, oldblks[i],
+ ffs_sblksize(fs, osize, i), oip->i_number);
+ }
+ extblocks = 0;
+ }
+ }
if (ovp->v_type == VLNK &&
(oip->i_size < ump->um_maxsymlinklen ||
- (ump->um_maxsymlinklen == 0 && DIP(oip, blocks) == 0))) {
+ (ump->um_maxsymlinklen == 0 && datablocks == 0))) {
KDASSERT(length == 0);
memset(SHORTLINK(oip), 0, (size_t)oip->i_size);
oip->i_size = 0;
@@ -247,7 +283,6 @@
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ffs_update(ovp, NULL, NULL, 0));
}
- fs = oip->i_fs;
if (length > ump->um_maxfilesize)
return (EFBIG);
@@ -415,10 +450,7 @@
indir_lbn[DOUBLE] = indir_lbn[SINGLE] - FFS_NINDIR(fs) - 1;
indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - FFS_NINDIR(fs) * FFS_NINDIR(fs) - 1;
for (level = TRIPLE; level >= SINGLE; level--) {
- if (oip->i_ump->um_fstype == UFS1)
- bn = ufs_rw32(oip->i_ffs1_ib[level],UFS_FSNEEDSWAP(fs));
- else
- bn = ufs_rw64(oip->i_ffs2_ib[level],UFS_FSNEEDSWAP(fs));
+ bn = ffs_getib(fs, oip, level);
if (bn != 0) {
if (lastiblock[level] < 0 &&
oip->i_ump->um_mountp->mnt_wapbl) {
@@ -461,10 +493,7 @@
for (i = UFS_NDADDR - 1; i > lastblock; i--) {
long bsize;
- if (oip->i_ump->um_fstype == UFS1)
- bn = ufs_rw32(oip->i_ffs1_db[i], UFS_FSNEEDSWAP(fs));
- else
- bn = ufs_rw64(oip->i_ffs2_db[i], UFS_FSNEEDSWAP(fs));
+ bn = ffs_getdb(fs, oip, i);
if (bn == 0)
continue;
@@ -488,10 +517,7 @@
* Finally, look for a change in size of the
* last direct block; release any frags.
*/
- if (oip->i_ump->um_fstype == UFS1)
- bn = ufs_rw32(oip->i_ffs1_db[lastblock], UFS_FSNEEDSWAP(fs));
- else
- bn = ufs_rw64(oip->i_ffs2_db[lastblock], UFS_FSNEEDSWAP(fs));
+ bn = ffs_getdb(fs, oip, lastblock);
if (bn != 0) {
long oldspace, newspace;
@@ -536,9 +562,9 @@
KASSERTMSG((blks[i] == DIP(oip, db[i])),
"itrunc2 blk mismatch: %jx != %jx",
(uintmax_t)blks[i], (uintmax_t)DIP(oip, db[i]));
- KASSERTMSG((length != 0 || LIST_EMPTY(&ovp->v_cleanblkhd)),
+ KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_cleanblkhd)),
"itrunc3: zero length and nonempty cleanblkhd");
- KASSERTMSG((length != 0 || LIST_EMPTY(&ovp->v_dirtyblkhd)),
+ KASSERTMSG((length != 0 || extblocks || LIST_EMPTY(&ovp->v_dirtyblkhd)),
"itrunc3: zero length and nonempty dirtyblkhd");
out:
--- 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,4 +1,4 @@
-/* $NetBSD: ffs_snapshot.c,v 1.151 2020/02/23 15:46:42 ad Exp $ */
+/* $NetBSD: ffs_snapshot.c,v 1.152 2020/04/18 19:18:34 christos Exp $ */
/*
* Copyright 2000 Marshall Kirk McKusick. All Rights Reserved.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.151 2020/02/23 15:46:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.152 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -443,16 +443,14 @@
if (error)
return EACCES;
- if (vp->v_size != 0) {
- /*
- * Must completely truncate the file here. Allocated
- * blocks on a snapshot mean that block has been copied
- * on write, see ffs_copyonwrite() testing "blkno != 0"
- */
- error = ufs_truncate_retry(vp, 0, NOCRED);
- if (error)
- return error;
- }
+ /*
+ * Must completely truncate the file here. Allocated
+ * blocks on a snapshot mean that block has been copied
+ * on write, see ffs_copyonwrite() testing "blkno != 0"
+ */
+ error = ufs_truncate_all(vp);
+ if (error)
+ return error;
/* Change inode to snapshot type file. */
error = UFS_WAPBL_BEGIN(mp);
--- 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,4 +1,4 @@
-/* $NetBSD: ffs_vnops.c,v 1.130 2020/02/23 15:46:42 ad Exp $ */
+/* $NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.130 2020/02/23 15:46:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.131 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -611,161 +611,4 @@
} else {
*eobp = ffs_blkroundup(fs, size);
}
-}
-
-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);
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
-}
-
-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);
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
-}
-
-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;
-
- if (fs->fs_magic == FS_UFS1_MAGIC) {
-#ifdef UFS_EXTATTR
- int error;
-
- error = ufs_getextattr(ap);
- return error;
-#else
- return (EOPNOTSUPP);
-#endif
- }
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
-}
-
-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;
-
- if (fs->fs_magic == FS_UFS1_MAGIC) {
-#ifdef UFS_EXTATTR
- int error;
-
- error = ufs_setextattr(ap);
- return error;
-#else
- return (EOPNOTSUPP);
-#endif
- }
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
-}
-
-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) {
-#ifdef UFS_EXTATTR
- int error;
-
- error = ufs_listextattr(ap);
- return error;
-#else
- return (EOPNOTSUPP);
-#endif
- }
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
-}
-
-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) {
-#ifdef UFS_EXTATTR
- int error;
-
- error = ufs_deleteextattr(ap);
- return error;
-#else
- return (EOPNOTSUPP);
-#endif
- }
-
- /* XXX Not implemented for UFS2 file systems. */
- return (EOPNOTSUPP);
}
--- 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,4 +1,4 @@
-/* $NetBSD: fs.h,v 1.66 2015/02/14 09:06:11 maxv Exp $ */
+/* $NetBSD: fs.h,v 1.67 2020/04/18 19:18:34 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -692,6 +692,14 @@
((fsb) & ((fs)->fs_frag - 1))
#define ffs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
((fsb) &~ ((fs)->fs_frag - 1))
+#define ffs_getdb(fs, ip, lb) \
+ ((fs)->fs_magic == FS_UFS2_MAGIC ? \
+ (daddr_t)ufs_rw64((ip)->i_ffs2_db[lb], UFS_FSNEEDSWAP(fs)) : \
+ (daddr_t)ufs_rw32((ip)->i_ffs1_db[lb], UFS_FSNEEDSWAP(fs)))
+#define ffs_getib(fs, ip, lb) \
+ ((fs)->fs_magic == FS_UFS2_MAGIC ? \
+ (daddr_t)ufs_rw64((ip)->i_ffs2_ib[lb], UFS_FSNEEDSWAP(fs)) : \
+ (daddr_t)ufs_rw32((ip)->i_ffs1_ib[lb], UFS_FSNEEDSWAP(fs)))
/*
* Determine the number of available frags given a
--- 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,4 +1,4 @@
-/* $NetBSD: extattr.h,v 1.11 2014/12/19 10:59:21 manu Exp $ */
+/* $NetBSD: extattr.h,v 1.12 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 1999-2001 Robert N. M. Watson
@@ -71,6 +71,39 @@
uint32_t ueh_i_gen; /* generation number for sanity */
/* data follows the header */
};
+
+/*
+ * This structure defines the required fields of an extended-attribute header.
+ */
+struct extattr {
+ uint32_t ea_length; /* length of this attribute */
+ uint8_t ea_namespace; /* name space of this attribute */
+ uint8_t ea_contentpadlen; /* bytes of padding at end of attribute */
+ uint8_t ea_namelength; /* length of attribute name */
+ char ea_name[1]; /* attribute name (NOT nul-terminated) */
+ /* padding, if any, to align attribute content to 8 byte boundary */
+ /* extended attribute content follows */
+};
+
+/*
+ * These macros are used to access and manipulate an extended attribute:
+ *
+ * EXTATTR_NEXT(eap) returns a pointer to the next extended attribute
+ * following eap.
+ * EXTATTR_CONTENT(eap) returns a pointer to the extended attribute
+ * content referenced by eap.
+ * EXTATTR_CONTENT_SIZE(eap) returns the size of the extended attribute
+ * content referenced by eap.
+ */
+#define EXTATTR_NEXT(eap) \
+ ((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length))
+#define EXTATTR_CONTENT(eap) \
+ (void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap))
+#define EXTATTR_CONTENT_SIZE(eap) \
+ ((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
+/* -1 below compensates for ea_name[1] */
+#define EXTATTR_BASE_LENGTH(eap) \
+ roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8)
#ifdef _KERNEL
--- 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,4 +1,4 @@
-/* $NetBSD: inode.h,v 1.76 2017/08/20 12:09:06 maya Exp $ */
+/* $NetBSD: inode.h,v 1.77 2020/04/18 19:18:34 christos Exp $ */
/*
* Copyright (c) 1982, 1989, 1993
@@ -156,6 +156,14 @@
struct dirhash *i_dirhash; /* Hashing for large directories */
/*
+ * Data for extended attribute modification.
+ */
+ u_char *i_ea_area; /* Pointer to malloced copy of EA area */
+ unsigned i_ea_len; /* Length of i_ea_area */
+ int i_ea_error; /* First errno in transaction */
+ int i_ea_refs; /* Number of users of EA area */
+
+ /*
* The on-disk dinode itself.
*/
union {
@@ -216,16 +224,16 @@
#define IN_UPDATE 0x0004 /* Inode written to; update mtime. */
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
#define IN_ACCESSED 0x0010 /* Inode has been accessed. */
-/* unused 0x0020 */ /* was IN_RENAME */
+/* unused 0x0020 */ /* was IN_RENAME */
#define IN_SHLOCK 0x0040 /* File has shared lock. */
#define IN_EXLOCK 0x0080 /* File has exclusive lock. */
-/* unused 0x0100 */ /* was LFS-only IN_CLEANING */
-/* unused 0x0200 */ /* was LFS-only IN_ADIROP */
+/* unused 0x0100 */ /* was LFS-only IN_CLEANING */
+/* unused 0x0200 */ /* was LFS-only IN_ADIROP */
#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */
-/* unused 0x0800 */ /* what was that? */
-/* unused 0x1000 */ /* was LFS-only IN_PAGING */
+/* unused 0x0800 */ /* what was that? */
+/* unused 0x1000 */ /* was LFS-only IN_PAGING */
#define IN_MODIFY 0x2000 /* Modification time update request. */
-/* unused 0x4000 */ /* was LFS-only IN_CDIROP */
+/* unused 0x4000 */ /* was LFS-only IN_CDIROP */
#if defined(_KERNEL)
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_extern.h,v 1.84 2020/01/17 20:08:10 ad Exp $ */
+/* $NetBSD: ufs_extern.h,v 1.85 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -111,7 +111,8 @@
/* ufs_inode.c */
int ufs_reclaim(struct vnode *);
int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int);
-int ufs_truncate_retry(struct vnode *, uint64_t, kauth_cred_t);
+int ufs_truncate_all(struct vnode *);
+int ufs_truncate_retry(struct vnode *, int, uint64_t, kauth_cred_t);
/* ufs_lookup.c */
void ufs_dirbad(struct inode *, doff_t, const char *);
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_inode.c,v 1.109 2020/02/23 15:46:43 ad Exp $ */
+/* $NetBSD: ufs_inode.c,v 1.110 2020/04/18 19:18:34 christos Exp $ */
/*
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.109 2020/02/23 15:46:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.110 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -98,16 +98,11 @@
#ifdef UFS_EXTATTR
ufs_extattr_vnode_inactive(vp, curlwp);
#endif
-
/*
* All file blocks must be freed before we can let the vnode
* be reclaimed, so can't postpone full truncating any further.
*/
- if (ip->i_size != 0) {
- allerror = ufs_truncate_retry(vp, 0, NOCRED);
- if (allerror)
- goto out;
- }
+ ufs_truncate_all(vp);
#if defined(QUOTA) || defined(QUOTA2)
error = UFS_WAPBL_BEGIN(mp);
@@ -292,7 +287,8 @@
}
int
-ufs_truncate_retry(struct vnode *vp, uint64_t newsize, kauth_cred_t cred)
+ufs_truncate_retry(struct vnode *vp, int ioflag, uint64_t newsize,
+ kauth_cred_t cred)
{
struct inode *ip = VTOI(vp);
struct mount *mp = vp->v_mount;
@@ -308,7 +304,7 @@
if (error)
goto out;
- error = UFS_TRUNCATE(vp, newsize, 0, cred);
+ error = UFS_TRUNCATE(vp, newsize, ioflag, cred);
UFS_WAPBL_END(mp);
if (error != 0 && error != EAGAIN)
@@ -317,4 +313,19 @@
out:
return error;
+}
+
+/* truncate all the data of the inode including extended attributes */
+int
+ufs_truncate_all(struct vnode *vp)
+{
+ struct inode *ip = VTOI(vp);
+ off_t isize = ip->i_size;
+
+ if (ip->i_ump->um_fstype == UFS2)
+ isize += ip->i_ffs2_extsize;
+
+ if (isize == 0)
+ return 0;
+ return ufs_truncate_retry(vp, IO_EXT, 0, NOCRED);
}
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_vnops.c,v 1.251 2020/04/13 19:23:20 ad Exp $ */
+/* $NetBSD: ufs_vnops.c,v 1.252 2020/04/18 19:18:34 christos Exp $ */
/*-
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.251 2020/04/13 19:23:20 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.252 2020/04/18 19:18:34 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -556,7 +556,7 @@
error = EPERM;
goto out;
}
- error = ufs_truncate_retry(vp, vap->va_size, cred);
+ error = ufs_truncate_retry(vp, 0, vap->va_size, cred);
if (error)
goto out;
break;