Experimental support for extended attributes on UFS1 file systems, using a

backing file per attribute type indexed by inode number to hold the extended
attributes.

This is working pretty well on my test systems, except for the "autostart"
feature.  I need someone with a better handle on the VFS locking protocol
to go over that.

This is a work-in-progress.  There are parts of this that could be re-factored
allowing this approach to be used on other types of file systems.

Adapted from FreeBSD.
This commit is contained in:
thorpej 2005-08-28 19:37:58 +00:00
parent 3876130b24
commit e1afed9c2d
16 changed files with 2186 additions and 21 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.567 2005/08/20 17:23:53 rpaulo Exp $
# $NetBSD: mi,v 1.568 2005/08/28 19:37:58 thorpej Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -964,6 +964,7 @@
./usr/sbin/envstat base-sysutil-bin
./usr/sbin/eshconfig base-sysutil-bin
./usr/sbin/etcupdate base-sysutil-bin
./usr/sbin/extattrctl base-sysutil-bin
./usr/sbin/faithd base-router-bin inet6
./usr/sbin/fixmount base-nfsclient-bin
./usr/sbin/flush base-obsolete obsolete

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.808 2005/08/23 17:47:07 elad Exp $
# $NetBSD: mi,v 1.809 2005/08/28 19:37:58 thorpej Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -1486,6 +1486,7 @@
./usr/include/ufs/ufs/dinode.h comp-c-include
./usr/include/ufs/ufs/dir.h comp-c-include
./usr/include/ufs/ufs/dirhash.h comp-obsolete obsolete
./usr/include/ufs/ufs/extattr.h comp-c-include
./usr/include/ufs/ufs/inode.h comp-c-include
./usr/include/ufs/ufs/quota.h comp-c-include
./usr/include/ufs/ufs/ufs_bswap.h comp-c-include

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.818 2005/08/23 12:14:01 peter Exp $
# $NetBSD: mi,v 1.819 2005/08/28 19:37:58 thorpej Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -1757,6 +1757,7 @@
./usr/share/man/cat8/evbsh3/makedev.0 man-obsolete obsolete
./usr/share/man/cat8/evbsh5/MAKEDEV.0 man-obsolete obsolete
./usr/share/man/cat8/evbsh5/makedev.0 man-obsolete obsolete
./usr/share/man/cat8/extattrctl.0 man-sysutil-catman .cat
./usr/share/man/cat8/faithd.0 man-router-catman inet6,.cat
./usr/share/man/cat8/fastboot.0 man-sysutil-catman .cat
./usr/share/man/cat8/fasthalt.0 man-sysutil-catman .cat
@ -4019,6 +4020,7 @@
./usr/share/man/man8/evbsh3/makedev.8 man-obsolete obsolete
./usr/share/man/man8/evbsh5/MAKEDEV.8 man-obsolete obsolete
./usr/share/man/man8/evbsh5/makedev.8 man-obsolete obsolete
./usr/share/man/man8/extattrctl.8 man-sysutil-man .man
./usr/share/man/man8/faithd.8 man-router-man inet6,.man
./usr/share/man/man8/fastboot.8 man-sysutil-man .man
./usr/share/man/man8/fasthalt.8 man-sysutil-man .man

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_extern.h,v 1.43 2005/07/15 05:01:16 thorpej Exp $ */
/* $NetBSD: ffs_extern.h,v 1.44 2005/08/28 19:37:59 thorpej Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -136,6 +136,8 @@ int ffs_sync(struct mount *, int, struct ucred *, struct proc *);
int ffs_vget(struct mount *, ino_t, struct vnode **);
int ffs_fhtovp(struct mount *, struct fid *, struct vnode **);
int ffs_vptofh(struct vnode *, struct fid *);
int ffs_extattrctl(struct mount *, int, struct vnode *, int,
const char *, struct proc *);
int ffs_sbupdate(struct ufsmount *, int);
int ffs_cgupdate(struct ufsmount *, int);
@ -155,6 +157,12 @@ int ffs_reclaim(void *);
int ffs_getpages(void *);
int ffs_putpages(void *);
void ffs_gop_size(struct vnode *, off_t, off_t *, int);
int ffs_openextattr(void *);
int ffs_closeextattr(void *);
int ffs_getextattr(void *);
int ffs_setextattr(void *);
int ffs_listextattr(void *);
int ffs_deleteextattr(void *);
#ifdef SYSCTL_SETUP_PROTO
SYSCTL_SETUP_PROTO(sysctl_vfs_ffs_setup);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_vfsops.c,v 1.169 2005/08/23 08:05:13 christos Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.170 2005/08/28 19:37:59 thorpej Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.169 2005/08/23 08:05:13 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.170 2005/08/28 19:37:59 thorpej Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -108,7 +108,7 @@ struct vfsops ffs_vfsops = {
ffs_mountroot,
ufs_check_export,
ffs_snapshot,
vfs_stdextattrctl,
ffs_extattrctl,
ffs_vnodeopv_descs,
};
VFS_ATTACH(ffs_vfsops);
@ -979,6 +979,22 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
}
if (ronly == 0 && fs->fs_snapinum[0] != 0)
ffs_snapshot_mount(mp);
#ifdef UFS_EXTATTR
/*
* Initialize file-backed extended attributes on UFS1 file
* systems.
*/
if (ump->um_fstype == UFS1) {
ufs_extattr_uepm_init(&ump->um_extattr);
#ifdef UFS_EXTATTR_AUTOSTART
/*
* XXX Just ignore errors. Not clear that we should
* XXX fail the mount in this case.
*/
(void) ufs_extattr_autostart(mp, p);
#endif
}
#endif /* UFS_EXTATTR */
return (0);
out:
if (fs)
@ -1116,14 +1132,24 @@ ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
int
ffs_unmount(struct mount *mp, int mntflags, struct proc *p)
{
struct ufsmount *ump;
struct fs *fs;
struct ufsmount *ump = VFSTOUFS(mp);
struct fs *fs = ump->um_fs;
int error, flags, penderr;
penderr = 0;
flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
#ifdef UFS_EXTATTR
if (ump->um_fstype == UFS1) {
error = ufs_extattr_stop(mp, p);
if (error)
printf("%s: ufs_extattr_stop returned %d\n",
fs->fs_fsmnt, error);
else
ufs_extattr_uepm_destroy(&ump->um_extattr);
}
#endif /* UFS_EXTATTR */
if (mp->mnt_flag & MNT_SOFTDEP) {
if ((error = softdep_flushfiles(mp, flags, p)) != 0)
return (error);
@ -1131,8 +1157,6 @@ ffs_unmount(struct mount *mp, int mntflags, struct proc *p)
if ((error = ffs_flushfiles(mp, flags, p)) != 0)
return (error);
}
ump = VFSTOUFS(mp);
fs = ump->um_fs;
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("%s: unmount pending error: blocks %" PRId64
" files %d\n",
@ -1685,3 +1709,19 @@ ffs_cgupdate(struct ufsmount *mp, int waitfor)
allerror = error;
return (allerror);
}
int
ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
int attrnamespace, const char *attrname, struct proc *p)
{
#ifdef UFS_EXTATTR
/*
* File-backed extended attributes are only supported on UFS1.
* UFS2 has native extended attributes.
*/
if (VFSTOUFS(mp)->um_fstype == UFS1)
return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname,
p));
#endif
return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname, p));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_vnops.c,v 1.72 2005/07/26 12:14:46 yamt Exp $ */
/* $NetBSD: ffs_vnops.c,v 1.73 2005/08/28 19:37:59 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.72 2005/07/26 12:14:46 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.73 2005/08/28 19:37:59 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -117,6 +117,12 @@ const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_getpages_desc, ffs_getpages }, /* getpages */
{ &vop_putpages_desc, ffs_putpages }, /* putpages */
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_vnodeop_opv_desc =
@ -172,6 +178,12 @@ const struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_getpages_desc, spec_getpages }, /* getpages */
{ &vop_putpages_desc, spec_putpages }, /* putpages */
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_specop_opv_desc =
@ -226,6 +238,12 @@ const struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_update_desc, ffs_update }, /* update */
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_putpages_desc, fifo_putpages }, /* putpages */
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ffs_fifoop_opv_desc =
@ -611,3 +629,141 @@ ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
*eobp = blkroundup(fs, size);
}
}
int
ffs_openextattr(void *v)
{
struct vop_openextattr_args /* {
struct vnode *a_vp;
struct ucred *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;
struct ucred *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;
struct ucred *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
return (ufs_getextattr(ap));
#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;
struct ucred *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
return (ufs_setextattr(ap));
#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;
struct ucred *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_deleteextattr(void *v)
{
struct vop_deleteextattr_args /* {
struct vnode *a_vp;
int a_attrnamespace;
struct ucred *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
return (ufs_deleteextattr(ap));
#else
return (EOPNOTSUPP);
#endif
}
/* XXX Not implemented for UFS2 file systems. */
return (EOPNOTSUPP);
}

