Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Change union rmdir semantics to fail directory removal for
details: https://anonhg.NetBSD.org/src/rev/e9ae32822a12
branches: trunk
changeset: 768046:e9ae32822a12
user: hannken <hannken%NetBSD.org@localhost>
date: Sun Aug 07 06:01:51 2011 +0000
description:
Change union rmdir semantics to fail directory removal for
non-empty directories like all other file systems do.
Change test accordingly.
diffstat:
sys/fs/union/union.h | 3 +-
sys/fs/union/union_subr.c | 95 +++++++++++++++++++++++++++++++++++++++++++++-
sys/fs/union/union_vnops.c | 11 ++++-
tests/fs/vfs/t_union.c | 5 +-
4 files changed, 107 insertions(+), 7 deletions(-)
diffs (192 lines):
diff -r 19fe505bf0ed -r e9ae32822a12 sys/fs/union/union.h
--- a/sys/fs/union/union.h Sun Aug 07 05:56:32 2011 +0000
+++ b/sys/fs/union/union.h Sun Aug 07 06:01:51 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: union.h,v 1.18 2008/06/28 01:34:05 rumble Exp $ */
+/* $NetBSD: union.h,v 1.19 2011/08/07 06:01:51 hannken Exp $ */
/*
* Copyright (c) 1994 The Regents of the University of California.
@@ -134,6 +134,7 @@
struct vnode *, struct vnode *,
struct componentname *, struct vnode *,
struct vnode *, int);
+extern int union_check_rmdir(struct union_node *, kauth_cred_t);
extern int union_copyfile(struct vnode *, struct vnode *, kauth_cred_t,
struct lwp *);
extern int union_copyup(struct union_node *, int, kauth_cred_t,
diff -r 19fe505bf0ed -r e9ae32822a12 sys/fs/union/union_subr.c
--- a/sys/fs/union/union_subr.c Sun Aug 07 05:56:32 2011 +0000
+++ b/sys/fs/union/union_subr.c Sun Aug 07 06:01:51 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: union_subr.c,v 1.43 2011/06/12 03:35:55 rmind Exp $ */
+/* $NetBSD: union_subr.c,v 1.44 2011/08/07 06:01:51 hannken Exp $ */
/*
* Copyright (c) 1994
@@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.43 2011/06/12 03:35:55 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.44 2011/08/07 06:01:51 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -82,6 +82,7 @@
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
+#include <sys/dirent.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
@@ -1194,6 +1195,96 @@
}
/*
+ * Check whether node can rmdir (check empty).
+ */
+int
+union_check_rmdir(struct union_node *un, kauth_cred_t cred)
+{
+ int dirlen, eofflag, error;
+ char *dirbuf;
+ struct vattr va;
+ struct vnode *tvp;
+ struct dirent *dp, *edp;
+ struct componentname cn;
+ struct iovec aiov;
+ struct uio auio;
+
+ KASSERT(un->un_uppervp != NULL);
+
+ /* Check upper for being opaque. */
+ KASSERT(VOP_ISLOCKED(un->un_uppervp));
+ error = VOP_GETATTR(un->un_uppervp, &va, cred);
+ if (error || (va.va_flags & OPAQUE))
+ return error;
+
+ if (un->un_lowervp == NULL)
+ return 0;
+
+ /* Check lower for being empty. */
+ vn_lock(un->un_lowervp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_GETATTR(un->un_lowervp, &va, cred);
+ if (error) {
+ VOP_UNLOCK(un->un_lowervp);
+ return error;
+ }
+ dirlen = va.va_blocksize;
+ dirbuf = kmem_alloc(dirlen, KM_SLEEP);
+ if (dirbuf == NULL) {
+ VOP_UNLOCK(un->un_lowervp);
+ return ENOMEM;
+ }
+ /* error = 0; */
+ eofflag = 0;
+ auio.uio_offset = 0;
+ do {
+ aiov.iov_len = dirlen;
+ aiov.iov_base = dirbuf;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = aiov.iov_len;
+ auio.uio_rw = UIO_READ;
+ UIO_SETUP_SYSSPACE(&auio);
+ error = VOP_READDIR(un->un_lowervp, &auio, cred, &eofflag,
+ NULL, NULL);
+ if (error)
+ break;
+ edp = (struct dirent *)&dirbuf[dirlen - auio.uio_resid];
+ for (dp = (struct dirent *)dirbuf;
+ error == 0 && dp < edp;
+ dp = (struct dirent *)((char *)dp + dp->d_reclen)) {
+ if (dp->d_reclen == 0) {
+ error = ENOTEMPTY;
+ break;
+ }
+ if (dp->d_type == DT_WHT ||
+ (dp->d_namlen == 1 && dp->d_name[0] == '.') ||
+ (dp->d_namlen == 2 && !memcmp(dp->d_name, "..", 2)))
+ continue;
+ /* Check for presence in the upper layer. */
+ cn.cn_nameiop = LOOKUP;
+ cn.cn_flags = ISLASTCN | RDONLY;
+ cn.cn_cred = cred;
+ cn.cn_nameptr = dp->d_name;
+ cn.cn_namelen = dp->d_namlen;
+ cn.cn_hash = 0;
+ cn.cn_consume = 0;
+ error = VOP_LOOKUP(un->un_uppervp, &tvp, &cn);
+ if (error == ENOENT && (cn.cn_flags & ISWHITEOUT)) {
+ error = 0;
+ continue;
+ }
+ if (error == 0)
+ vput(tvp);
+ error = ENOTEMPTY;
+ }
+ } while (error == 0 && !eofflag);
+ kmem_free(dirbuf, dirlen);
+ VOP_UNLOCK(un->un_lowervp);
+
+ return error;
+}
+
+/*
* This hook is called from vn_readdir() to switch to lower directory
* entry after the upper directory is read.
*/
diff -r 19fe505bf0ed -r e9ae32822a12 sys/fs/union/union_vnops.c
--- a/sys/fs/union/union_vnops.c Sun Aug 07 05:56:32 2011 +0000
+++ b/sys/fs/union/union_vnops.c Sun Aug 07 06:01:51 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: union_vnops.c,v 1.41 2011/08/05 08:17:47 hannken Exp $ */
+/* $NetBSD: union_vnops.c,v 1.42 2011/08/07 06:01:51 hannken Exp $ */
/*
* Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.41 2011/08/05 08:17:47 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.42 2011/08/07 06:01:51 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1432,6 +1432,13 @@
if (dun->un_uppervp == NULLVP)
panic("union rmdir: null upper vnode");
+ error = union_check_rmdir(un, cnp->cn_cred);
+ if (error) {
+ vput(ap->a_dvp);
+ vput(ap->a_vp);
+ return error;
+ }
+
if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
diff -r 19fe505bf0ed -r e9ae32822a12 tests/fs/vfs/t_union.c
--- a/tests/fs/vfs/t_union.c Sun Aug 07 05:56:32 2011 +0000
+++ b/tests/fs/vfs/t_union.c Sun Aug 07 06:01:51 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: t_union.c,v 1.7 2011/08/05 08:17:47 hannken Exp $ */
+/* $NetBSD: t_union.c,v 1.8 2011/08/07 06:01:51 hannken Exp $ */
#include <sys/types.h>
#include <sys/mount.h>
@@ -176,8 +176,9 @@
mountunion(mp, lower);
- /* all file systems fail sooner or later */
FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(ENOTEMPTY, rump_sys_rmdir(TDIR) == -1);
+ RL(rump_sys_rmdir(TDFILE));
RL(rump_sys_rmdir(TDIR));
ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TDFILE, &sb) == -1);
ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TDIR, &sb) == -1);
Home |
Main Index |
Thread Index |
Old Index