From 98f7132dfa6b3850c719c3ed3905f8cd02e35dfe Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 12 May 2008 23:15:46 +0000 Subject: [PATCH] HAMMER 43A/Many: Cleanup, bug fixes. * Fix an assertion that can occur when a deleted softlink is racing a sync of the inode. * Set HAMER_INODE_DONDISK for general records as well as for data records. This flag is set when a record might be laid down on media before its inode. (This fixes an assertion). * Set HAMMER_INODE_DDIRTY for all mtime updates. * Clean up hammer_ip_check_directory_empty(). --- sys/vfs/hammer/hammer.h | 4 ++-- sys/vfs/hammer/hammer_inode.c | 22 +++++++++++++++++++++- sys/vfs/hammer/hammer_object.c | 17 ++++++++++++----- sys/vfs/hammer/hammer_vnops.c | 16 ++++++++++++---- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 10c9fb6138..eebfb6eb9b 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.64 2008/05/12 21:17:18 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.65 2008/05/12 23:15:46 dillon Exp $ */ /* * This header file contains structures used internally by the HAMMERFS @@ -632,7 +632,7 @@ int hammer_ip_resolve_data(hammer_cursor_t cursor); int hammer_ip_delete_record(hammer_cursor_t cursor, hammer_tid_t tid); int hammer_delete_at_cursor(hammer_cursor_t cursor, int64_t *stat_bytes); int hammer_ip_check_directory_empty(hammer_transaction_t trans, - hammer_cursor_t parent_cursor, hammer_inode_t ip); + hammer_inode_t ip); int hammer_sync_hmp(hammer_mount_t hmp, int waitfor); hammer_record_t diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 7d1da72e45..74f0972b11 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.55 2008/05/12 21:17:18 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.56 2008/05/12 23:15:46 dillon Exp $ */ #include "hammer.h" @@ -1275,6 +1275,25 @@ hammer_sync_record_callback(hammer_record_t record, void *data) KKASSERT((record->flags & HAMMER_RECF_INTERLOCK_BE) == 0); record->flags |= HAMMER_RECF_INTERLOCK_BE; + /* + * If the whole inode is being deleting all on-disk records will + * be deleted very soon, we can't sync anything to disk or its + * create_tid will match its delete_tid (which is illegal), and assert. + */ + if (record->ip->sync_flags & HAMMER_INODE_DELETING) { + if (record->type == HAMMER_MEM_RECORD_GENERAL) { + record->flags |= HAMMER_RECF_DELETED_FE; + record->flags |= HAMMER_RECF_DELETED_BE; + } else { + /* + * Ugh. If it's an add we have a problem. + */ + KKASSERT(record->type != HAMMER_MEM_RECORD_ADD); + } + error = 0; + goto done; + } + /* * If DELETED_FE is set we may have already sent dependant pieces * to the disk and we must flush the record as if it hadn't been @@ -1318,6 +1337,7 @@ hammer_sync_record_callback(hammer_record_t record, void *data) Debugger("sync failed rec"); } } +done: hammer_flush_record_done(record, error); return(error); } diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index 60cb7687f4..a24ae74108 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.57 2008/05/12 21:17:18 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.58 2008/05/12 23:15:46 dillon Exp $ */ #include "hammer.h" @@ -553,6 +553,8 @@ hammer_ip_del_directory(struct hammer_transaction *trans, * the record's key. This also causes lookups to skip the * record. */ + KKASSERT(dip->flags & + (HAMMER_INODE_ONDISK | HAMMER_INODE_DONDISK)); record = hammer_alloc_mem_record(dip, 0); record->type = HAMMER_MEM_RECORD_DEL; record->leaf.base = cursor->leaf->base; @@ -785,6 +787,12 @@ hammer_ip_sync_record_cursor(hammer_cursor_t cursor, hammer_record_t record) cursor->flags |= HAMMER_CURSOR_BACKEND; cursor->flags &= ~HAMMER_CURSOR_INSERT; + /* + * Records can wind up on-media before the inode itself is on-media. + * Flag the case. + */ + record->ip->flags |= HAMMER_INODE_DONDISK; + /* * If we are deleting an exact match must be found on-disk. */ @@ -1204,7 +1212,8 @@ next_memory: * to it it would have interlocked the cursor and we should * have seen the in-memory record marked DELETED_FE. */ - if (cursor->iprec->type == HAMMER_MEM_RECORD_DEL) { + if (cursor->iprec->type == HAMMER_MEM_RECORD_DEL && + (cursor->flags & HAMMER_CURSOR_DELETE_VISIBILITY) == 0) { panic("hammer_ip_next: del-on-disk with no b-tree entry"); } break; @@ -1238,7 +1247,6 @@ hammer_ip_resolve_data(hammer_cursor_t cursor) int error; if (cursor->iprec && cursor->leaf == &cursor->iprec->leaf) { - cursor->leaf = &cursor->iprec->leaf; cursor->data = cursor->iprec->data; error = 0; } else { @@ -1592,8 +1600,7 @@ hammer_delete_at_cursor(hammer_cursor_t cursor, int64_t *stat_bytes) * Returns 0 on success, ENOTEMPTY or EDEADLK (or other errors) on failure. */ int -hammer_ip_check_directory_empty(hammer_transaction_t trans, - hammer_cursor_t parent_cursor, hammer_inode_t ip) +hammer_ip_check_directory_empty(hammer_transaction_t trans, hammer_inode_t ip) { struct hammer_cursor cursor; int error; diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 80c699689c..ddbb41911a 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.52 2008/05/12 21:17:18 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.53 2008/05/12 23:15:46 dillon Exp $ */ #include @@ -525,6 +525,11 @@ hammer_vop_ncreate(struct vop_ncreate_args *ap) /* * hammer_vop_getattr { vp, vap } + * + * Retrieve an inode's attribute information. When accessing inodes + * historically we fake the atime field to ensure consistent results. + * The atime field is stored in the B-Tree element and allowed to be + * updated without cycling the element. */ static int @@ -552,7 +557,10 @@ hammer_vop_getattr(struct vop_getattr_args *ap) vap->va_rmajor = 0; vap->va_rminor = 0; vap->va_size = ip->ino_data.size; - hammer_to_timespec(ip->ino_leaf.atime, &vap->va_atime); + if (ip->flags & HAMMER_INODE_RO) + hammer_to_timespec(ip->ino_data.mtime, &vap->va_atime); + else + hammer_to_timespec(ip->ino_leaf.atime, &vap->va_atime); hammer_to_timespec(ip->ino_data.mtime, &vap->va_mtime); hammer_to_timespec(ip->ino_data.ctime, &vap->va_ctime); vap->va_flags = ip->ino_data.uflags; @@ -1477,6 +1485,7 @@ hammer_vop_setattr(struct vop_setattr_args *ap) ip->ino_data.mtime = hammer_timespec_to_transid(&vap->va_mtime); modflags |= HAMMER_INODE_ITIMES; + modflags |= HAMMER_INODE_DDIRTY; /* XXX mtime */ } if (vap->va_mode != (mode_t)VNOVAL) { if (ip->ino_data.mode != vap->va_mode) { @@ -2043,8 +2052,7 @@ retry: */ if (error == 0 && ip->ino_data.obj_type == HAMMER_OBJTYPE_DIRECTORY) { - error = hammer_ip_check_directory_empty(trans, &cursor, - ip); + error = hammer_ip_check_directory_empty(trans, ip); } /* -- 2.41.0