View File

@ -1,4 +1,4 @@
# $NetBSD: files.ufs,v 1.10 2005/07/10 01:08:52 thorpej Exp $
# $NetBSD: files.ufs,v 1.11 2005/08/28 19:37:58 thorpej Exp $
deffs FFS
deffs EXT2FS
@ -7,6 +7,7 @@ deffs fs_lfs.h LFS # XXX
defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS
UFS_DIRHASH
UFS_EXTATTR UFS_EXTATTR_AUTOSTART
file ufs/ext2fs/ext2fs_alloc.c ext2fs
file ufs/ext2fs/ext2fs_balloc.c ext2fs
@ -50,6 +51,7 @@ file ufs/mfs/mfs_vnops.c mfs
file ufs/ufs/ufs_bmap.c ffs | lfs | mfs | ext2fs
file ufs/ufs/ufs_dirhash.c (ffs | lfs | mfs | ext2fs) & ufs_dirhash
file ufs/ufs/ufs_extattr.c (ffs | mfs) & ufs_extattr
file ufs/ufs/ufs_ihash.c ffs | lfs | mfs | ext2fs
file ufs/ufs/ufs_inode.c ffs | lfs | mfs
file ufs/ufs/ufs_lookup.c ffs | lfs | mfs | ext2fs

View File

