xref: /dflybsd-src/sys/vfs/hammer/hammer_mirror.c (revision dd94f1b1ad357fec1cb4404c99bb7ed9ba6460d1)
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