Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ufs Move ufs_wapbl_rename to ufs_vnops.c next to the...
details: https://anonhg.NetBSD.org/src/rev/f76129e85d56
branches: trunk
changeset: 767423:f76129e85d56
user: dholland <dholland%NetBSD.org@localhost>
date: Mon Jul 18 06:45:27 2011 +0000
description:
Move ufs_wapbl_rename to ufs_vnops.c next to the old ufs_rename.
diffstat:
sys/ufs/ufs/ufs_vnops.c | 870 +++++++++++++++++++++++++++++++++++++++++++++++-
sys/ufs/ufs/ufs_wapbl.c | 870 +-----------------------------------------------
2 files changed, 870 insertions(+), 870 deletions(-)
diffs (truncated from 1789 to 300 lines):
diff -r 641f674852f5 -r f76129e85d56 sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c Mon Jul 18 06:31:59 2011 +0000
+++ b/sys/ufs/ufs/ufs_vnops.c Mon Jul 18 06:45:27 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_vnops.c,v 1.198 2011/07/18 02:35:11 dholland Exp $ */
+/* $NetBSD: ufs_vnops.c,v 1.199 2011/07/18 06:45:27 dholland Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.198 2011/07/18 02:35:11 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.199 2011/07/18 06:45:27 dholland Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -1103,6 +1103,872 @@
* once.)
*/
+/* XXX following lifted from ufs_lookup.c */
+#define FSFMT(vp) (((vp)->v_mount->mnt_iflag & IMNT_DTYPE) == 0)
+
+/*
+ * Check if either entry referred to by FROM_ULR is within the range
+ * of entries named by TO_ULR.
+ */
+static int
+ulr_overlap(const struct ufs_lookup_results *from_ulr,
+ const struct ufs_lookup_results *to_ulr)
+{
+ doff_t from_start, from_prevstart;
+ doff_t to_start, to_end;
+
+ /*
+ * FROM is a DELETE result; offset points to the entry to
+ * remove and subtracting count gives the previous entry.
+ */
+ from_start = from_ulr->ulr_offset - from_ulr->ulr_count;
+ from_prevstart = from_ulr->ulr_offset;
+
+ /*
+ * TO is a RENAME (thus non-DELETE) result; offset points
+ * to the beginning of a region to write in, and adding
+ * count gives the end of the region.
+ */
+ to_start = to_ulr->ulr_offset;
+ to_end = to_ulr->ulr_offset + to_ulr->ulr_count;
+
+ if (from_prevstart >= to_start && from_prevstart < to_end) {
+ return 1;
+ }
+ if (from_start >= to_start && from_start < to_end) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Wrapper for relookup that also updates the supplemental results.
+ */
+static int
+do_relookup(struct vnode *dvp, struct ufs_lookup_results *ulr,
+ struct vnode **vp, struct componentname *cnp)
+{
+ int error;
+
+ error = relookup(dvp, vp, cnp, 0);
+ if (error) {
+ return error;
+ }
+ /* update the supplemental reasults */
+ *ulr = VTOI(dvp)->i_crap;
+ UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
+ return 0;
+}
+
+/*
+ * Lock and relookup a sequence of two directories and two children.
+ *
+ */
+static int
+lock_vnode_sequence(struct vnode *d1, struct ufs_lookup_results *ulr1,
+ struct vnode **v1_ret, struct componentname *cn1,
+ int v1_missing_ok,
+ int overlap_error,
+ struct vnode *d2, struct ufs_lookup_results *ulr2,
+ struct vnode **v2_ret, struct componentname *cn2,
+ int v2_missing_ok)
+{
+ struct vnode *v1, *v2;
+ int error;
+
+ KASSERT(d1 != d2);
+
+ vn_lock(d1, LK_EXCLUSIVE | LK_RETRY);
+ if (VTOI(d1)->i_size == 0) {
+ /* d1 has been rmdir'd */
+ VOP_UNLOCK(d1);
+ return ENOENT;
+ }
+ error = do_relookup(d1, ulr1, &v1, cn1);
+ if (v1_missing_ok) {
+ if (error == ENOENT) {
+ /*
+ * Note: currently if the name doesn't exist,
+ * relookup succeeds (it intercepts the
+ * EJUSTRETURN from VOP_LOOKUP) and sets tvp
+ * to NULL. Therefore, we will never get
+ * ENOENT and this branch is not needed.
+ * However, in a saner future the EJUSTRETURN
+ * garbage will go away, so let's DTRT.
+ */
+ v1 = NULL;
+ error = 0;
+ }
+ } else {
+ if (error == 0 && v1 == NULL) {
+ /* This is what relookup sets if v1 disappeared. */
+ error = ENOENT;
+ }
+ }
+ if (error) {
+ VOP_UNLOCK(d1);
+ return error;
+ }
+ if (v1 && v1 == d2) {
+ VOP_UNLOCK(d1);
+ VOP_UNLOCK(v1);
+ vrele(v1);
+ return overlap_error;
+ }
+
+ /*
+ * The right way to do this is to do lookups without locking
+ * the results, and lock the results afterwards; then at the
+ * end we can avoid trying to lock v2 if v2 == v1.
+ *
+ * However, for the reasons described in the fdvp == tdvp case
+ * in rename below, we can't do that safely. So, in the case
+ * where v1 is not a directory, unlock it and lock it again
+ * afterwards. This is safe in locking order because a
+ * non-directory can't be above anything else in the tree. If
+ * v1 *is* a directory, that's not true, but then because d1
+ * != d2, v1 != v2.
+ */
+ if (v1 && v1->v_type != VDIR) {
+ VOP_UNLOCK(v1);
+ }
+ vn_lock(d2, LK_EXCLUSIVE | LK_RETRY);
+ if (VTOI(d2)->i_size == 0) {
+ /* d2 has been rmdir'd */
+ VOP_UNLOCK(d2);
+ if (v1 && v1->v_type == VDIR) {
+ VOP_UNLOCK(v1);
+ }
+ VOP_UNLOCK(d1);
+ if (v1) {
+ vrele(v1);
+ }
+ return ENOENT;
+ }
+ error = do_relookup(d2, ulr2, &v2, cn2);
+ if (v2_missing_ok) {
+ if (error == ENOENT) {
+ /* as above */
+ v2 = NULL;
+ error = 0;
+ }
+ } else {
+ if (error == 0 && v2 == NULL) {
+ /* This is what relookup sets if v2 disappeared. */
+ error = ENOENT;
+ }
+ }
+ if (error) {
+ VOP_UNLOCK(d2);
+ if (v1 && v1->v_type == VDIR) {
+ VOP_UNLOCK(v1);
+ }
+ VOP_UNLOCK(d1);
+ if (v1) {
+ vrele(v1);
+ }
+ return error;
+ }
+ if (v1 && v1->v_type != VDIR && v1 != v2) {
+ vn_lock(v1, LK_EXCLUSIVE | LK_RETRY);
+ }
+ *v1_ret = v1;
+ *v2_ret = v2;
+ return 0;
+}
+
+/*
+ * Rename vnode operation
+ * rename("foo", "bar");
+ * is essentially
+ * unlink("bar");
+ * link("foo", "bar");
+ * unlink("foo");
+ * but ``atomically''. Can't do full commit without saving state in the
+ * inode on disk which isn't feasible at this time. Best we can do is
+ * always guarantee the target exists.
+ *
+ * Basic algorithm is:
+ *
+ * 1) Bump link count on source while we're linking it to the
+ * target. This also ensure the inode won't be deleted out
+ * from underneath us while we work (it may be truncated by
+ * a concurrent `trunc' or `open' for creation).
+ * 2) Link source to destination. If destination already exists,
+ * delete it first.
+ * 3) Unlink source reference to inode if still around. If a
+ * directory was moved and the parent of the destination
+ * is different from the source, patch the ".." entry in the
+ * directory.
+ *
+ * WAPBL NOTE: wapbl_ufs_rename derived from ufs_rename in ufs_vnops.c
+ * ufs_vnops.c netbsd cvs revision 1.108
+ * which has the berkeley copyright above
+ * changes introduced to ufs_rename since netbsd cvs revision 1.164
+ * will need to be ported into wapbl_ufs_rename
+ */
+int
+wapbl_ufs_rename(void *v)
+{
+ struct vop_rename_args /* {
+ struct vnode *a_fdvp;
+ struct vnode *a_fvp;
+ struct componentname *a_fcnp;
+ struct vnode *a_tdvp;
+ struct vnode *a_tvp;
+ struct componentname *a_tcnp;
+ } */ *ap = v;
+ struct vnode *tvp, *tdvp, *fvp, *fdvp;
+ struct componentname *tcnp, *fcnp;
+ struct inode *ip, *txp, *fxp, *tdp, *fdp;
+ struct mount *mp;
+ struct direct *newdir;
+ int doingdirectory, oldparent, newparent, error;
+
+ struct ufs_lookup_results from_ulr, to_ulr;
+
+ tvp = ap->a_tvp;
+ tdvp = ap->a_tdvp;
+ fvp = ap->a_fvp;
+ fdvp = ap->a_fdvp;
+ tcnp = ap->a_tcnp;
+ fcnp = ap->a_fcnp;
+ doingdirectory = oldparent = newparent = error = 0;
+
+ /* save the supplemental lookup results as they currently exist */
+ from_ulr = VTOI(fdvp)->i_crap;
+ to_ulr = VTOI(tdvp)->i_crap;
+ UFS_CHECK_CRAPCOUNTER(VTOI(fdvp));
+ UFS_CHECK_CRAPCOUNTER(VTOI(tdvp));
+
+ /*
+ * Owing to VFS oddities we are currently called with tdvp/tvp
+ * locked and not fdvp/fvp. In a sane world we'd be passed
+ * tdvp and fdvp only, unlocked, and two name strings. Pretend
+ * we have a sane world and unlock tdvp and tvp.
+ */
+ VOP_UNLOCK(tdvp);
+ if (tvp && tvp != tdvp) {
+ VOP_UNLOCK(tvp);
+ }
+
+ /* Also pretend we have a sane world and vrele fvp/tvp. */
+ vrele(fvp);
+ fvp = NULL;
+ if (tvp) {
+ vrele(tvp);
+ tvp = NULL;
+ }
+
+ /*
+ * Check for cross-device rename.
+ */
+ if (fdvp->v_mount != tdvp->v_mount) {
+ error = EXDEV;
+ goto abort;
+ }
+
+ /*
+ * Reject "." and ".."
+ */
+ if ((fcnp->cn_flags & ISDOTDOT) || (tcnp->cn_flags & ISDOTDOT) ||
+ (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
+ (tcnp->cn_namelen == 1 && tcnp->cn_nameptr[0] == '.')) {
+ error = EINVAL;
+ goto abort;
+ }
+
+ /*
+ * Get locks.
+ */
Home |
Main Index |
Thread Index |
Old Index