@ -1,7 +1,8 @@
# $NetBSD: Makefile,v 1.3 2005/01/24 01:32:22 rumble Exp $
# $NetBSD: Makefile,v 1.4 2005/08/28 19:37:59 thorpej Exp $
INCSDIR= /usr/include/ufs/ufs
INCS= dinode.h dir.h inode.h quota.h ufs_bswap.h ufs_extern.h ufsmount.h
INCS= dinode.h dir.h extattr.h inode.h quota.h ufs_bswap.h ufs_extern.h \
ufsmount.h
.include <bsd.kinc.mk>

121
sys/ufs/ufs/extattr.h Normal file
View File

@ -0,0 +1,121 @@
/* $NetBSD: extattr.h,v 1.1 2005/08/28 19:37:59 thorpej Exp $ */
/*-
* Copyright (c) 1999-2001 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
*
* 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.
*
* $FreeBSD: src/sys/ufs/ufs/extattr.h,v 1.20 2005/01/31 08:16:45 imp Exp $
*/
/*
* Support for file system extended attributes on the UFS1 file system.
* Developed by the TrustedBSD Project.
*/
#ifndef _UFS_UFS_EXTATTR_H_
#define _UFS_UFS_EXTATTR_H_
#define UFS_EXTATTR_MAGIC 0x00b5d5ec
#define UFS_EXTATTR_VERSION 0x00000003
#define UFS_EXTATTR_FSROOTSUBDIR ".attribute"
#define UFS_EXTATTR_SUBDIR_SYSTEM "system"
#define UFS_EXTATTR_SUBDIR_USER "user"
#define UFS_EXTATTR_MAXEXTATTRNAME 65 /* including null */
#define UFS_EXTATTR_ATTR_FLAG_INUSE 0x00000001 /* attr has been set */
#define UFS_EXTATTR_PERM_KERNEL 0x00000000
#define UFS_EXTATTR_PERM_ROOT 0x00000001
#define UFS_EXTATTR_PERM_OWNER 0x00000002
#define UFS_EXTATTR_PERM_ANYONE 0x00000003
#define UFS_EXTATTR_UEPM_INITIALIZED 0x00000001
#define UFS_EXTATTR_UEPM_STARTED 0x00000002
#define UFS_EXTATTR_CMD_START 0x00000001
#define UFS_EXTATTR_CMD_STOP 0x00000002
#define UFS_EXTATTR_CMD_ENABLE 0x00000003
#define UFS_EXTATTR_CMD_DISABLE 0x00000004
struct ufs_extattr_fileheader {
uint32_t uef_magic; /* magic number for sanity checking */
uint32_t uef_version; /* version of attribute file */
uint32_t uef_size; /* size of attributes, w/o header */
};
struct ufs_extattr_header {
uint32_t ueh_flags; /* flags for attribute */
uint32_t ueh_len; /* local defined length; <= uef_size */
uint32_t ueh_i_gen; /* generation number for sanity */
/* data follows the header */
};
#ifdef _KERNEL
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_EXTATTR);
#endif
struct vnode;
LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry);
struct ufs_extattr_list_entry {
LIST_ENTRY(ufs_extattr_list_entry) uele_entries;
struct ufs_extattr_fileheader uele_fileheader;
int uele_attrnamespace;
char uele_attrname[UFS_EXTATTR_MAXEXTATTRNAME];
struct vnode *uele_backing_vnode;
int uele_flags;
};
/* uele_flags */
#define UELE_F_NEEDSWAP 0x01 /* needs byte swap */
#define UELE_NEEDSWAP(uele) ((uele)->uele_flags & UELE_F_NEEDSWAP)
struct lock;
struct ucred;
struct ufs_extattr_per_mount {
struct lock uepm_lock;
struct ufs_extattr_list_head uepm_list;
struct ucred *uepm_ucred;
int uepm_flags;
};
void ufs_extattr_uepm_init(struct ufs_extattr_per_mount *uepm);
void ufs_extattr_uepm_destroy(struct ufs_extattr_per_mount *uepm);
int ufs_extattr_start(struct mount *mp, struct proc *p);
int ufs_extattr_autostart(struct mount *mp, struct proc *p);
int ufs_extattr_stop(struct mount *mp, struct proc *p);
int ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename,
int attrnamespace, const char *attrname, struct proc *p);
int ufs_getextattr(struct vop_getextattr_args *ap);
int ufs_deleteextattr(struct vop_deleteextattr_args *ap);
int ufs_setextattr(struct vop_setextattr_args *ap);
int ufs_listextattr(struct vop_listextattr_args *ap);
void ufs_extattr_vnode_inactive(struct vnode *vp, struct proc *p);
#endif /* !_KERNEL */
#endif /* !_UFS_UFS_EXTATTR_H_ */

