Blame view
fs/reiserfs/tail_conversion.c
9.18 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 |
/* |
098297b27 reiserfs: cleanup... |
3 4 |
* Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright * details |
1da177e4c Linux-2.6.12-rc2 |
5 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 |
#include <linux/time.h> #include <linux/pagemap.h> #include <linux/buffer_head.h> |
f466c6fdb move private bits... |
9 |
#include "reiserfs.h" |
1da177e4c Linux-2.6.12-rc2 |
10 |
|
098297b27 reiserfs: cleanup... |
11 12 13 14 |
/* * access to tail : when one is going to read tail it must make sure, that is * not running. direct2indirect and indirect2direct can not run concurrently */ |
1da177e4c Linux-2.6.12-rc2 |
15 |
|
098297b27 reiserfs: cleanup... |
16 17 18 19 20 21 22 23 |
/* * Converts direct items to an unformatted node. Panics if file has no * tail. -ENOSPC if no disk space for conversion */ /* * path points to first direct item of the file regardless of how many of * them are there */ |
bd4c625c0 reiserfs: run scr... |
24 |
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, |
fec6d055d [PATCH] struct pa... |
25 |
struct treepath *path, struct buffer_head *unbh, |
bd4c625c0 reiserfs: run scr... |
26 |
loff_t tail_offset) |
1da177e4c Linux-2.6.12-rc2 |
27 |
{ |
bd4c625c0 reiserfs: run scr... |
28 29 |
struct super_block *sb = inode->i_sb; struct buffer_head *up_to_date_bh; |
4cf5f7add reiserfs: cleanup... |
30 |
struct item_head *p_le_ih = tp_item_head(path); |
bd4c625c0 reiserfs: run scr... |
31 |
unsigned long total_tail = 0; |
098297b27 reiserfs: cleanup... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/* Key to search for the last byte of the converted item. */ struct cpu_key end_key; /* * new indirect item to be inserted or key * of unfm pointer to be pasted */ struct item_head ind_ih; int blk_size; /* returned value for reiserfs_insert_item and clones */ int retval; /* Handle on an unformatted node that will be inserted in the tree. */ unp_t unfm_ptr; |
bd4c625c0 reiserfs: run scr... |
46 47 48 49 |
BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_direct2indirect++; |
ee93961be reiserfs: rename ... |
50 |
blk_size = sb->s_blocksize; |
bd4c625c0 reiserfs: run scr... |
51 |
|
098297b27 reiserfs: cleanup... |
52 53 54 55 |
/* * and key to search for append or insert pointer to the new * unformatted node. */ |
bd4c625c0 reiserfs: run scr... |
56 57 58 59 60 61 |
copy_item_head(&ind_ih, p_le_ih); set_le_ih_k_offset(&ind_ih, tail_offset); set_le_ih_k_type(&ind_ih, TYPE_INDIRECT); /* Set the key to search for the place for new unfm pointer */ make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4); |
0222e6571 reiserfs: strip t... |
62 |
/* FIXME: we could avoid this */ |
bd4c625c0 reiserfs: run scr... |
63 |
if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) { |
0030b6457 reiserfs: use rei... |
64 65 66 |
reiserfs_error(sb, "PAP-14030", "pasted or inserted byte exists in " "the tree %K. Use fsck to repair.", &end_key); |
bd4c625c0 reiserfs: run scr... |
67 68 69 |
pathrelse(path); return -EIO; } |
4cf5f7add reiserfs: cleanup... |
70 |
p_le_ih = tp_item_head(path); |
bd4c625c0 reiserfs: run scr... |
71 72 73 74 75 76 77 78 |
unfm_ptr = cpu_to_le32(unbh->b_blocknr); if (is_statdata_le_ih(p_le_ih)) { /* Insert new indirect item. */ set_ih_free_space(&ind_ih, 0); /* delete at nearest future */ put_ih_item_len(&ind_ih, UNFM_P_SIZE); PATH_LAST_POSITION(path)++; |
ee93961be reiserfs: rename ... |
79 |
retval = |
bd4c625c0 reiserfs: run scr... |
80 |
reiserfs_insert_item(th, path, &end_key, &ind_ih, inode, |
1da177e4c Linux-2.6.12-rc2 |
81 |
(char *)&unfm_ptr); |
1da177e4c Linux-2.6.12-rc2 |
82 |
} else { |
bd4c625c0 reiserfs: run scr... |
83 |
/* Paste into last indirect item of an object. */ |
ee93961be reiserfs: rename ... |
84 |
retval = reiserfs_paste_into_item(th, path, &end_key, inode, |
bd4c625c0 reiserfs: run scr... |
85 86 |
(char *)&unfm_ptr, UNFM_P_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
87 |
} |
ee93961be reiserfs: rename ... |
88 89 |
if (retval) { return retval; |
bd4c625c0 reiserfs: run scr... |
90 |
} |
098297b27 reiserfs: cleanup... |
91 92 93 94 |
/* * note: from here there are two keys which have matching first * three key components. They only differ by the fourth one. */ |
bd4c625c0 reiserfs: run scr... |
95 96 97 98 |
/* Set the key to search for the direct items of the file */ make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT, 4); |
098297b27 reiserfs: cleanup... |
99 100 101 102 |
/* * Move bytes from the direct items to the new unformatted node * and delete them. */ |
bd4c625c0 reiserfs: run scr... |
103 104 |
while (1) { int tail_size; |
098297b27 reiserfs: cleanup... |
105 106 107 108 |
/* * end_key.k_offset is set so, that we will always have found * last item of the file */ |
bd4c625c0 reiserfs: run scr... |
109 110 |
if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) |
c3a9c2109 reiserfs: rework ... |
111 |
reiserfs_panic(sb, "PAP-14050", |
bd4c625c0 reiserfs: run scr... |
112 |
"direct item (%K) not found", &end_key); |
4cf5f7add reiserfs: cleanup... |
113 |
p_le_ih = tp_item_head(path); |
bd4c625c0 reiserfs: run scr... |
114 115 116 |
RFALSE(!is_direct_le_ih(p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); |
ee93961be reiserfs: rename ... |
117 |
tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1)) |
bd4c625c0 reiserfs: run scr... |
118 |
+ ih_item_len(p_le_ih) - 1; |
098297b27 reiserfs: cleanup... |
119 120 121 122 123 124 |
/* * we only send the unbh pointer if the buffer is not * up to date. this avoids overwriting good data from * writepage() with old data from the disk or buffer cache * Special case: unbh->b_page will be NULL if we are coming * through DIRECT_IO handler here. |
bd4c625c0 reiserfs: run scr... |
125 126 127 128 129 130 131 |
*/ if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL; } else { up_to_date_bh = unbh; } |
ee93961be reiserfs: rename ... |
132 |
retval = reiserfs_delete_item(th, path, &end_key, inode, |
bd4c625c0 reiserfs: run scr... |
133 |
up_to_date_bh); |
ee93961be reiserfs: rename ... |
134 |
total_tail += retval; |
098297b27 reiserfs: cleanup... |
135 136 |
/* done: file does not have direct items anymore */ |
ee93961be reiserfs: rename ... |
137 |
if (tail_size == retval) |
bd4c625c0 reiserfs: run scr... |
138 |
break; |
1da177e4c Linux-2.6.12-rc2 |
139 |
|
bd4c625c0 reiserfs: run scr... |
140 |
} |
098297b27 reiserfs: cleanup... |
141 142 143 |
/* * if we've copied bytes from disk into the page, we need to zero * out the unused part of the block (it was not up to date before) |
bd4c625c0 reiserfs: run scr... |
144 145 146 |
*/ if (up_to_date_bh) { unsigned pgoff = |
09cbfeaf1 mm, fs: get rid o... |
147 |
(tail_offset + total_tail - 1) & (PAGE_SIZE - 1); |
883da600b reiserfs: remove ... |
148 |
char *kaddr = kmap_atomic(up_to_date_bh->b_page); |
ee93961be reiserfs: rename ... |
149 |
memset(kaddr + pgoff, 0, blk_size - total_tail); |
883da600b reiserfs: remove ... |
150 |
kunmap_atomic(kaddr); |
bd4c625c0 reiserfs: run scr... |
151 152 153 154 155 156 |
} REISERFS_I(inode)->i_first_direct_byte = U32_MAX; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
157 158 |
/* stolen from fs/buffer.c */ |
bd4c625c0 reiserfs: run scr... |
159 160 161 162 163 164 165 |
void reiserfs_unmap_buffer(struct buffer_head *bh) { lock_buffer(bh); if (buffer_journaled(bh) || buffer_journal_dirty(bh)) { BUG(); } clear_buffer_dirty(bh); |
098297b27 reiserfs: cleanup... |
166 167 168 169 170 |
/* * Remove the buffer from whatever list it belongs to. We are mostly * interested in removing it from per-sb j_dirty_buffers list, to avoid * BUG() on attempt to write not mapped buffer */ |
bd4c625c0 reiserfs: run scr... |
171 172 173 174 175 176 177 178 179 180 181 182 183 |
if ((!list_empty(&bh->b_assoc_buffers) || bh->b_private) && bh->b_page) { struct inode *inode = bh->b_page->mapping->host; struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); spin_lock(&j->j_dirty_buffers_lock); list_del_init(&bh->b_assoc_buffers); reiserfs_free_jh(bh); spin_unlock(&j->j_dirty_buffers_lock); } clear_buffer_mapped(bh); clear_buffer_req(bh); clear_buffer_new(bh); bh->b_bdev = NULL; unlock_buffer(bh); |
1da177e4c Linux-2.6.12-rc2 |
184 |
} |
098297b27 reiserfs: cleanup... |
185 186 187 188 189 190 191 192 |
/* * this first locks inode (neither reads nor sync are permitted), * reads tail through page cache, insert direct item. When direct item * inserted successfully inode is left locked. Return value is always * what we expect from it (number of cut bytes). But when tail remains * in the unformatted node, we set mode to SKIP_BALANCING and unlock * inode */ |
995c762ea reiserfs: rename ... |
193 194 |
int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *inode, struct page *page, |
d68caa953 reiserfs: rename ... |
195 196 197 198 |
struct treepath *path, /* path to the indirect item. */ const struct cpu_key *item_key, /* Key to look for * unformatted node * pointer to be cut. */ |
bd4c625c0 reiserfs: run scr... |
199 |
loff_t n_new_file_size, /* New file size. */ |
d68caa953 reiserfs: rename ... |
200 |
char *mode) |
1da177e4c Linux-2.6.12-rc2 |
201 |
{ |
995c762ea reiserfs: rename ... |
202 |
struct super_block *sb = inode->i_sb; |
bd4c625c0 reiserfs: run scr... |
203 |
struct item_head s_ih; |
ee93961be reiserfs: rename ... |
204 |
unsigned long block_size = sb->s_blocksize; |
bd4c625c0 reiserfs: run scr... |
205 206 207 208 |
char *tail; int tail_len, round_tail_len; loff_t pos, pos1; /* position of first byte of the tail */ struct cpu_key key; |
1da177e4c Linux-2.6.12-rc2 |
209 |
|
bd4c625c0 reiserfs: run scr... |
210 |
BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
211 |
|
a9dd36435 reiserfs: rename ... |
212 |
REISERFS_SB(sb)->s_indirect2direct++; |
1da177e4c Linux-2.6.12-rc2 |
213 |
|
d68caa953 reiserfs: rename ... |
214 |
*mode = M_SKIP_BALANCING; |
1da177e4c Linux-2.6.12-rc2 |
215 |
|
bd4c625c0 reiserfs: run scr... |
216 |
/* store item head path points to. */ |
4cf5f7add reiserfs: cleanup... |
217 |
copy_item_head(&s_ih, tp_item_head(path)); |
bd4c625c0 reiserfs: run scr... |
218 |
|
ee93961be reiserfs: rename ... |
219 |
tail_len = (n_new_file_size & (block_size - 1)); |
995c762ea reiserfs: rename ... |
220 |
if (get_inode_sd_version(inode) == STAT_DATA_V2) |
bd4c625c0 reiserfs: run scr... |
221 222 223 224 225 226 |
round_tail_len = ROUND_UP(tail_len); else round_tail_len = tail_len; pos = le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - |
a9dd36435 reiserfs: rename ... |
227 |
1) * sb->s_blocksize; |
bd4c625c0 reiserfs: run scr... |
228 |
pos1 = pos; |
098297b27 reiserfs: cleanup... |
229 230 231 232 233 |
/* * we are protected by i_mutex. The tail can not disapper, not * append can be done either * we are in truncate or packing tail in file_release */ |
bd4c625c0 reiserfs: run scr... |
234 235 |
tail = (char *)kmap(page); /* this can schedule */ |
d68caa953 reiserfs: rename ... |
236 |
if (path_changed(&s_ih, path)) { |
bd4c625c0 reiserfs: run scr... |
237 |
/* re-search indirect item */ |
d68caa953 reiserfs: rename ... |
238 |
if (search_for_position_by_key(sb, item_key, path) |
bd4c625c0 reiserfs: run scr... |
239 |
== POSITION_NOT_FOUND) |
a9dd36435 reiserfs: rename ... |
240 |
reiserfs_panic(sb, "PAP-5520", |
bd4c625c0 reiserfs: run scr... |
241 |
"item to be converted %K does not exist", |
d68caa953 reiserfs: rename ... |
242 |
item_key); |
4cf5f7add reiserfs: cleanup... |
243 |
copy_item_head(&s_ih, tp_item_head(path)); |
1da177e4c Linux-2.6.12-rc2 |
244 |
#ifdef CONFIG_REISERFS_CHECK |
bd4c625c0 reiserfs: run scr... |
245 246 |
pos = le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - |
a9dd36435 reiserfs: rename ... |
247 |
1) * sb->s_blocksize; |
bd4c625c0 reiserfs: run scr... |
248 |
if (pos != pos1) |
a9dd36435 reiserfs: rename ... |
249 |
reiserfs_panic(sb, "vs-5530", "tail position " |
c3a9c2109 reiserfs: rework ... |
250 |
"changed while we were reading it"); |
1da177e4c Linux-2.6.12-rc2 |
251 |
#endif |
bd4c625c0 reiserfs: run scr... |
252 |
} |
1da177e4c Linux-2.6.12-rc2 |
253 |
|
bd4c625c0 reiserfs: run scr... |
254 |
/* Set direct item header to insert. */ |
995c762ea reiserfs: rename ... |
255 |
make_le_item_head(&s_ih, NULL, get_inode_item_key_version(inode), |
bd4c625c0 reiserfs: run scr... |
256 257 |
pos1 + 1, TYPE_DIRECT, round_tail_len, 0xffff /*ih_free_space */ ); |
098297b27 reiserfs: cleanup... |
258 259 260 261 |
/* * we want a pointer to the first byte of the tail in the page. * the page was locked and this part of the page was up to date when * indirect2direct was called, so we know the bytes are still valid |
bd4c625c0 reiserfs: run scr... |
262 |
*/ |
09cbfeaf1 mm, fs: get rid o... |
263 |
tail = tail + (pos & (PAGE_SIZE - 1)); |
bd4c625c0 reiserfs: run scr... |
264 |
|
d68caa953 reiserfs: rename ... |
265 |
PATH_LAST_POSITION(path)++; |
bd4c625c0 reiserfs: run scr... |
266 |
|
d68caa953 reiserfs: rename ... |
267 |
key = *item_key; |
bd4c625c0 reiserfs: run scr... |
268 269 270 |
set_cpu_key_k_type(&key, TYPE_DIRECT); key.key_length = 4; /* Insert tail as new direct item in the tree */ |
d68caa953 reiserfs: rename ... |
271 |
if (reiserfs_insert_item(th, path, &key, &s_ih, inode, |
bd4c625c0 reiserfs: run scr... |
272 |
tail ? tail : NULL) < 0) { |
098297b27 reiserfs: cleanup... |
273 274 275 276 277 278 279 280 |
/* * No disk memory. So we can not convert last unformatted node * to the direct item. In this case we used to adjust * indirect items's ih_free_space. Now ih_free_space is not * used, it would be ideal to write zeros to corresponding * unformatted node. For now i_size is considered as guard for * going out of file size */ |
bd4c625c0 reiserfs: run scr... |
281 |
kunmap(page); |
ee93961be reiserfs: rename ... |
282 |
return block_size - round_tail_len; |
bd4c625c0 reiserfs: run scr... |
283 284 |
} kunmap(page); |
1da177e4c Linux-2.6.12-rc2 |
285 |
|
bd4c625c0 reiserfs: run scr... |
286 |
/* make sure to get the i_blocks changes from reiserfs_insert_item */ |
995c762ea reiserfs: rename ... |
287 |
reiserfs_update_sd(th, inode); |
1da177e4c Linux-2.6.12-rc2 |
288 |
|
098297b27 reiserfs: cleanup... |
289 290 291 292 293 |
/* * note: we have now the same as in above direct2indirect * conversion: there are two keys which have matching first three * key components. They only differ by the fourth one. */ |
1da177e4c Linux-2.6.12-rc2 |
294 |
|
098297b27 reiserfs: cleanup... |
295 296 297 298 |
/* * We have inserted new direct item and must remove last * unformatted node. */ |
d68caa953 reiserfs: rename ... |
299 |
*mode = M_CUT; |
1da177e4c Linux-2.6.12-rc2 |
300 |
|
bd4c625c0 reiserfs: run scr... |
301 |
/* we store position of first direct item in the in-core inode */ |
995c762ea reiserfs: rename ... |
302 303 |
/* mark_file_with_tail (inode, pos1 + 1); */ REISERFS_I(inode)->i_first_direct_byte = pos1 + 1; |
1da177e4c Linux-2.6.12-rc2 |
304 |
|
ee93961be reiserfs: rename ... |
305 |
return block_size - round_tail_len; |
bd4c625c0 reiserfs: run scr... |
306 |
} |