HAMMER 43A/Many: Cleanup, bug fixes.
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 12 May 2008 23:15:46 +0000 (23:15 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 12 May 2008 23:15:46 +0000 (23:15 +0000)
* 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
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_vnops.c

index 10c9fb6..eebfb6e 100644 (file)
@@ -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
index 7d1da72..74f0972 100644 (file)
@@ -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);
 }
index 60cb768..a24ae74 100644 (file)
@@ -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;
index 80c6996..ddbb419 100644 (file)
@@ -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 <sys/param.h>
@@ -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);
                }
 
                /*