1324
sys/ufs/ufs/ufs_extattr.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_inode.c,v 1.51 2005/07/23 12:18:41 yamt Exp $ */
/* $NetBSD: ufs_inode.c,v 1.52 2005/08/28 19:37:59 thorpej Exp $ */
/*
* Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.51 2005/07/23 12:18:41 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.52 2005/08/28 19:37:59 thorpej Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -59,6 +59,9 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.51 2005/07/23 12:18:41 yamt Exp $");
#ifdef UFS_DIRHASH
#include <ufs/ufs/dirhash.h>
#endif
#ifdef UFS_EXTATTR
#include <ufs/ufs/extattr.h>
#endif
#include <uvm/uvm.h>
@ -97,6 +100,9 @@ ufs_inactive(void *v)
#ifdef QUOTA
if (!getinoquota(ip))
(void)chkiq(ip, -1, NOCRED, 0);
#endif
#ifdef UFS_EXTATTR
ufs_extattr_vnode_inactive(vp, p);
#endif
if (ip->i_size != 0) {
error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufsmount.h,v 1.18 2005/05/22 08:35:28 hannken Exp $ */
/* $NetBSD: ufsmount.h,v 1.19 2005/08/28 19:37:59 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -58,6 +58,8 @@ struct mfs_args {
#include "opt_ffs.h"
#endif
#include <ufs/ufs/extattr.h>
struct buf;
struct inode;
struct nameidata;
@ -84,6 +86,9 @@ struct ufsmount {
#define um_e2fs ufsmount_u.e2fs
#define um_e2fsb ufsmount_u.e2fs->s_es
/* Extended attribute information. */
struct ufs_extattr_per_mount um_extattr;
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
u_long um_nindir; /* indirect ptrs per block */

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.204 2005/07/11 15:37:05 kiyohara Exp $
# $NetBSD: Makefile,v 1.205 2005/08/28 19:37:58 thorpej Exp $
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
.include <bsd.own.mk>
@ -6,7 +6,7 @@
SUBDIR= ac accton altq amd apm apmd arp bad144 bind bootp catman \
chown chroot chrtbl cnwctl cron dev_mkdb \
dhcp diskpart dumpfs dumplfs edquota eeprom \
envstat eshconfig etcupdate fssconfig fwctl grfconfig \
envstat eshconfig etcupdate extattrctl fssconfig fwctl grfconfig \
grfinfo gspa hilinfo ifwatchd inetd installboot \
iopctl iostat ipwctl irdaattach isdn iteconfig iwictl\
kgmon lastlogin link lpr mailwrapper makefs \

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2005/08/28 19:37:59 thorpej Exp $
PROG= extattrctl
MAN= extattrctl.8
WARNS?= 3
.include <bsd.prog.mk>

