Don't actually panic if a journal checksum failure is detected on
[ext4-patch-queue.git] / ext4-add-ext4_ext_walk_space.patch
blobfe8834dc0c35d10464ca68563432da463c71a2cc
1 ext4: reinstate ext4_ext_walk_space()
3 From: Eric Sandeen <sandeen@redhat.com>
5 The ext4 fiemap call needs this helper function.
7 XXX Not ready for pushing --- I need to dig for the original author to
8 see what signed-off-by lines should be here.
10 ---
11 fs/ext4/ext4_extents.h | 14 ++++++
12 fs/ext4/extents.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++
13 2 files changed, 120 insertions(+)
15 Index: linux-2.6.26-rc4/fs/ext4/extents.c
16 ===================================================================
17 --- linux-2.6.26-rc4.orig/fs/ext4/extents.c 2008-05-30 11:41:30.000000000 -0700
18 +++ linux-2.6.26-rc4/fs/ext4/extents.c 2008-05-30 11:41:34.000000000 -0700
19 @@ -1619,6 +1619,112 @@ cleanup:
20 return err;
23 +int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
24 + ext4_lblk_t num, ext_prepare_callback func,
25 + void *cbdata)
27 + struct ext4_ext_path *path = NULL;
28 + struct ext4_ext_cache cbex;
29 + struct ext4_extent *ex;
30 + ext4_lblk_t next, start = 0, end = 0;
31 + ext4_lblk_t last = block + num;
32 + int depth, exists, err = 0;
34 + BUG_ON(func == NULL);
35 + BUG_ON(inode == NULL);
37 + while (block < last && block != EXT_MAX_BLOCK) {
38 + num = last - block;
39 + /* find extent for this block */
40 + path = ext4_ext_find_extent(inode, block, path);
41 + if (IS_ERR(path)) {
42 + err = PTR_ERR(path);
43 + path = NULL;
44 + break;
45 + }
47 + depth = ext_depth(inode);
48 + BUG_ON(path[depth].p_hdr == NULL);
49 + ex = path[depth].p_ext;
50 + next = ext4_ext_next_allocated_block(path);
52 + exists = 0;
53 + if (!ex) {
54 + /* there is no extent yet, so try to allocate
55 + * all requested space */
56 + start = block;
57 + end = block + num;
58 + } else if (le32_to_cpu(ex->ee_block) > block) {
59 + /* need to allocate space before found extent */
60 + start = block;
61 + end = le32_to_cpu(ex->ee_block);
62 + if (block + num < end)
63 + end = block + num;
64 + } else if (block >= le32_to_cpu(ex->ee_block)
65 + + ext4_ext_get_actual_len(ex)) {
66 + /* need to allocate space after found extent */
67 + start = block;
68 + end = block + num;
69 + if (end >= next)
70 + end = next;
71 + } else if (block >= le32_to_cpu(ex->ee_block)) {
72 + /*
73 + * some part of requested space is covered
74 + * by found extent
75 + */
76 + start = block;
77 + end = le32_to_cpu(ex->ee_block)
78 + + ext4_ext_get_actual_len(ex);
79 + if (block + num < end)
80 + end = block + num;
81 + exists = 1;
82 + } else {
83 + BUG();
84 + }
85 + BUG_ON(end <= start);
87 + if (!exists) {
88 + cbex.ec_block = start;
89 + cbex.ec_len = end - start;
90 + cbex.ec_start = 0;
91 + cbex.ec_type = EXT4_EXT_CACHE_GAP;
92 + } else {
93 + cbex.ec_block = le32_to_cpu(ex->ee_block);
94 + cbex.ec_len = ext4_ext_get_actual_len(ex);
95 + cbex.ec_start = ext_pblock(ex);
96 + cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
97 + }
99 + BUG_ON(cbex.ec_len == 0);
100 + err = func(inode, path, &cbex, cbdata);
101 + ext4_ext_drop_refs(path);
103 + if (err < 0)
104 + break;
105 + if (err == EXT_REPEAT)
106 + continue;
107 + else if (err == EXT_BREAK) {
108 + err = 0;
109 + break;
112 + if (ext_depth(inode) != depth) {
113 + /* depth was changed. we have to realloc path */
114 + kfree(path);
115 + path = NULL;
118 + block = cbex.ec_block + cbex.ec_len;
121 + if (path) {
122 + ext4_ext_drop_refs(path);
123 + kfree(path);
126 + return err;
129 static void
130 ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block,
131 __u32 len, ext4_fsblk_t start, int type)
132 Index: linux-2.6.26-rc4/fs/ext4/ext4_extents.h
133 ===================================================================
134 --- linux-2.6.26-rc4.orig/fs/ext4/ext4_extents.h 2008-05-30 11:41:30.000000000 -0700
135 +++ linux-2.6.26-rc4/fs/ext4/ext4_extents.h 2008-05-30 11:41:34.000000000 -0700
136 @@ -124,6 +124,19 @@ struct ext4_ext_path {
137 #define EXT4_EXT_CACHE_GAP 1
138 #define EXT4_EXT_CACHE_EXTENT 2
141 + * to be called by ext4_ext_walk_space()
142 + * negative retcode - error
143 + * positive retcode - signal for ext4_ext_walk_space(), see below
144 + * callback must return valid extent (passed or newly created)
145 + */
146 +typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
147 + struct ext4_ext_cache *,
148 + void *);
150 +#define EXT_CONTINUE 0
151 +#define EXT_BREAK 1
152 +#define EXT_REPEAT 2
154 #define EXT_MAX_BLOCK 0xffffffff
156 @@ -221,6 +234,7 @@ extern int ext4_ext_try_to_merge(struct
157 struct ext4_extent *);
158 extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
159 extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
160 +extern int ext4_ext_walk_space(struct inode *, ext4_lblk_t, ext4_lblk_t, ext_prepare_callback, void *);
161 extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
162 struct ext4_ext_path *);
163 extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,