1*dd94f1b1SMatthew Dillon /* 2*dd94f1b1SMatthew Dillon * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3*dd94f1b1SMatthew Dillon * 4*dd94f1b1SMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5*dd94f1b1SMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 6*dd94f1b1SMatthew Dillon * 7*dd94f1b1SMatthew Dillon * Redistribution and use in source and binary forms, with or without 8*dd94f1b1SMatthew Dillon * modification, are permitted provided that the following conditions 9*dd94f1b1SMatthew Dillon * are met: 10*dd94f1b1SMatthew Dillon * 11*dd94f1b1SMatthew Dillon * 1. Redistributions of source code must retain the above copyright 12*dd94f1b1SMatthew Dillon * notice, this list of conditions and the following disclaimer. 13*dd94f1b1SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 14*dd94f1b1SMatthew Dillon * notice, this list of conditions and the following disclaimer in 15*dd94f1b1SMatthew Dillon * the documentation and/or other materials provided with the 16*dd94f1b1SMatthew Dillon * distribution. 17*dd94f1b1SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 18*dd94f1b1SMatthew Dillon * contributors may be used to endorse or promote products derived 19*dd94f1b1SMatthew Dillon * from this software without specific, prior written permission. 20*dd94f1b1SMatthew Dillon * 21*dd94f1b1SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*dd94f1b1SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*dd94f1b1SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24*dd94f1b1SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25*dd94f1b1SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26*dd94f1b1SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*dd94f1b1SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*dd94f1b1SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29*dd94f1b1SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30*dd94f1b1SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31*dd94f1b1SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*dd94f1b1SMatthew Dillon * SUCH DAMAGE. 33*dd94f1b1SMatthew Dillon * 34*dd94f1b1SMatthew Dillon * $DragonFly: src/sys/vfs/hammer/hammer_mirror.c,v 1.1 2008/06/24 17:38:17 dillon Exp $ 35*dd94f1b1SMatthew Dillon */ 36*dd94f1b1SMatthew Dillon /* 37*dd94f1b1SMatthew Dillon * HAMMER mirroring ioctls - serialize and deserialize modifications made 38*dd94f1b1SMatthew Dillon * to a filesystem. 39*dd94f1b1SMatthew Dillon */ 40*dd94f1b1SMatthew Dillon 41*dd94f1b1SMatthew Dillon #include "hammer.h" 42*dd94f1b1SMatthew Dillon 43*dd94f1b1SMatthew Dillon int 44*dd94f1b1SMatthew Dillon hammer_ioc_mirror_read(hammer_transaction_t trans, hammer_inode_t ip, 45*dd94f1b1SMatthew Dillon struct hammer_ioc_mirror_rw *mirror) 46*dd94f1b1SMatthew Dillon { 47*dd94f1b1SMatthew Dillon struct hammer_cursor cursor; 48*dd94f1b1SMatthew Dillon hammer_btree_elm_t elm; 49*dd94f1b1SMatthew Dillon int error; 50*dd94f1b1SMatthew Dillon 51*dd94f1b1SMatthew Dillon if ((mirror->key_beg.localization | mirror->key_end.localization) & 52*dd94f1b1SMatthew Dillon HAMMER_LOCALIZE_PSEUDOFS_MASK) { 53*dd94f1b1SMatthew Dillon return(EINVAL); 54*dd94f1b1SMatthew Dillon } 55*dd94f1b1SMatthew Dillon if (hammer_btree_cmp(&mirror->key_beg, &mirror->key_end) > 0) 56*dd94f1b1SMatthew Dillon return(EINVAL); 57*dd94f1b1SMatthew Dillon 58*dd94f1b1SMatthew Dillon mirror->key_cur = mirror->key_beg; 59*dd94f1b1SMatthew Dillon mirror->key_cur.localization += ip->obj_localization; 60*dd94f1b1SMatthew Dillon 61*dd94f1b1SMatthew Dillon retry: 62*dd94f1b1SMatthew Dillon error = hammer_init_cursor(trans, &cursor, NULL, NULL); 63*dd94f1b1SMatthew Dillon if (error) { 64*dd94f1b1SMatthew Dillon hammer_done_cursor(&cursor); 65*dd94f1b1SMatthew Dillon goto failed; 66*dd94f1b1SMatthew Dillon } 67*dd94f1b1SMatthew Dillon cursor.key_beg = mirror->key_cur; 68*dd94f1b1SMatthew Dillon cursor.key_end = mirror->key_end; 69*dd94f1b1SMatthew Dillon cursor.key_end.localization += ip->obj_localization; 70*dd94f1b1SMatthew Dillon 71*dd94f1b1SMatthew Dillon cursor.flags |= HAMMER_CURSOR_END_INCLUSIVE; 72*dd94f1b1SMatthew Dillon cursor.flags |= HAMMER_CURSOR_BACKEND; 73*dd94f1b1SMatthew Dillon 74*dd94f1b1SMatthew Dillon /* 75*dd94f1b1SMatthew Dillon * This flag allows the btree scan code to return internal nodes 76*dd94f1b1SMatthew Dillon * at every index, giving the mirroring code the ability to skip 77*dd94f1b1SMatthew Dillon * whole sub-trees based on mirror_tid. 78*dd94f1b1SMatthew Dillon */ 79*dd94f1b1SMatthew Dillon cursor.flags |= HAMMER_CURSOR_MIRRORING; 80*dd94f1b1SMatthew Dillon 81*dd94f1b1SMatthew Dillon error = hammer_btree_first(&cursor); 82*dd94f1b1SMatthew Dillon while (error == 0) { 83*dd94f1b1SMatthew Dillon /* 84*dd94f1b1SMatthew Dillon * Internal or Leaf node 85*dd94f1b1SMatthew Dillon */ 86*dd94f1b1SMatthew Dillon elm = &cursor.node->ondisk->elms[cursor.index]; 87*dd94f1b1SMatthew Dillon reblock->key_cur.obj_id = elm->base.obj_id; 88*dd94f1b1SMatthew Dillon reblock->key_cur.localization = elm->base.localization; 89*dd94f1b1SMatthew Dillon 90*dd94f1b1SMatthew Dillon /* 91*dd94f1b1SMatthew Dillon * Yield to more important tasks 92*dd94f1b1SMatthew Dillon */ 93*dd94f1b1SMatthew Dillon if ((error = hammer_signal_check(trans->hmp)) != 0) 94*dd94f1b1SMatthew Dillon break; 95*dd94f1b1SMatthew Dillon if (trans->hmp->sync_lock.wanted) { 96*dd94f1b1SMatthew Dillon tsleep(trans, 0, "hmrslo", hz / 10); 97*dd94f1b1SMatthew Dillon } 98*dd94f1b1SMatthew Dillon if (trans->hmp->locked_dirty_count + 99*dd94f1b1SMatthew Dillon trans->hmp->io_running_count > hammer_limit_dirtybufs) { 100*dd94f1b1SMatthew Dillon hammer_flusher_async(trans->hmp); 101*dd94f1b1SMatthew Dillon tsleep(trans, 0, "hmrslo", hz / 10); 102*dd94f1b1SMatthew Dillon } 103*dd94f1b1SMatthew Dillon 104*dd94f1b1SMatthew Dillon #if 0 105*dd94f1b1SMatthew Dillon /* 106*dd94f1b1SMatthew Dillon * Acquiring the sync_lock prevents the operation from 107*dd94f1b1SMatthew Dillon * crossing a synchronization boundary. 108*dd94f1b1SMatthew Dillon * 109*dd94f1b1SMatthew Dillon * NOTE: cursor.node may have changed on return. 110*dd94f1b1SMatthew Dillon */ 111*dd94f1b1SMatthew Dillon hammer_sync_lock_sh(trans); 112*dd94f1b1SMatthew Dillon error = hammer_reblock_helper(reblock, &cursor, elm); 113*dd94f1b1SMatthew Dillon hammer_sync_unlock(trans); 114*dd94f1b1SMatthew Dillon #endif 115*dd94f1b1SMatthew Dillon if (error == 0) { 116*dd94f1b1SMatthew Dillon cursor.flags |= HAMMER_CURSOR_ATEDISK; 117*dd94f1b1SMatthew Dillon error = hammer_btree_iterate(&cursor); 118*dd94f1b1SMatthew Dillon } 119*dd94f1b1SMatthew Dillon } 120*dd94f1b1SMatthew Dillon if (error == ENOENT) 121*dd94f1b1SMatthew Dillon error = 0; 122*dd94f1b1SMatthew Dillon hammer_done_cursor(&cursor); 123*dd94f1b1SMatthew Dillon if (error == EDEADLK) 124*dd94f1b1SMatthew Dillon goto retry; 125*dd94f1b1SMatthew Dillon if (error == EINTR) { 126*dd94f1b1SMatthew Dillon reblock->head.flags |= HAMMER_IOC_HEAD_INTR; 127*dd94f1b1SMatthew Dillon error = 0; 128*dd94f1b1SMatthew Dillon } 129*dd94f1b1SMatthew Dillon failed: 130*dd94f1b1SMatthew Dillon mirror->key_cur.localization &= HAMMER_LOCALIZE_MASK; 131*dd94f1b1SMatthew Dillon return(error); 132*dd94f1b1SMatthew Dillon } 133*dd94f1b1SMatthew Dillon 134