View File

@ -0,0 +1,209 @@
.\" $NetBSD: extattrctl.8,v 1.1 2005/08/28 19:37:59 thorpej Exp $
.\"
.\" Copyright (c) 2000-2001 Robert N. M. Watson
.\" All rights reserved.
.\"
.\" This software was developed by Robert Watson for the TrustedBSD Project.
.\"
.\" 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.
.\"
.\" $FreeBSD: src/usr.sbin/extattrctl/extattrctl.8,v 1.24 2005/02/09 18:04:40 ru Exp $
.\"
.\" Developed by the TrustedBSD Project.
.\" Support for file system extended attribute.
.\"
.Dd July 11, 2005
.Dt EXTATTRCTL 8
.Os
.Sh NAME
.Nm extattrctl
.Nd manage UFS1 extended attributes
.Sh SYNOPSIS
.Nm
.Cm start
.Ar path
.Nm
.Cm stop
.Ar path
.Nm
.Cm initattr
.Op Fl f
.Op Fl p Ar path
.Ar attrsize
.Ar attrfile
.Nm
.Cm showattr
.Ar attrfile
.Nm
.Cm enable
.Ar path
.Ar attrnamespace
.Ar attrname
.Ar attrfile
.Nm
.Cm disable
.Ar path
.Ar attrnamespace
.Ar attrname
.Sh DESCRIPTION
The
.Nm
utility
is the management utility for extended attributes over the UFS1 file system.
It allows the starting and stopping of extended attributes on a file system,
as well as initialization of attribute backing files, and enabling and
disabling of specific extended attributes on a file system.
.Pp
The first argument on the command line indicates the operation to be
performed.
Operation must be one of the following:
.Bl -tag -width indent
.It Cm start Ar path
Start extended attribute support on the file system named using
.Ar path .
The file system must be an UFS1 file system, and the UFS_EXTATTR kernel
option must have been enabled.
.It Cm stop Ar path
Stop extended attribute support on the file system named using
.Ar path .
Extended attribute support must previously have been started.
.It Xo
.Cm initattr
.Op Fl f
.Op Fl p Ar path
.Ar attrsize attrfile
.Xc
Create and initialize a file to use as an attribute backing file.
You must specify a maximum per-inode size for the attribute in bytes in
.Ar attrsize ,
as well as the file where the attribute will be stored, using
.Ar attrfile .
.Pp
The
.Fl f
argument may be used to indicate that it is alright to overwrite an
existing attribute backing file; otherwise, if the target file exists,
an error will be returned.
.Pp
The
.Fl p Ar path
argument may be used to preallocate space for all attributes rather than
relying on sparse files to conserve space.
This has the advantage of guaranteeing that space will be available
for attributes when they are written, preventing low disk space conditions
from denying attribute service.
.Pp
This file should not exist before running
.Cm initattr .
.It Cm showattr Ar attrfile
Show the attribute header values in the attribute file named by
.Ar attrfile .
.It Cm enable Ar path attrnamespace attrname attrfile
Enable an attribute named
.Ar attrname
in the namespace
.Ar attrnamespace
on the file system identified using
.Ar path ,
and backed by initialized attribute file
.Ar attrfile .
Available namespaces are "user" and "system".
The backing file must have been initialized using
.Cm initattr
before its first use.
Attributes must have been started on the file system prior to the
enabling of any attributes.
.It Cm disable Ar path attrnamespace attrname
Disable the attributed named
.Ar attrname
in namespace
.Ar attrnamespace
on the file system identified by
.Ar path .
Available namespaces are "user" and "system".
The file system must have attributes started on it, and the attribute
most have been enabled using
.Cm enable .
.El
.Pp
The kernel also includes support for automatic starting of extended
attributes on a file system at mount time once configured with
.Nm .
If the kernel is built with the
.Dq UFS_EXTATTR_AUTOSTART
option, UFS will search for a
.Pa .attribute
sub-directory of the file system root during the mount operation.
If found, extended attribute support will be started for the file system.
UFS will then search for
.Pa system
and
.Pa user
sub-directories of the
.Pa .attribute
directory for any potential backing files and enable an extended attribute
for each valid backing file with the backing file name as the attribute
name.
.Sh EXAMPLES
.Dl extattrctl start /
.Pp
Start extended attributes on the root file system.
.Pp
.Dl extattrctl initattr 17 /.attribute/system/md5
.Pp
Create an attribute backing file in /.attribute/system/md5, and set the maximum
size of each attribute to 17 bytes, with a sparse file used for storing
the attributes.
.Pp
.Dl extattrctl enable / system md5 /.attribute/system/md5
.Pp
Enable an attribute named md5 on the root file system, backed from the file
/.attribute/system/md5.
.Pp
.Dl extattrctl disable / md5
.Pp
Disable the attribute named md5 on the root file system.
.Pp
.Dl extattrctl stop /
.Pp
Stop extended attributes on the root file system.
.Sh SEE ALSO
.Xr extattr_get_file 2 ,
.\" .Xr ffs 7 ,
.Xr getextattr 1 ,
.Xr extattr 9
.Sh HISTORY
Extended attribute support was developed as part of the TrustedBSD Project,
and introduced in
.Fx 5.0
and
.Nx 4.0 .
It was developed to support security extensions requiring additional labels
to be associated with each file or directory.
.Sh AUTHORS
Robert N M Watson
.Sh BUGS
.Nm
works only on UFS1 file systems.
The kernel support for extended attribute backing files and this control
program should be generalized for any file system that lacks native extended
attribute support.

View File

@ -0,0 +1,281 @@
/* $NetBSD: extattrctl.c,v 1.1 2005/08/28 19:37:59 thorpej Exp $ */
/*-
* Copyright (c) 1999-2002 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
*
* 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.
*
* $FreeBSD: src/usr.sbin/extattrctl/extattrctl.c,v 1.19 2002/04/19 01:42:55 rwatson Exp $
*/
/*
* Developed by the TrustedBSD Project.
* Support for file system extended attribute.
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/extattr.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <ufs/ufs/extattr.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <machine/bswap.h>
#include <machine/endian.h>
static int needswap;
static uint32_t
rw32(uint32_t v)
{
if (needswap)
return (bswap32(v));
return (v);
}
static void
usage(void)
{
fprintf(stderr,
"usage:\n"
" %s start path\n"
" %s stop path\n"
" %s initattr [-f] [-p path] attrsize attrfile\n"
" %s showattr attrfile\n"
" %s enable path attrnamespace attrname attrfile\n"
" %s disable path attrnamespace attrname\n",
getprogname(), getprogname(), getprogname(),
getprogname(), getprogname(), getprogname());
exit(1);
}
static uint64_t
num_inodes_by_path(const char *path)
{
struct statvfs buf;
if (statvfs(path, &buf) == -1) {
warn("statvfs(%s)", path);
return (-1);
}
return (buf.f_files);
}
static const char zero_buf[8192];
static int
initattr(int argc, char *argv[])
{
struct ufs_extattr_fileheader uef;
char *fs_path = NULL;
int ch, i, error, flags;
ssize_t wlen;
size_t easize;
flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
optind = 0;
while ((ch = getopt(argc, argv, "fp:r:w:")) != -1) {
switch (ch) {
case 'f':
flags &= ~O_EXCL;
break;
case 'p':
fs_path = optarg;
break;
case 'B':
#if BYTE_ORDER == LITTLE_ENDIAN
if (strcmp(optarg, "le") == 0)
needswap = 0;
else if (strcmp(optarg, "be") == 0)
needswap = 1;
else
usage();
#else
if (strcmp(optarg, "be") == 0)
needswap = 0;
else if (strcmp(optarg, "le") == 0)
needswap = 1;
else
usage();
#endif
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
error = 0;
if ((i = open(argv[1], flags, 0600)) == -1) {
warn("open(%s)", argv[1]);
return (-1);
}
uef.uef_magic = rw32(UFS_EXTATTR_MAGIC);
uef.uef_version = rw32(UFS_EXTATTR_VERSION);
uef.uef_size = rw32(atoi(argv[0]));
if (write(i, &uef, sizeof(uef)) != sizeof(uef)) {
warn("unable to write arribute file header");
error = -1;
} else if (fs_path != NULL) {
easize = (sizeof(uef) + uef.uef_size) *
num_inodes_by_path(fs_path);
while (easize > 0) {
size_t x = (easize > sizeof(zero_buf)) ?
sizeof(zero_buf) : easize;
wlen = write(i, zero_buf, x);
if (wlen != x) {
warn("unable to write attribute file");
error = -1;
break;
}
easize -= wlen;
}
}
if (error == -1) {
unlink(argv[1]);
return (-1);
}
return (0);
}
static int
showattr(int argc, char *argv[])
{
struct ufs_extattr_fileheader uef;
int i, fd;
const char *bo;
if (argc != 1)
usage();
fd = open(argv[0], O_RDONLY);
if (fd == -1) {
warn("open(%s)", argv[0]);
return (-1);
}
i = read(fd, &uef, sizeof(uef));
if (i != sizeof(uef)) {
warn("unable to read attribute file header");
return (-1);
}
if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) {
needswap = 1;
if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) {
fprintf(stderr, "%s: bad magic\n", argv[0]);
return (-1);
}
}
#if BYTE_ORDER == LITTLE_ENDIAN
bo = needswap ? "big-endian" : "little-endian";
#else
bo = needswap ? "little-endian" : "big-endian";
#endif
printf("%s: version %u, size %u, byte-order: %s\n",
argv[0], rw32(uef.uef_version), rw32(uef.uef_size), bo);
return (0);
}
int
main(int argc, char *argv[])
{
int error = 0, attrnamespace;
if (argc < 2)
usage();
if (!strcmp(argv[1], "start")) {
if (argc != 3)
usage();
error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
NULL);
if (error)
err(1, "start");
} else if (!strcmp(argv[1], "stop")) {
if (argc != 3)
usage();
error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
NULL);
if (error)
err(1, "stop");
} else if (!strcmp(argv[1], "enable")) {
if (argc != 6)
usage();
error = extattr_string_to_namespace(argv[3], &attrnamespace);
if (error)
errx(1, "bad namespace: %s", argv[3]);
error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
attrnamespace, argv[4]);
if (error)
err(1, "enable");
} else if (!strcmp(argv[1], "disable")) {
if (argc != 5)
usage();
error = extattr_string_to_namespace(argv[3], &attrnamespace);
if (error)
errx(1, "bad namespace: %s", argv[3]);
error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
attrnamespace, argv[4]);
if (error)
err(1, "disable");
} else if (!strcmp(argv[1], "initattr")) {
argc -= 2;
argv += 2;
error = initattr(argc, argv);
if (error)
return (1);
} else if (!strcmp(argv[1], "showattr")) {
argc -= 2;
argv += 2;
error = showattr(argc, argv);
if (error)
return (1);
} else
usage();
return (0);
}