blob: 960c9114f6d348b959af129e343d251b82e929c7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3 */
4
5/*
6 * Written by Anatoly P. Pinchuk pap@namesys.botik.ru
7 * Programm System Institute
8 * Pereslavl-Zalessky Russia
9 */
10
11/*
12 * This file contains functions dealing with S+tree
13 *
14 * B_IS_IN_TREE
15 * copy_item_head
16 * comp_short_keys
17 * comp_keys
18 * comp_short_le_keys
19 * le_key2cpu_key
20 * comp_le_keys
21 * bin_search
22 * get_lkey
23 * get_rkey
24 * key_in_buffer
25 * decrement_bcount
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 * reiserfs_check_path
27 * pathrelse_and_restore
28 * pathrelse
29 * search_by_key_reada
30 * search_by_key
31 * search_for_position_by_key
32 * comp_items
33 * prepare_for_direct_item
34 * prepare_for_direntry_item
35 * prepare_for_delete_or_cut
36 * calc_deleted_bytes_number
37 * init_tb_struct
38 * padd_item
39 * reiserfs_delete_item
40 * reiserfs_delete_solid_item
41 * reiserfs_delete_object
42 * maybe_indirect_to_direct
43 * indirect_to_direct_roll_back
44 * reiserfs_cut_from_item
45 * truncate_directory
46 * reiserfs_do_truncate
47 * reiserfs_paste_into_item
48 * reiserfs_insert_item
49 */
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/time.h>
52#include <linux/string.h>
53#include <linux/pagemap.h>
54#include <linux/reiserfs_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <linux/buffer_head.h>
56#include <linux/quotaops.h>
57
58/* Does the buffer contain a disk block which is in the tree. */
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -040059inline int B_IS_IN_TREE(const struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060{
61
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -040062 RFALSE(B_LEVEL(bh) > MAX_HEIGHT,
63 "PAP-1010: block (%b) has too big level (%z)", bh, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -040065 return (B_LEVEL(bh) != FREE_LEVEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066}
67
68//
69// to gets item head in le form
70//
Jeff Mahoneyd68caa92009-03-30 14:02:49 -040071inline void copy_item_head(struct item_head *to,
72 const struct item_head *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073{
Jeff Mahoneyd68caa92009-03-30 14:02:49 -040074 memcpy(to, from, IH_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075}
76
Linus Torvalds1da177e2005-04-16 15:20:36 -070077/* k1 is pointer to on-disk structure which is stored in little-endian
78 form. k2 is pointer to cpu variable. For key of items of the same
79 object this returns 0.
Jeff Mahoney0222e652009-03-30 14:02:44 -040080 Returns: -1 if key1 < key2
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 0 if key1 == key2
82 1 if key1 > key2 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070083inline int comp_short_keys(const struct reiserfs_key *le_key,
84 const struct cpu_key *cpu_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070086 __u32 n;
87 n = le32_to_cpu(le_key->k_dir_id);
88 if (n < cpu_key->on_disk_key.k_dir_id)
89 return -1;
90 if (n > cpu_key->on_disk_key.k_dir_id)
91 return 1;
92 n = le32_to_cpu(le_key->k_objectid);
93 if (n < cpu_key->on_disk_key.k_objectid)
94 return -1;
95 if (n > cpu_key->on_disk_key.k_objectid)
96 return 1;
97 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098}
99
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100/* k1 is pointer to on-disk structure which is stored in little-endian
101 form. k2 is pointer to cpu variable.
102 Compare keys using all 4 key fields.
103 Returns: -1 if key1 < key2 0
104 if key1 = key2 1 if key1 > key2 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700105static inline int comp_keys(const struct reiserfs_key *le_key,
106 const struct cpu_key *cpu_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700108 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700110 retval = comp_short_keys(le_key, cpu_key);
111 if (retval)
112 return retval;
113 if (le_key_k_offset(le_key_version(le_key), le_key) <
114 cpu_key_k_offset(cpu_key))
115 return -1;
116 if (le_key_k_offset(le_key_version(le_key), le_key) >
117 cpu_key_k_offset(cpu_key))
118 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700120 if (cpu_key->key_length == 3)
121 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700123 /* this part is needed only when tail conversion is in progress */
124 if (le_key_k_type(le_key_version(le_key), le_key) <
125 cpu_key_k_type(cpu_key))
126 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700128 if (le_key_k_type(le_key_version(le_key), le_key) >
129 cpu_key_k_type(cpu_key))
130 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700132 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700135inline int comp_short_le_keys(const struct reiserfs_key *key1,
136 const struct reiserfs_key *key2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400138 __u32 *k1_u32, *k2_u32;
Jeff Mahoneyee939612009-03-30 14:02:50 -0400139 int key_length = REISERFS_SHORT_KEY_LEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400141 k1_u32 = (__u32 *) key1;
142 k2_u32 = (__u32 *) key2;
Jeff Mahoneyee939612009-03-30 14:02:50 -0400143 for (; key_length--; ++k1_u32, ++k2_u32) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400144 if (le32_to_cpu(*k1_u32) < le32_to_cpu(*k2_u32))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700145 return -1;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400146 if (le32_to_cpu(*k1_u32) > le32_to_cpu(*k2_u32))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700147 return 1;
148 }
149 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150}
151
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700152inline void le_key2cpu_key(struct cpu_key *to, const struct reiserfs_key *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700154 int version;
155 to->on_disk_key.k_dir_id = le32_to_cpu(from->k_dir_id);
156 to->on_disk_key.k_objectid = le32_to_cpu(from->k_objectid);
157
158 // find out version of the key
159 version = le_key_version(from);
160 to->version = version;
161 to->on_disk_key.k_offset = le_key_k_offset(version, from);
162 to->on_disk_key.k_type = le_key_k_type(version, from);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163}
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165// this does not say which one is bigger, it only returns 1 if keys
166// are not equal, 0 otherwise
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700167inline int comp_le_keys(const struct reiserfs_key *k1,
168 const struct reiserfs_key *k2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700170 return memcmp(k1, k2, sizeof(struct reiserfs_key));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171}
172
173/**************************************************************************
174 * Binary search toolkit function *
175 * Search for an item in the array by the item key *
176 * Returns: 1 if found, 0 if not found; *
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400177 * *pos = number of the searched element if found, else the *
178 * number of the first element that is larger than key. *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 **************************************************************************/
Jeff Mahoneyee939612009-03-30 14:02:50 -0400180/* For those not familiar with binary search: lbound is the leftmost item that it
181 could be, rbound the rightmost item that it could be. We examine the item
182 halfway between lbound and rbound, and that tells us either that we can increase
183 lbound, or decrease rbound, or that we have found it, or if lbound <= rbound that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 there are no possible items, and we have not found it. With each examination we
185 cut the number of possible items it could be by one more than half rounded down,
186 or we find it. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400187static inline int bin_search(const void *key, /* Key to search for. */
188 const void *base, /* First item in the array. */
189 int num, /* Number of items in the array. */
190 int width, /* Item size in the array.
191 searched. Lest the reader be
192 confused, note that this is crafted
193 as a general function, and when it
194 is applied specifically to the array
195 of item headers in a node, width
196 is actually the item header size not
197 the item size. */
198 int *pos /* Number of the searched for element. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700199 )
200{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400201 int rbound, lbound, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Jeff Mahoneyee939612009-03-30 14:02:50 -0400203 for (j = ((rbound = num - 1) + (lbound = 0)) / 2;
204 lbound <= rbound; j = (rbound + lbound) / 2)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700205 switch (comp_keys
Jeff Mahoneyee939612009-03-30 14:02:50 -0400206 ((struct reiserfs_key *)((char *)base + j * width),
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400207 (struct cpu_key *)key)) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700208 case -1:
Jeff Mahoneyee939612009-03-30 14:02:50 -0400209 lbound = j + 1;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700210 continue;
211 case 1:
Jeff Mahoneyee939612009-03-30 14:02:50 -0400212 rbound = j - 1;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700213 continue;
214 case 0:
Jeff Mahoneyee939612009-03-30 14:02:50 -0400215 *pos = j;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700216 return ITEM_FOUND; /* Key found in the array. */
217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700219 /* bin_search did not find given key, it returns position of key,
220 that is minimal and greater than the given one. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400221 *pos = lbound;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700222 return ITEM_NOT_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
225#ifdef CONFIG_REISERFS_CHECK
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700226extern struct tree_balance *cur_tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227#endif
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229/* Minimal possible key. It is never in the tree. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700230const struct reiserfs_key MIN_KEY = { 0, 0, {{0, 0},} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232/* Maximal possible key. It is never in the tree. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700233static const struct reiserfs_key MAX_KEY = {
Al Viro3e8962b2005-05-01 08:59:18 -0700234 __constant_cpu_to_le32(0xffffffff),
235 __constant_cpu_to_le32(0xffffffff),
236 {{__constant_cpu_to_le32(0xffffffff),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700237 __constant_cpu_to_le32(0xffffffff)},}
Al Viro3e8962b2005-05-01 08:59:18 -0700238};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
241 of the path, and going upwards. We must check the path's validity at each step. If the key is not in
242 the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
243 case we return a special key, either MIN_KEY or MAX_KEY. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400244static inline const struct reiserfs_key *get_lkey(const struct treepath *chk_path,
245 const struct super_block *sb)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700246{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400247 int position, path_offset = chk_path->path_length;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400248 struct buffer_head *parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Jeff Mahoneyee939612009-03-30 14:02:50 -0400250 RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700251 "PAP-5010: invalid offset in the path");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700253 /* While not higher in path than first element. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400254 while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700256 RFALSE(!buffer_uptodate
Jeff Mahoneyee939612009-03-30 14:02:50 -0400257 (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700258 "PAP-5020: parent is not uptodate");
259
260 /* Parent at the path is not in the tree now. */
261 if (!B_IS_IN_TREE
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400262 (parent =
Jeff Mahoneyee939612009-03-30 14:02:50 -0400263 PATH_OFFSET_PBUFFER(chk_path, path_offset)))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700264 return &MAX_KEY;
265 /* Check whether position in the parent is correct. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400266 if ((position =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400267 PATH_OFFSET_POSITION(chk_path,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400268 path_offset)) >
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400269 B_NR_ITEMS(parent))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700270 return &MAX_KEY;
271 /* Check whether parent at the path really points to the child. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400272 if (B_N_CHILD_NUM(parent, position) !=
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400273 PATH_OFFSET_PBUFFER(chk_path,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400274 path_offset + 1)->b_blocknr)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700275 return &MAX_KEY;
276 /* Return delimiting key if position in the parent is not equal to zero. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400277 if (position)
278 return B_N_PDELIM_KEY(parent, position - 1);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700279 }
280 /* Return MIN_KEY if we are in the root of the buffer tree. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400281 if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400282 b_blocknr == SB_ROOT_BLOCK(sb))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700283 return &MIN_KEY;
284 return &MAX_KEY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285}
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287/* Get delimiting key of the buffer at the path and its right neighbor. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400288inline const struct reiserfs_key *get_rkey(const struct treepath *chk_path,
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400289 const struct super_block *sb)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700290{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400291 int position, path_offset = chk_path->path_length;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400292 struct buffer_head *parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
Jeff Mahoneyee939612009-03-30 14:02:50 -0400294 RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700295 "PAP-5030: invalid offset in the path");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Jeff Mahoneyee939612009-03-30 14:02:50 -0400297 while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700299 RFALSE(!buffer_uptodate
Jeff Mahoneyee939612009-03-30 14:02:50 -0400300 (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700301 "PAP-5040: parent is not uptodate");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700303 /* Parent at the path is not in the tree now. */
304 if (!B_IS_IN_TREE
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400305 (parent =
Jeff Mahoneyee939612009-03-30 14:02:50 -0400306 PATH_OFFSET_PBUFFER(chk_path, path_offset)))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700307 return &MIN_KEY;
308 /* Check whether position in the parent is correct. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400309 if ((position =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400310 PATH_OFFSET_POSITION(chk_path,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400311 path_offset)) >
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400312 B_NR_ITEMS(parent))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700313 return &MIN_KEY;
314 /* Check whether parent at the path really points to the child. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400315 if (B_N_CHILD_NUM(parent, position) !=
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400316 PATH_OFFSET_PBUFFER(chk_path,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400317 path_offset + 1)->b_blocknr)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700318 return &MIN_KEY;
319 /* Return delimiting key if position in the parent is not the last one. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400320 if (position != B_NR_ITEMS(parent))
321 return B_N_PDELIM_KEY(parent, position);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700322 }
323 /* Return MAX_KEY if we are in the root of the buffer tree. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400324 if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400325 b_blocknr == SB_ROOT_BLOCK(sb))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700326 return &MAX_KEY;
327 return &MIN_KEY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328}
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330/* Check whether a key is contained in the tree rooted from a buffer at a path. */
331/* This works by looking at the left and right delimiting keys for the buffer in the last path_element in
332 the path. These delimiting keys are stored at least one level above that buffer in the tree. If the
333 buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
334 this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400335static inline int key_in_buffer(struct treepath *chk_path, /* Path which should be checked. */
336 const struct cpu_key *key, /* Key which should be checked. */
337 struct super_block *sb
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700338 )
339{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400341 RFALSE(!key || chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET
342 || chk_path->path_length > MAX_HEIGHT,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700343 "PAP-5050: pointer to the key(%p) is NULL or invalid path length(%d)",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400344 key, chk_path->path_length);
345 RFALSE(!PATH_PLAST_BUFFER(chk_path)->b_bdev,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700346 "PAP-5060: device must not be NODEV");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400348 if (comp_keys(get_lkey(chk_path, sb), key) == 1)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700349 /* left delimiting key is bigger, that the key we look for */
350 return 0;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400351 /* if ( comp_keys(key, get_rkey(chk_path, sb)) != -1 ) */
352 if (comp_keys(get_rkey(chk_path, sb), key) != 1)
353 /* key must be less than right delimitiing key */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700354 return 0;
355 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356}
357
Josef "Jeff" Sipekfec6d052006-12-08 02:36:32 -0800358int reiserfs_check_path(struct treepath *p)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700359{
360 RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
361 "path not properly relsed");
362 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363}
364
Jeff Mahoney3cd6dbe2009-03-30 14:02:43 -0400365/* Drop the reference to each buffer in a path and restore
366 * dirty bits clean when preparing the buffer for the log.
367 * This version should only be called from fix_nodes() */
368void pathrelse_and_restore(struct super_block *sb,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400369 struct treepath *search_path)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700370{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400371 int path_offset = search_path->path_length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jeff Mahoneyee939612009-03-30 14:02:50 -0400373 RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700374 "clm-4000: invalid path offset");
375
Jeff Mahoneyee939612009-03-30 14:02:50 -0400376 while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
Jeff Mahoney3cd6dbe2009-03-30 14:02:43 -0400377 struct buffer_head *bh;
Jeff Mahoneyee939612009-03-30 14:02:50 -0400378 bh = PATH_OFFSET_PBUFFER(search_path, path_offset--);
Jeff Mahoney3cd6dbe2009-03-30 14:02:43 -0400379 reiserfs_restore_prepared_buffer(sb, bh);
380 brelse(bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700381 }
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400382 search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383}
384
Jeff Mahoney3cd6dbe2009-03-30 14:02:43 -0400385/* Drop the reference to each buffer in a path */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400386void pathrelse(struct treepath *search_path)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400388 int path_offset = search_path->path_length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Jeff Mahoneyee939612009-03-30 14:02:50 -0400390 RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700391 "PAP-5090: invalid path offset");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Jeff Mahoneyee939612009-03-30 14:02:50 -0400393 while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET)
394 brelse(PATH_OFFSET_PBUFFER(search_path, path_offset--));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400396 search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397}
398
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700399static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
400{
401 struct block_head *blkh;
402 struct item_head *ih;
403 int used_space;
404 int prev_location;
405 int i;
406 int nr;
407
408 blkh = (struct block_head *)buf;
409 if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400410 reiserfs_warning(NULL, "reiserfs-5080",
411 "this should be caught earlier");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700412 return 0;
413 }
414
415 nr = blkh_nr_item(blkh);
416 if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
417 /* item number is too big or too small */
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400418 reiserfs_warning(NULL, "reiserfs-5081",
419 "nr_item seems wrong: %z", bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700420 return 0;
421 }
422 ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
423 used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location(ih));
424 if (used_space != blocksize - blkh_free_space(blkh)) {
425 /* free space does not match to calculated amount of use space */
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400426 reiserfs_warning(NULL, "reiserfs-5082",
427 "free space seems wrong: %z", bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700428 return 0;
429 }
430 // FIXME: it is_leaf will hit performance too much - we may have
431 // return 1 here
432
433 /* check tables of item heads */
434 ih = (struct item_head *)(buf + BLKH_SIZE);
435 prev_location = blocksize;
436 for (i = 0; i < nr; i++, ih++) {
437 if (le_ih_k_type(ih) == TYPE_ANY) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400438 reiserfs_warning(NULL, "reiserfs-5083",
439 "wrong item type for item %h",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700440 ih);
441 return 0;
442 }
443 if (ih_location(ih) >= blocksize
444 || ih_location(ih) < IH_SIZE * nr) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400445 reiserfs_warning(NULL, "reiserfs-5084",
446 "item location seems wrong: %h",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700447 ih);
448 return 0;
449 }
450 if (ih_item_len(ih) < 1
451 || ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400452 reiserfs_warning(NULL, "reiserfs-5085",
453 "item length seems wrong: %h",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700454 ih);
455 return 0;
456 }
457 if (prev_location - ih_location(ih) != ih_item_len(ih)) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400458 reiserfs_warning(NULL, "reiserfs-5086",
459 "item location seems wrong "
460 "(second one): %h", ih);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700461 return 0;
462 }
463 prev_location = ih_location(ih);
464 }
465
466 // one may imagine much more checks
467 return 1;
468}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470/* returns 1 if buf looks like an internal node, 0 otherwise */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700471static int is_internal(char *buf, int blocksize, struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700473 struct block_head *blkh;
474 int nr;
475 int used_space;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700477 blkh = (struct block_head *)buf;
478 nr = blkh_level(blkh);
479 if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
480 /* this level is not possible for internal nodes */
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400481 reiserfs_warning(NULL, "reiserfs-5087",
482 "this should be caught earlier");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700483 return 0;
484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700486 nr = blkh_nr_item(blkh);
487 if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
488 /* for internal which is not root we might check min number of keys */
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400489 reiserfs_warning(NULL, "reiserfs-5088",
490 "number of key seems wrong: %z", bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700491 return 0;
492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700494 used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
495 if (used_space != blocksize - blkh_free_space(blkh)) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400496 reiserfs_warning(NULL, "reiserfs-5089",
497 "free space seems wrong: %z", bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700498 return 0;
499 }
500 // one may imagine much more checks
501 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504// make sure that bh contains formatted node of reiserfs tree of
505// 'level'-th level
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700506static int is_tree_node(struct buffer_head *bh, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700508 if (B_LEVEL(bh) != level) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400509 reiserfs_warning(NULL, "reiserfs-5090", "node level %d does "
510 "not match to the expected one %d",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700511 B_LEVEL(bh), level);
512 return 0;
513 }
514 if (level == DISK_LEAF_NODE_LEVEL)
515 return is_leaf(bh->b_data, bh->b_size, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700517 return is_internal(bh->b_data, bh->b_size, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520#define SEARCH_BY_KEY_READA 16
521
522/* The function is NOT SCHEDULE-SAFE! */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700523static void search_by_key_reada(struct super_block *s,
524 struct buffer_head **bh,
Jeff Mahoney3ee16672007-10-18 23:39:25 -0700525 b_blocknr_t *b, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700527 int i, j;
528
529 for (i = 0; i < num; i++) {
530 bh[i] = sb_getblk(s, b[i]);
531 }
Frederic Weisbecker09eb47a2009-05-08 14:21:33 +0200532 /*
533 * We are going to read some blocks on which we
534 * have a reference. It's safe, though we might be
535 * reading blocks concurrently changed if we release
536 * the lock. But it's still fine because we check later
537 * if the tree changed
538 */
539 reiserfs_write_unlock(s);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700540 for (j = 0; j < i; j++) {
541 /*
542 * note, this needs attention if we are getting rid of the BKL
543 * you have to make sure the prepared bit isn't set on this buffer
544 */
545 if (!buffer_uptodate(bh[j]))
546 ll_rw_block(READA, 1, bh + j);
547 brelse(bh[j]);
548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549}
550
551/**************************************************************************
552 * Algorithm SearchByKey *
553 * look for item in the Disk S+Tree by its key *
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400554 * Input: sb - super block *
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400555 * key - pointer to the key to search *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 * Output: ITEM_FOUND, ITEM_NOT_FOUND or IO_ERROR *
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400557 * search_path - path from the root to the needed leaf *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 **************************************************************************/
559
560/* This function fills up the path from the root to the leaf as it
561 descends the tree looking for the key. It uses reiserfs_bread to
562 try to find buffers in the cache given their block number. If it
563 does not find them in the cache it reads them from disk. For each
564 node search_by_key finds using reiserfs_bread it then uses
565 bin_search to look through that node. bin_search will find the
566 position of the block_number of the next node if it is looking
567 through an internal node. If it is looking through a leaf node
568 bin_search will find the position of the item which has key either
569 equal to given key, or which is the maximal key less than the given
570 key. search_by_key returns a path that must be checked for the
571 correctness of the top of the path but need not be checked for the
572 correctness of the bottom of the path */
573/* The function is NOT SCHEDULE-SAFE! */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400574int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to search. */
575 struct treepath *search_path,/* This structure was
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700576 allocated and initialized
577 by the calling
578 function. It is filled up
579 by this function. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400580 int stop_level /* How far down the tree to search. To
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700581 stop at leaf level - set to
582 DISK_LEAF_NODE_LEVEL */
583 )
584{
Jeff Mahoneyee939612009-03-30 14:02:50 -0400585 b_blocknr_t block_number;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700586 int expected_level;
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400587 struct buffer_head *bh;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400588 struct path_element *last_element;
Jeff Mahoneyee939612009-03-30 14:02:50 -0400589 int node_level, retval;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700590 int right_neighbor_of_leaf_node;
591 int fs_gen;
592 struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
Jeff Mahoney3ee16672007-10-18 23:39:25 -0700593 b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA];
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700594 int reada_count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyee939612009-03-30 14:02:50 -0400597 int repeat_counter = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400600 PROC_INFO_INC(sb, search_by_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700602 /* As we add each node to a path we increase its count. This means that
603 we must be careful to release all nodes in a path before we either
604 discard the path struct or re-use the path struct, as we do here. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400606 pathrelse(search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700607
608 right_neighbor_of_leaf_node = 0;
609
610 /* With each iteration of this loop we search through the items in the
611 current node, and calculate the next current node(next path element)
612 for the next iteration of this loop.. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400613 block_number = SB_ROOT_BLOCK(sb);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700614 expected_level = -1;
615 while (1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
617#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyee939612009-03-30 14:02:50 -0400618 if (!(++repeat_counter % 50000))
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400619 reiserfs_warning(sb, "PAP-5100",
Jeff Mahoney45b03d52009-03-30 14:02:21 -0400620 "%s: there were %d iterations of "
621 "while loop looking for key %K",
Jeff Mahoneyee939612009-03-30 14:02:50 -0400622 current->comm, repeat_counter,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400623 key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624#endif
625
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700626 /* prep path to have another element added to it. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400627 last_element =
628 PATH_OFFSET_PELEMENT(search_path,
629 ++search_path->path_length);
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400630 fs_gen = get_generation(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700632 /* Read the next tree node, and set the last element in the path to
633 have a pointer to it. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400634 if ((bh = last_element->pe_buffer =
Jeff Mahoneyee939612009-03-30 14:02:50 -0400635 sb_getblk(sb, block_number))) {
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400636 if (!buffer_uptodate(bh) && reada_count > 1)
Frederic Weisbecker09eb47a2009-05-08 14:21:33 +0200637 /* will unlock the write lock */
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400638 search_by_key_reada(sb, reada_bh,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700639 reada_blocks, reada_count);
Frederic Weisbecker09eb47a2009-05-08 14:21:33 +0200640 else
641 reiserfs_write_unlock(sb);
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400642 ll_rw_block(READ, 1, &bh);
643 wait_on_buffer(bh);
Frederic Weisbecker8ebc4232009-04-07 04:19:49 +0200644 reiserfs_write_lock(sb);
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400645 if (!buffer_uptodate(bh))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700646 goto io_error;
647 } else {
648 io_error:
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400649 search_path->path_length--;
650 pathrelse(search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700651 return IO_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700653 reada_count = 0;
654 if (expected_level == -1)
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400655 expected_level = SB_TREE_HEIGHT(sb);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700656 expected_level--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700658 /* It is possible that schedule occurred. We must check whether the key
659 to search is still in the tree rooted from the current buffer. If
660 not then repeat search from the root. */
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400661 if (fs_changed(fs_gen, sb) &&
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400662 (!B_IS_IN_TREE(bh) ||
663 B_LEVEL(bh) != expected_level ||
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400664 !key_in_buffer(search_path, key, sb))) {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400665 PROC_INFO_INC(sb, search_by_key_fs_changed);
666 PROC_INFO_INC(sb, search_by_key_restarted);
667 PROC_INFO_INC(sb,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700668 sbk_restarted[expected_level - 1]);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400669 pathrelse(search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700670
671 /* Get the root block number so that we can repeat the search
672 starting from the root. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400673 block_number = SB_ROOT_BLOCK(sb);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700674 expected_level = -1;
675 right_neighbor_of_leaf_node = 0;
676
677 /* repeat search from the root */
678 continue;
679 }
680
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400681 /* only check that the key is in the buffer if key is not
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700682 equal to the MAX_KEY. Latter case is only possible in
683 "finish_unfinished()" processing during mount. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400684 RFALSE(comp_keys(&MAX_KEY, key) &&
685 !key_in_buffer(search_path, key, sb),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700686 "PAP-5130: key is not in the buffer");
687#ifdef CONFIG_REISERFS_CHECK
688 if (cur_tb) {
689 print_cur_tb("5140");
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400690 reiserfs_panic(sb, "PAP-5140",
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -0400691 "schedule occurred in do_balance!");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700692 }
693#endif
694
695 // make sure, that the node contents look like a node of
696 // certain level
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400697 if (!is_tree_node(bh, expected_level)) {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400698 reiserfs_error(sb, "vs-5150",
Jeff Mahoney0030b642009-03-30 14:02:28 -0400699 "invalid format found in block %ld. "
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400700 "Fsck?", bh->b_blocknr);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400701 pathrelse(search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700702 return IO_ERROR;
703 }
704
705 /* ok, we have acquired next formatted node in the tree */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400706 node_level = B_LEVEL(bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700707
Jeff Mahoneyee939612009-03-30 14:02:50 -0400708 PROC_INFO_BH_STAT(sb, bh, node_level - 1);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700709
Jeff Mahoneyee939612009-03-30 14:02:50 -0400710 RFALSE(node_level < stop_level,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700711 "vs-5152: tree level (%d) is less than stop level (%d)",
Jeff Mahoneyee939612009-03-30 14:02:50 -0400712 node_level, stop_level);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700713
Jeff Mahoneyee939612009-03-30 14:02:50 -0400714 retval = bin_search(key, B_N_PITEM_HEAD(bh, 0),
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400715 B_NR_ITEMS(bh),
Jeff Mahoneyee939612009-03-30 14:02:50 -0400716 (node_level ==
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700717 DISK_LEAF_NODE_LEVEL) ? IH_SIZE :
718 KEY_SIZE,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400719 &(last_element->pe_position));
Jeff Mahoneyee939612009-03-30 14:02:50 -0400720 if (node_level == stop_level) {
721 return retval;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700722 }
723
724 /* we are not in the stop level */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400725 if (retval == ITEM_FOUND)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700726 /* item has been found, so we choose the pointer which is to the right of the found one */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400727 last_element->pe_position++;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700728
729 /* if item was not found we choose the position which is to
730 the left of the found item. This requires no code,
731 bin_search did it already. */
732
733 /* So we have chosen a position in the current node which is
734 an internal node. Now we calculate child block number by
735 position in the node. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400736 block_number =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400737 B_N_CHILD_NUM(bh, last_element->pe_position);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700738
739 /* if we are going to read leaf nodes, try for read ahead as well */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400740 if ((search_path->reada & PATH_READA) &&
Jeff Mahoneyee939612009-03-30 14:02:50 -0400741 node_level == DISK_LEAF_NODE_LEVEL + 1) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400742 int pos = last_element->pe_position;
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400743 int limit = B_NR_ITEMS(bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700744 struct reiserfs_key *le_key;
745
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400746 if (search_path->reada & PATH_READA_BACK)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700747 limit = 0;
748 while (reada_count < SEARCH_BY_KEY_READA) {
749 if (pos == limit)
750 break;
751 reada_blocks[reada_count++] =
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400752 B_N_CHILD_NUM(bh, pos);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400753 if (search_path->reada & PATH_READA_BACK)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700754 pos--;
755 else
756 pos++;
757
758 /*
759 * check to make sure we're in the same object
760 */
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400761 le_key = B_N_PDELIM_KEY(bh, pos);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700762 if (le32_to_cpu(le_key->k_objectid) !=
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400763 key->on_disk_key.k_objectid) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700764 break;
765 }
766 }
767 }
768 }
769}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
771/* Form the path to an item and position in this item which contains
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400772 file byte defined by key. If there is no such item
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 corresponding to the key, we point the path to the item with
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400774 maximal key less than key, and *pos_in_item is set to one
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 past the last entry/byte in the item. If searching for entry in a
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400776 directory item, and it is not found, *pos_in_item is set to one
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 entry more than the entry with maximal key which is less than the
778 sought key.
779
780 Note that if there is no entry in this same node which is one more,
781 then we point to an imaginary entry. for direct items, the
782 position is in units of bytes, for indirect items the position is
783 in units of blocknr entries, for directory items the position is in
784 units of directory entries. */
785
786/* The function is NOT SCHEDULE-SAFE! */
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400787int search_for_position_by_key(struct super_block *sb, /* Pointer to the super block. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700788 const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400789 struct treepath *search_path /* Filled up by this function. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700790 )
791{
792 struct item_head *p_le_ih; /* pointer to on-disk structure */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400793 int blk_size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700794 loff_t item_offset, offset;
795 struct reiserfs_dir_entry de;
796 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700798 /* If searching for directory entry. */
799 if (is_direntry_cpu_key(p_cpu_key))
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400800 return search_by_entry_key(sb, p_cpu_key, search_path,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700801 &de);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700803 /* If not searching for directory entry. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700805 /* If item is found. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400806 retval = search_item(sb, p_cpu_key, search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700807 if (retval == IO_ERROR)
808 return retval;
809 if (retval == ITEM_FOUND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700811 RFALSE(!ih_item_len
812 (B_N_PITEM_HEAD
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400813 (PATH_PLAST_BUFFER(search_path),
814 PATH_LAST_POSITION(search_path))),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700815 "PAP-5165: item length equals zero");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400817 pos_in_item(search_path) = 0;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700818 return POSITION_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400821 RFALSE(!PATH_LAST_POSITION(search_path),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700822 "PAP-5170: position equals zero");
823
824 /* Item is not found. Set path to the previous item. */
825 p_le_ih =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400826 B_N_PITEM_HEAD(PATH_PLAST_BUFFER(search_path),
827 --PATH_LAST_POSITION(search_path));
Jeff Mahoneyee939612009-03-30 14:02:50 -0400828 blk_size = sb->s_blocksize;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700829
830 if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
831 return FILE_NOT_FOUND;
832 }
833 // FIXME: quite ugly this far
834
835 item_offset = le_ih_k_offset(p_le_ih);
836 offset = cpu_key_k_offset(p_cpu_key);
837
838 /* Needed byte is contained in the item pointed to by the path. */
839 if (item_offset <= offset &&
Jeff Mahoneyee939612009-03-30 14:02:50 -0400840 item_offset + op_bytes_number(p_le_ih, blk_size) > offset) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400841 pos_in_item(search_path) = offset - item_offset;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700842 if (is_indirect_le_ih(p_le_ih)) {
Jeff Mahoneyee939612009-03-30 14:02:50 -0400843 pos_in_item(search_path) /= blk_size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700844 }
845 return POSITION_FOUND;
846 }
847
848 /* Needed byte is not contained in the item pointed to by the
849 path. Set pos_in_item out of the item. */
850 if (is_indirect_le_ih(p_le_ih))
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400851 pos_in_item(search_path) =
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700852 ih_item_len(p_le_ih) / UNFM_P_SIZE;
853 else
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400854 pos_in_item(search_path) = ih_item_len(p_le_ih);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700855
856 return POSITION_NOT_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859/* Compare given item and item pointed to by the path. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400860int comp_items(const struct item_head *stored_ih, const struct treepath *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400862 struct buffer_head *bh = PATH_PLAST_BUFFER(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700863 struct item_head *ih;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700865 /* Last buffer at the path is not in the tree. */
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -0400866 if (!B_IS_IN_TREE(bh))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700867 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700869 /* Last path position is invalid. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400870 if (PATH_LAST_POSITION(path) >= B_NR_ITEMS(bh))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700871 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700873 /* we need only to know, whether it is the same item */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400874 ih = get_ih(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700875 return memcmp(stored_ih, ih, IH_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876}
877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878/* unformatted nodes are not logged anymore, ever. This is safe
879** now
880*/
881#define held_by_others(bh) (atomic_read(&(bh)->b_count) > 1)
882
883// block can not be forgotten as it is in I/O or held by someone
884#define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh)))
885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886// prepare for delete or cut of direct item
Josef "Jeff" Sipekfec6d052006-12-08 02:36:32 -0800887static inline int prepare_for_direct_item(struct treepath *path,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700888 struct item_head *le_ih,
889 struct inode *inode,
890 loff_t new_file_length, int *cut_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700892 loff_t round_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700894 if (new_file_length == max_reiserfs_offset(inode)) {
895 /* item has to be deleted */
896 *cut_size = -(IH_SIZE + ih_item_len(le_ih));
897 return M_DELETE;
898 }
899 // new file gets truncated
900 if (get_inode_item_key_version(inode) == KEY_FORMAT_3_6) {
Jeff Mahoney0222e652009-03-30 14:02:44 -0400901 //
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700902 round_len = ROUND_UP(new_file_length);
Jeff Mahoneyee939612009-03-30 14:02:50 -0400903 /* this was new_file_length < le_ih ... */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700904 if (round_len < le_ih_k_offset(le_ih)) {
905 *cut_size = -(IH_SIZE + ih_item_len(le_ih));
906 return M_DELETE; /* Delete this item. */
907 }
908 /* Calculate first position and size for cutting from item. */
909 pos_in_item(path) = round_len - (le_ih_k_offset(le_ih) - 1);
910 *cut_size = -(ih_item_len(le_ih) - pos_in_item(path));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700912 return M_CUT; /* Cut from this item. */
913 }
914
915 // old file: items may have any length
916
917 if (new_file_length < le_ih_k_offset(le_ih)) {
918 *cut_size = -(IH_SIZE + ih_item_len(le_ih));
919 return M_DELETE; /* Delete this item. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 /* Calculate first position and size for cutting from item. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700922 *cut_size = -(ih_item_len(le_ih) -
923 (pos_in_item(path) =
924 new_file_length + 1 - le_ih_k_offset(le_ih)));
925 return M_CUT; /* Cut from this item. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926}
927
Josef "Jeff" Sipekfec6d052006-12-08 02:36:32 -0800928static inline int prepare_for_direntry_item(struct treepath *path,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700929 struct item_head *le_ih,
930 struct inode *inode,
931 loff_t new_file_length,
932 int *cut_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700934 if (le_ih_k_offset(le_ih) == DOT_OFFSET &&
935 new_file_length == max_reiserfs_offset(inode)) {
936 RFALSE(ih_entry_count(le_ih) != 2,
937 "PAP-5220: incorrect empty directory item (%h)", le_ih);
938 *cut_size = -(IH_SIZE + ih_item_len(le_ih));
939 return M_DELETE; /* Delete the directory item containing "." and ".." entry. */
940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700942 if (ih_entry_count(le_ih) == 1) {
943 /* Delete the directory item such as there is one record only
944 in this item */
945 *cut_size = -(IH_SIZE + ih_item_len(le_ih));
946 return M_DELETE;
947 }
948
949 /* Cut one record from the directory item. */
950 *cut_size =
951 -(DEH_SIZE +
952 entry_length(get_last_bh(path), le_ih, pos_in_item(path)));
953 return M_CUT;
954}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -0800956#define JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD (2 * JOURNAL_PER_BALANCE_CNT + 1)
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958/* If the path points to a directory or direct item, calculate mode and the size cut, for balance.
959 If the path points to an indirect item, remove some number of its unformatted nodes.
960 In case of file truncate calculate whether this item must be deleted/truncated or last
961 unformatted node of this item will be converted to a direct item.
962 This function returns a determination of what balance mode the calling function should employ. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400963static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, const struct cpu_key *item_key, int *removed, /* Number of unformatted nodes which were removed
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700964 from end of the file. */
Jeff Mahoneyee939612009-03-30 14:02:50 -0400965 int *cut_size, unsigned long long new_file_length /* MAX_KEY_OFFSET in case of delete. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700966 )
967{
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400968 struct super_block *sb = inode->i_sb;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400969 struct item_head *p_le_ih = PATH_PITEM_HEAD(path);
970 struct buffer_head *bh = PATH_PLAST_BUFFER(path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700972 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700974 /* Stat_data item. */
975 if (is_statdata_le_ih(p_le_ih)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
Jeff Mahoneyee939612009-03-30 14:02:50 -0400977 RFALSE(new_file_length != max_reiserfs_offset(inode),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700978 "PAP-5210: mode must be M_DELETE");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400980 *cut_size = -(IH_SIZE + ih_item_len(p_le_ih));
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700981 return M_DELETE;
982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700984 /* Directory item. */
985 if (is_direntry_le_ih(p_le_ih))
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400986 return prepare_for_direntry_item(path, p_le_ih, inode,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400987 new_file_length,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400988 cut_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700990 /* Direct item. */
991 if (is_direct_le_ih(p_le_ih))
Jeff Mahoneyd68caa92009-03-30 14:02:49 -0400992 return prepare_for_direct_item(path, p_le_ih, inode,
Jeff Mahoneyee939612009-03-30 14:02:50 -0400993 new_file_length, cut_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700995 /* Case of an indirect item. */
996 {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -0400997 int blk_size = sb->s_blocksize;
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -0800998 struct item_head s_ih;
999 int need_re_search;
1000 int delete = 0;
1001 int result = M_CUT;
1002 int pos = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Jeff Mahoneyee939612009-03-30 14:02:50 -04001004 if ( new_file_length == max_reiserfs_offset (inode) ) {
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001005 /* prepare_for_delete_or_cut() is called by
1006 * reiserfs_delete_item() */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001007 new_file_length = 0;
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001008 delete = 1;
1009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001011 do {
1012 need_re_search = 0;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001013 *cut_size = 0;
1014 bh = PATH_PLAST_BUFFER(path);
1015 copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001016 pos = I_UNFM_NUM(&s_ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
Jeff Mahoneyee939612009-03-30 14:02:50 -04001018 while (le_ih_k_offset (&s_ih) + (pos - 1) * blk_size > new_file_length) {
Al Viro87588dd2007-07-26 17:47:03 +01001019 __le32 *unfm;
1020 __u32 block;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001022 /* Each unformatted block deletion may involve one additional
1023 * bitmap block into the transaction, thereby the initial
1024 * journal space reservation might not be enough. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001025 if (!delete && (*cut_size) != 0 &&
1026 reiserfs_transaction_free_space(th) < JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD)
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001027 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -04001029 unfm = (__le32 *)B_I_PITEM(bh, &s_ih) + pos - 1;
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001030 block = get_block_num(unfm, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001032 if (block != 0) {
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -04001033 reiserfs_prepare_for_journal(sb, bh, 1);
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001034 put_block_num(unfm, 0, 0);
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -04001035 journal_mark_dirty(th, sb, bh);
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001036 reiserfs_free_block(th, inode, block, 1);
1037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Frederic Weisbecker5e69e3a2009-04-30 23:36:33 +02001039 reiserfs_write_unlock(sb);
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001040 cond_resched();
Frederic Weisbecker5e69e3a2009-04-30 23:36:33 +02001041 reiserfs_write_lock(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001043 if (item_moved (&s_ih, path)) {
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001044 need_re_search = 1;
1045 break;
1046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001048 pos --;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001049 (*removed)++;
1050 (*cut_size) -= UNFM_P_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001052 if (pos == 0) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001053 (*cut_size) -= IH_SIZE;
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001054 result = M_DELETE;
1055 break;
1056 }
1057 }
1058 /* a trick. If the buffer has been logged, this will do nothing. If
1059 ** we've broken the loop without logging it, it will restore the
1060 ** buffer */
Jeff Mahoneyad31a4f2009-03-30 14:02:46 -04001061 reiserfs_restore_prepared_buffer(sb, bh);
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001062 } while (need_re_search &&
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001063 search_for_position_by_key(sb, item_key, path) == POSITION_FOUND);
1064 pos_in_item(path) = pos * UNFM_P_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001066 if (*cut_size == 0) {
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001067 /* Nothing were cut. maybe convert last unformatted node to the
1068 * direct item? */
1069 result = M_CONVERT;
1070 }
1071 return result;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073}
1074
1075/* Calculate number of bytes which will be deleted or cut during balance */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001076static int calc_deleted_bytes_number(struct tree_balance *tb, char mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077{
Jeff Mahoneyee939612009-03-30 14:02:50 -04001078 int del_size;
Jeff Mahoneya063ae12009-03-30 14:02:48 -04001079 struct item_head *p_le_ih = PATH_PITEM_HEAD(tb->tb_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001081 if (is_statdata_le_ih(p_le_ih))
1082 return 0;
1083
Jeff Mahoneyee939612009-03-30 14:02:50 -04001084 del_size =
1085 (mode ==
Jeff Mahoneya063ae12009-03-30 14:02:48 -04001086 M_DELETE) ? ih_item_len(p_le_ih) : -tb->insert_size[0];
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001087 if (is_direntry_le_ih(p_le_ih)) {
Jeff Mahoneyee939612009-03-30 14:02:50 -04001088 /* return EMPTY_DIR_SIZE; We delete emty directoris only.
1089 * we can't use EMPTY_DIR_SIZE, as old format dirs have a different
1090 * empty size. ick. FIXME, is this right? */
1091 return del_size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001092 }
1093
1094 if (is_indirect_le_ih(p_le_ih))
Jeff Mahoneyee939612009-03-30 14:02:50 -04001095 del_size = (del_size / UNFM_P_SIZE) *
Jeff Mahoneya063ae12009-03-30 14:02:48 -04001096 (PATH_PLAST_BUFFER(tb->tb_path)->b_size);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001097 return del_size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001098}
1099
1100static void init_tb_struct(struct reiserfs_transaction_handle *th,
Jeff Mahoneya063ae12009-03-30 14:02:48 -04001101 struct tree_balance *tb,
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001102 struct super_block *sb,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001103 struct treepath *path, int size)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001104{
1105
1106 BUG_ON(!th->t_trans_id);
1107
Jeff Mahoneya063ae12009-03-30 14:02:48 -04001108 memset(tb, '\0', sizeof(struct tree_balance));
1109 tb->transaction_handle = th;
1110 tb->tb_sb = sb;
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001111 tb->tb_path = path;
1112 PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
1113 PATH_OFFSET_POSITION(path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001114 tb->insert_size[0] = size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001115}
1116
1117void padd_item(char *item, int total_length, int length)
1118{
1119 int i;
1120
1121 for (i = total_length; i > length;)
1122 item[--i] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123}
1124
1125#ifdef REISERQUOTA_DEBUG
1126char key2type(struct reiserfs_key *ih)
1127{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001128 if (is_direntry_le_key(2, ih))
1129 return 'd';
1130 if (is_direct_le_key(2, ih))
1131 return 'D';
1132 if (is_indirect_le_key(2, ih))
1133 return 'i';
1134 if (is_statdata_le_key(2, ih))
1135 return 's';
1136 return 'u';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137}
1138
1139char head2type(struct item_head *ih)
1140{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001141 if (is_direntry_le_ih(ih))
1142 return 'd';
1143 if (is_direct_le_ih(ih))
1144 return 'D';
1145 if (is_indirect_le_ih(ih))
1146 return 'i';
1147 if (is_statdata_le_ih(ih))
1148 return 's';
1149 return 'u';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150}
1151#endif
1152
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001153/* Delete object item.
1154 * th - active transaction handle
1155 * path - path to the deleted item
1156 * item_key - key to search for the deleted item
1157 * indode - used for updating i_blocks and quotas
1158 * un_bh - NULL or unformatted node pointer
1159 */
1160int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
1161 struct treepath *path, const struct cpu_key *item_key,
1162 struct inode *inode, struct buffer_head *un_bh)
1163{
Jeff Mahoney995c7622009-03-30 14:02:47 -04001164 struct super_block *sb = inode->i_sb;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001165 struct tree_balance s_del_balance;
1166 struct item_head s_ih;
1167 struct item_head *q_ih;
1168 int quota_cut_bytes;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001169 int ret_value, del_size, removed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyee939612009-03-30 14:02:50 -04001172 char mode;
1173 int iter = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174#endif
1175
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001176 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001178 init_tb_struct(th, &s_del_balance, sb, path,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001179 0 /*size is unknown */ );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001181 while (1) {
Jeff Mahoneyee939612009-03-30 14:02:50 -04001182 removed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
1184#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyee939612009-03-30 14:02:50 -04001185 iter++;
1186 mode =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187#endif
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001188 prepare_for_delete_or_cut(th, inode, path,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001189 item_key, &removed,
1190 &del_size,
Jeff Mahoney995c7622009-03-30 14:02:47 -04001191 max_reiserfs_offset(inode));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
Jeff Mahoneyee939612009-03-30 14:02:50 -04001193 RFALSE(mode != M_DELETE, "PAP-5320: mode must be M_DELETE");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001195 copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
Jeff Mahoneyee939612009-03-30 14:02:50 -04001196 s_del_balance.insert_size[0] = del_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
Jeff Mahoneyee939612009-03-30 14:02:50 -04001198 ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);
1199 if (ret_value != REPEAT_SEARCH)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001200 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001202 PROC_INFO_INC(sb, delete_item_restarted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001204 // file system changed, repeat search
Jeff Mahoneyee939612009-03-30 14:02:50 -04001205 ret_value =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001206 search_for_position_by_key(sb, item_key, path);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001207 if (ret_value == IO_ERROR)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001208 break;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001209 if (ret_value == FILE_NOT_FOUND) {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001210 reiserfs_warning(sb, "vs-5340",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001211 "no items of the file %K found",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001212 item_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001213 break;
1214 }
1215 } /* while (1) */
1216
Jeff Mahoneyee939612009-03-30 14:02:50 -04001217 if (ret_value != CARRY_ON) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001218 unfix_nodes(&s_del_balance);
1219 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 }
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001221 // reiserfs_delete_item returns item length when success
Jeff Mahoneyee939612009-03-30 14:02:50 -04001222 ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001223 q_ih = get_ih(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001224 quota_cut_bytes = ih_item_len(q_ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001226 /* hack so the quota code doesn't have to guess if the file
1227 ** has a tail. On tail insert, we allocate quota for 1 unformatted node.
1228 ** We test the offset because the tail might have been
1229 ** split into multiple items, and we only want to decrement for
1230 ** the unfm node once
1231 */
Jeff Mahoney995c7622009-03-30 14:02:47 -04001232 if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(q_ih)) {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001233 if ((le_ih_k_offset(q_ih) & (sb->s_blocksize - 1)) == 1) {
1234 quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001235 } else {
1236 quota_cut_bytes = 0;
1237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001240 if (un_bh) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001241 int off;
1242 char *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001244 /* We are in direct2indirect conversion, so move tail contents
1245 to the unformatted node */
1246 /* note, we do the copy before preparing the buffer because we
1247 ** don't care about the contents of the unformatted node yet.
1248 ** the only thing we really care about is the direct item's data
1249 ** is in the unformatted node.
1250 **
1251 ** Otherwise, we would have to call reiserfs_prepare_for_journal on
1252 ** the unformatted node, which might schedule, meaning we'd have to
1253 ** loop all the way back up to the start of the while loop.
1254 **
1255 ** The unformatted node must be dirtied later on. We can't be
1256 ** sure here if the entire tail has been deleted yet.
1257 **
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001258 ** un_bh is from the page cache (all unformatted nodes are
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001259 ** from the page cache) and might be a highmem page. So, we
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001260 ** can't use un_bh->b_data.
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001261 ** -clm
1262 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001264 data = kmap_atomic(un_bh->b_page, KM_USER0);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001265 off = ((le_ih_k_offset(&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));
1266 memcpy(data + off,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001267 B_I_PITEM(PATH_PLAST_BUFFER(path), &s_ih),
Jeff Mahoneyee939612009-03-30 14:02:50 -04001268 ret_value);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001269 kunmap_atomic(data, KM_USER0);
1270 }
1271 /* Perform balancing after all resources have been collected at once. */
1272 do_balance(&s_del_balance, NULL, NULL, M_DELETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274#ifdef REISERQUOTA_DEBUG
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001275 reiserfs_debug(sb, REISERFS_DEBUG_CODE,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001276 "reiserquota delete_item(): freeing %u, id=%u type=%c",
Jeff Mahoney995c7622009-03-30 14:02:47 -04001277 quota_cut_bytes, inode->i_uid, head2type(&s_ih));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278#endif
Linus Torvaldse1c50242009-03-30 12:29:21 -07001279 vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001281 /* Return deleted body length */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001282 return ret_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283}
1284
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285/* Summary Of Mechanisms For Handling Collisions Between Processes:
1286
1287 deletion of the body of the object is performed by iput(), with the
1288 result that if multiple processes are operating on a file, the
1289 deletion of the body of the file is deferred until the last process
1290 that has an open inode performs its iput().
1291
1292 writes and truncates are protected from collisions by use of
1293 semaphores.
1294
1295 creates, linking, and mknod are protected from collisions with other
1296 processes by making the reiserfs_add_entry() the last step in the
1297 creation, and then rolling back all changes if there was a collision.
1298 - Hans
1299*/
1300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301/* this deletes item which never gets split */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001302void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
1303 struct inode *inode, struct reiserfs_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001305 struct tree_balance tb;
1306 INITIALIZE_PATH(path);
1307 int item_len = 0;
1308 int tb_init = 0;
1309 struct cpu_key cpu_key;
1310 int retval;
1311 int quota_cut_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001313 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001315 le_key2cpu_key(&cpu_key, key);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001317 while (1) {
1318 retval = search_item(th->t_super, &cpu_key, &path);
1319 if (retval == IO_ERROR) {
Jeff Mahoney0030b642009-03-30 14:02:28 -04001320 reiserfs_error(th->t_super, "vs-5350",
1321 "i/o failure occurred trying "
1322 "to delete %K", &cpu_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001323 break;
1324 }
1325 if (retval != ITEM_FOUND) {
1326 pathrelse(&path);
1327 // No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
1328 if (!
1329 ((unsigned long long)
1330 GET_HASH_VALUE(le_key_k_offset
1331 (le_key_version(key), key)) == 0
1332 && (unsigned long long)
1333 GET_GENERATION_NUMBER(le_key_k_offset
1334 (le_key_version(key),
1335 key)) == 1))
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001336 reiserfs_warning(th->t_super, "vs-5355",
1337 "%k not found", key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001338 break;
1339 }
1340 if (!tb_init) {
1341 tb_init = 1;
1342 item_len = ih_item_len(PATH_PITEM_HEAD(&path));
1343 init_tb_struct(th, &tb, th->t_super, &path,
1344 -(IH_SIZE + item_len));
1345 }
1346 quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path));
1347
1348 retval = fix_nodes(M_DELETE, &tb, NULL, NULL);
1349 if (retval == REPEAT_SEARCH) {
1350 PROC_INFO_INC(th->t_super, delete_solid_item_restarted);
1351 continue;
1352 }
1353
1354 if (retval == CARRY_ON) {
1355 do_balance(&tb, NULL, NULL, M_DELETE);
1356 if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357#ifdef REISERQUOTA_DEBUG
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001358 reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
1359 "reiserquota delete_solid_item(): freeing %u id=%u type=%c",
1360 quota_cut_bytes, inode->i_uid,
1361 key2type(key));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362#endif
Jan Kara77db4f22009-01-26 17:14:18 +01001363 vfs_dq_free_space_nodirty(inode,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001364 quota_cut_bytes);
1365 }
1366 break;
1367 }
1368 // IO_ERROR, NO_DISK_SPACE, etc
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001369 reiserfs_warning(th->t_super, "vs-5360",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001370 "could not delete %K due to fix_nodes failure",
1371 &cpu_key);
1372 unfix_nodes(&tb);
1373 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
1375
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001376 reiserfs_check_path(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377}
1378
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001379int reiserfs_delete_object(struct reiserfs_transaction_handle *th,
1380 struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001382 int err;
1383 inode->i_size = 0;
1384 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001386 /* for directory this deletes item containing "." and ".." */
1387 err =
1388 reiserfs_do_truncate(th, inode, NULL, 0 /*no timestamp updates */ );
1389 if (err)
1390 return err;
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392#if defined( USE_INODE_GENERATION_COUNTER )
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001393 if (!old_format_only(th->t_super)) {
1394 __le32 *inode_generation;
1395
1396 inode_generation =
1397 &REISERFS_SB(th->t_super)->s_rs->s_inode_generation;
Marcin Slusarz9e902df2008-04-28 02:16:20 -07001398 le32_add_cpu(inode_generation, 1);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400/* USE_INODE_GENERATION_COUNTER */
1401#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001402 reiserfs_delete_solid_item(th, inode, INODE_PKEY(inode));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001404 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001407static void unmap_buffers(struct page *page, loff_t pos)
1408{
1409 struct buffer_head *bh;
1410 struct buffer_head *head;
1411 struct buffer_head *next;
1412 unsigned long tail_index;
1413 unsigned long cur_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001415 if (page) {
1416 if (page_has_buffers(page)) {
1417 tail_index = pos & (PAGE_CACHE_SIZE - 1);
1418 cur_index = 0;
1419 head = page_buffers(page);
1420 bh = head;
1421 do {
1422 next = bh->b_this_page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001424 /* we want to unmap the buffers that contain the tail, and
1425 ** all the buffers after it (since the tail must be at the
1426 ** end of the file). We don't want to unmap file data
1427 ** before the tail, since it might be dirty and waiting to
1428 ** reach disk
1429 */
1430 cur_index += bh->b_size;
1431 if (cur_index > tail_index) {
1432 reiserfs_unmap_buffer(bh);
1433 }
1434 bh = next;
1435 } while (bh != head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438}
1439
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001440static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
Jeff Mahoney995c7622009-03-30 14:02:47 -04001441 struct inode *inode,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001442 struct page *page,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001443 struct treepath *path,
1444 const struct cpu_key *item_key,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001445 loff_t new_file_size, char *mode)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001446{
Jeff Mahoney995c7622009-03-30 14:02:47 -04001447 struct super_block *sb = inode->i_sb;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001448 int block_size = sb->s_blocksize;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001449 int cut_bytes;
1450 BUG_ON(!th->t_trans_id);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001451 BUG_ON(new_file_size != inode->i_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001453 /* the page being sent in could be NULL if there was an i/o error
1454 ** reading in the last block. The user will hit problems trying to
1455 ** read the file, but for now we just skip the indirect2direct
1456 */
Jeff Mahoney995c7622009-03-30 14:02:47 -04001457 if (atomic_read(&inode->i_count) > 1 ||
1458 !tail_has_to_be_packed(inode) ||
1459 !page || (REISERFS_I(inode)->i_flags & i_nopack_mask)) {
Jeff Mahoney0222e652009-03-30 14:02:44 -04001460 /* leave tail in an unformatted node */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001461 *mode = M_SKIP_BALANCING;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001462 cut_bytes =
Jeff Mahoneyee939612009-03-30 14:02:50 -04001463 block_size - (new_file_size & (block_size - 1));
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001464 pathrelse(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001465 return cut_bytes;
1466 }
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001467 /* Perform the conversion to a direct_item. */
1468 /* return indirect_to_direct(inode, path, item_key,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001469 new_file_size, mode); */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001470 return indirect2direct(th, inode, page, path, item_key,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001471 new_file_size, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472}
1473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474/* we did indirect_to_direct conversion. And we have inserted direct
1475 item successesfully, but there were no disk space to cut unfm
1476 pointer being converted. Therefore we have to delete inserted
1477 direct item(s) */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001478static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
Josef "Jeff" Sipekfec6d052006-12-08 02:36:32 -08001479 struct inode *inode, struct treepath *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001481 struct cpu_key tail_key;
1482 int tail_len;
1483 int removed;
1484 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001486 make_cpu_key(&tail_key, inode, inode->i_size + 1, TYPE_DIRECT, 4); // !!!!
1487 tail_key.key_length = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001489 tail_len =
1490 (cpu_key_k_offset(&tail_key) & (inode->i_sb->s_blocksize - 1)) - 1;
1491 while (tail_len) {
1492 /* look for the last byte of the tail */
1493 if (search_for_position_by_key(inode->i_sb, &tail_key, path) ==
1494 POSITION_NOT_FOUND)
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001495 reiserfs_panic(inode->i_sb, "vs-5615",
1496 "found invalid item");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001497 RFALSE(path->pos_in_item !=
1498 ih_item_len(PATH_PITEM_HEAD(path)) - 1,
1499 "vs-5616: appended bytes found");
1500 PATH_LAST_POSITION(path)--;
1501
1502 removed =
1503 reiserfs_delete_item(th, path, &tail_key, inode,
1504 NULL /*unbh not needed */ );
1505 RFALSE(removed <= 0
1506 || removed > tail_len,
1507 "vs-5617: there was tail %d bytes, removed item length %d bytes",
1508 tail_len, removed);
1509 tail_len -= removed;
1510 set_cpu_key_k_offset(&tail_key,
1511 cpu_key_k_offset(&tail_key) - removed);
1512 }
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001513 reiserfs_warning(inode->i_sb, "reiserfs-5091", "indirect_to_direct "
1514 "conversion has been rolled back due to "
1515 "lack of disk space");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001516 //mark_file_without_tail (inode);
1517 mark_inode_dirty(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518}
1519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520/* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001521int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001522 struct treepath *path,
1523 struct cpu_key *item_key,
Jeff Mahoney995c7622009-03-30 14:02:47 -04001524 struct inode *inode,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001525 struct page *page, loff_t new_file_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526{
Jeff Mahoney995c7622009-03-30 14:02:47 -04001527 struct super_block *sb = inode->i_sb;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001528 /* Every function which is going to call do_balance must first
1529 create a tree_balance structure. Then it must fill up this
1530 structure by using the init_tb_struct and fix_nodes functions.
1531 After that we can make tree balancing. */
1532 struct tree_balance s_cut_balance;
1533 struct item_head *p_le_ih;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001534 int cut_size = 0, /* Amount to be cut. */
1535 ret_value = CARRY_ON, removed = 0, /* Number of the removed unformatted nodes. */
1536 is_inode_locked = 0;
1537 char mode; /* Mode of the balance. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001538 int retval2 = -1;
1539 int quota_cut_bytes;
1540 loff_t tail_pos = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001542 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001544 init_tb_struct(th, &s_cut_balance, inode->i_sb, path,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001545 cut_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001547 /* Repeat this loop until we either cut the item without needing
1548 to balance, or we fix_nodes without schedule occurring */
1549 while (1) {
1550 /* Determine the balance mode, position of the first byte to
1551 be cut, and size to be cut. In case of the indirect item
1552 free unformatted nodes which are pointed to by the cut
1553 pointers. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Jeff Mahoneyee939612009-03-30 14:02:50 -04001555 mode =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001556 prepare_for_delete_or_cut(th, inode, path,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001557 item_key, &removed,
1558 &cut_size, new_file_size);
1559 if (mode == M_CONVERT) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001560 /* convert last unformatted node to direct item or leave
1561 tail in the unformatted node */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001562 RFALSE(ret_value != CARRY_ON,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001563 "PAP-5570: can not convert twice");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Jeff Mahoneyee939612009-03-30 14:02:50 -04001565 ret_value =
Jeff Mahoney995c7622009-03-30 14:02:47 -04001566 maybe_indirect_to_direct(th, inode, page,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001567 path, item_key,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001568 new_file_size, &mode);
1569 if (mode == M_SKIP_BALANCING)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001570 /* tail has been left in the unformatted node */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001571 return ret_value;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001572
Jeff Mahoneyee939612009-03-30 14:02:50 -04001573 is_inode_locked = 1;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001574
1575 /* removing of last unformatted node will change value we
1576 have to return to truncate. Save it */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001577 retval2 = ret_value;
1578 /*retval2 = sb->s_blocksize - (new_file_size & (sb->s_blocksize - 1)); */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001579
1580 /* So, we have performed the first part of the conversion:
1581 inserting the new direct item. Now we are removing the
1582 last unformatted node pointer. Set key to search for
1583 it. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001584 set_cpu_key_k_type(item_key, TYPE_INDIRECT);
1585 item_key->key_length = 4;
Jeff Mahoneyee939612009-03-30 14:02:50 -04001586 new_file_size -=
1587 (new_file_size & (sb->s_blocksize - 1));
1588 tail_pos = new_file_size;
1589 set_cpu_key_k_offset(item_key, new_file_size + 1);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001590 if (search_for_position_by_key
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001591 (sb, item_key,
1592 path) == POSITION_NOT_FOUND) {
1593 print_block(PATH_PLAST_BUFFER(path), 3,
1594 PATH_LAST_POSITION(path) - 1,
1595 PATH_LAST_POSITION(path) + 1);
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001596 reiserfs_panic(sb, "PAP-5580", "item to "
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001597 "convert does not exist (%K)",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001598 item_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001599 }
1600 continue;
1601 }
Jeff Mahoneyee939612009-03-30 14:02:50 -04001602 if (cut_size == 0) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001603 pathrelse(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001604 return 0;
1605 }
1606
Jeff Mahoneyee939612009-03-30 14:02:50 -04001607 s_cut_balance.insert_size[0] = cut_size;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001608
Jeff Mahoneyee939612009-03-30 14:02:50 -04001609 ret_value = fix_nodes(mode, &s_cut_balance, NULL, NULL);
1610 if (ret_value != REPEAT_SEARCH)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001611 break;
1612
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001613 PROC_INFO_INC(sb, cut_from_item_restarted);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001614
Jeff Mahoneyee939612009-03-30 14:02:50 -04001615 ret_value =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001616 search_for_position_by_key(sb, item_key, path);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001617 if (ret_value == POSITION_FOUND)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001618 continue;
1619
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001620 reiserfs_warning(sb, "PAP-5610", "item %K not found",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001621 item_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001622 unfix_nodes(&s_cut_balance);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001623 return (ret_value == IO_ERROR) ? -EIO : -ENOENT;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001624 } /* while */
1625
1626 // check fix_nodes results (IO_ERROR or NO_DISK_SPACE)
Jeff Mahoneyee939612009-03-30 14:02:50 -04001627 if (ret_value != CARRY_ON) {
1628 if (is_inode_locked) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001629 // FIXME: this seems to be not needed: we are always able
1630 // to cut item
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001631 indirect_to_direct_roll_back(th, inode, path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001632 }
Jeff Mahoneyee939612009-03-30 14:02:50 -04001633 if (ret_value == NO_DISK_SPACE)
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001634 reiserfs_warning(sb, "reiserfs-5092",
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001635 "NO_DISK_SPACE");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001636 unfix_nodes(&s_cut_balance);
1637 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
1639
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001640 /* go ahead and perform balancing */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Jeff Mahoneyee939612009-03-30 14:02:50 -04001642 RFALSE(mode == M_PASTE || mode == M_INSERT, "invalid mode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001644 /* Calculate number of bytes that need to be cut from the item. */
1645 quota_cut_bytes =
Jeff Mahoneyee939612009-03-30 14:02:50 -04001646 (mode ==
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001647 M_DELETE) ? ih_item_len(get_ih(path)) : -s_cut_balance.
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001648 insert_size[0];
1649 if (retval2 == -1)
Jeff Mahoneyee939612009-03-30 14:02:50 -04001650 ret_value = calc_deleted_bytes_number(&s_cut_balance, mode);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001651 else
Jeff Mahoneyee939612009-03-30 14:02:50 -04001652 ret_value = retval2;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001653
1654 /* For direct items, we only change the quota when deleting the last
1655 ** item.
1656 */
1657 p_le_ih = PATH_PITEM_HEAD(s_cut_balance.tb_path);
Jeff Mahoney995c7622009-03-30 14:02:47 -04001658 if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(p_le_ih)) {
Jeff Mahoneyee939612009-03-30 14:02:50 -04001659 if (mode == M_DELETE &&
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001660 (le_ih_k_offset(p_le_ih) & (sb->s_blocksize - 1)) ==
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001661 1) {
1662 // FIXME: this is to keep 3.5 happy
Jeff Mahoney995c7622009-03-30 14:02:47 -04001663 REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001664 quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001665 } else {
1666 quota_cut_bytes = 0;
1667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyee939612009-03-30 14:02:50 -04001670 if (is_inode_locked) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001671 struct item_head *le_ih =
1672 PATH_PITEM_HEAD(s_cut_balance.tb_path);
1673 /* we are going to complete indirect2direct conversion. Make
1674 sure, that we exactly remove last unformatted node pointer
1675 of the item */
1676 if (!is_indirect_le_ih(le_ih))
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001677 reiserfs_panic(sb, "vs-5652",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001678 "item must be indirect %h", le_ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Jeff Mahoneyee939612009-03-30 14:02:50 -04001680 if (mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001681 reiserfs_panic(sb, "vs-5653", "completing "
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001682 "indirect2direct conversion indirect "
1683 "item %h being deleted must be of "
1684 "4 byte long", le_ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
Jeff Mahoneyee939612009-03-30 14:02:50 -04001686 if (mode == M_CUT
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001687 && s_cut_balance.insert_size[0] != -UNFM_P_SIZE) {
Jeff Mahoneya9dd3642009-03-30 14:02:45 -04001688 reiserfs_panic(sb, "vs-5654", "can not complete "
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001689 "indirect2direct conversion of %h "
1690 "(CUT, insert_size==%d)",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001691 le_ih, s_cut_balance.insert_size[0]);
1692 }
1693 /* it would be useful to make sure, that right neighboring
1694 item is direct item of this file */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001697
Jeff Mahoneyee939612009-03-30 14:02:50 -04001698 do_balance(&s_cut_balance, NULL, NULL, mode);
1699 if (is_inode_locked) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001700 /* we've done an indirect->direct conversion. when the data block
1701 ** was freed, it was removed from the list of blocks that must
1702 ** be flushed before the transaction commits, make sure to
1703 ** unmap and invalidate it
1704 */
1705 unmap_buffers(page, tail_pos);
Jeff Mahoney995c7622009-03-30 14:02:47 -04001706 REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708#ifdef REISERQUOTA_DEBUG
Jeff Mahoney995c7622009-03-30 14:02:47 -04001709 reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001710 "reiserquota cut_from_item(): freeing %u id=%u type=%c",
Jeff Mahoney995c7622009-03-30 14:02:47 -04001711 quota_cut_bytes, inode->i_uid, '?');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712#endif
Linus Torvaldse1c50242009-03-30 12:29:21 -07001713 vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
Jeff Mahoneyee939612009-03-30 14:02:50 -04001714 return ret_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715}
1716
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001717static void truncate_directory(struct reiserfs_transaction_handle *th,
1718 struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001720 BUG_ON(!th->t_trans_id);
1721 if (inode->i_nlink)
Jeff Mahoney0030b642009-03-30 14:02:28 -04001722 reiserfs_error(inode->i_sb, "vs-5655", "link count != 0");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001724 set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), DOT_OFFSET);
1725 set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_DIRENTRY);
1726 reiserfs_delete_solid_item(th, inode, INODE_PKEY(inode));
1727 reiserfs_update_sd(th, inode);
1728 set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), SD_OFFSET);
1729 set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_STAT_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730}
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732/* Truncate file to the new size. Note, this must be called with a transaction
1733 already started */
Jeff Mahoney995c7622009-03-30 14:02:47 -04001734int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
1735 struct inode *inode, /* ->i_size contains new size */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001736 struct page *page, /* up to date for last block */
1737 int update_timestamps /* when it is called by
1738 file_release to convert
1739 the tail - no timestamps
1740 should be updated */
1741 )
1742{
1743 INITIALIZE_PATH(s_search_path); /* Path to the current object item. */
1744 struct item_head *p_le_ih; /* Pointer to an item header. */
1745 struct cpu_key s_item_key; /* Key to search for a previous file item. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001746 loff_t file_size, /* Old file size. */
1747 new_file_size; /* New file size. */
1748 int deleted; /* Number of deleted or truncated bytes. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001749 int retval;
1750 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001752 BUG_ON(!th->t_trans_id);
1753 if (!
Jeff Mahoney995c7622009-03-30 14:02:47 -04001754 (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
1755 || S_ISLNK(inode->i_mode)))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001756 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
Jeff Mahoney995c7622009-03-30 14:02:47 -04001758 if (S_ISDIR(inode->i_mode)) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001759 // deletion of directory - no need to update timestamps
Jeff Mahoney995c7622009-03-30 14:02:47 -04001760 truncate_directory(th, inode);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001761 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 }
1763
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001764 /* Get new file size. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001765 new_file_size = inode->i_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001767 // FIXME: note, that key type is unimportant here
Jeff Mahoney995c7622009-03-30 14:02:47 -04001768 make_cpu_key(&s_item_key, inode, max_reiserfs_offset(inode),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001769 TYPE_DIRECT, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001771 retval =
Jeff Mahoney995c7622009-03-30 14:02:47 -04001772 search_for_position_by_key(inode->i_sb, &s_item_key,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001773 &s_search_path);
1774 if (retval == IO_ERROR) {
Jeff Mahoney995c7622009-03-30 14:02:47 -04001775 reiserfs_error(inode->i_sb, "vs-5657",
Jeff Mahoney0030b642009-03-30 14:02:28 -04001776 "i/o failure occurred trying to truncate %K",
1777 &s_item_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001778 err = -EIO;
1779 goto out;
1780 }
1781 if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {
Jeff Mahoney995c7622009-03-30 14:02:47 -04001782 reiserfs_error(inode->i_sb, "PAP-5660",
Jeff Mahoney0030b642009-03-30 14:02:28 -04001783 "wrong result %d of search for %K", retval,
1784 &s_item_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001786 err = -EIO;
1787 goto out;
1788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001790 s_search_path.pos_in_item--;
1791
1792 /* Get real file size (total length of all file items) */
1793 p_le_ih = PATH_PITEM_HEAD(&s_search_path);
1794 if (is_statdata_le_ih(p_le_ih))
Jeff Mahoneyee939612009-03-30 14:02:50 -04001795 file_size = 0;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001796 else {
1797 loff_t offset = le_ih_k_offset(p_le_ih);
1798 int bytes =
Jeff Mahoney995c7622009-03-30 14:02:47 -04001799 op_bytes_number(p_le_ih, inode->i_sb->s_blocksize);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001800
1801 /* this may mismatch with real file size: if last direct item
1802 had no padding zeros and last unformatted node had no free
1803 space, this file would have this file size */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001804 file_size = offset + bytes - 1;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 /*
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001807 * are we doing a full truncate or delete, if so
1808 * kick in the reada code
1809 */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001810 if (new_file_size == 0)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001811 s_search_path.reada = PATH_READA | PATH_READA_BACK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Jeff Mahoneyee939612009-03-30 14:02:50 -04001813 if (file_size == 0 || file_size < new_file_size) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001814 goto update_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001817 /* Update key to search for the last file item. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001818 set_cpu_key_k_offset(&s_item_key, file_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001820 do {
1821 /* Cut or delete file item. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001822 deleted =
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001823 reiserfs_cut_from_item(th, &s_search_path, &s_item_key,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001824 inode, page, new_file_size);
1825 if (deleted < 0) {
Jeff Mahoney995c7622009-03-30 14:02:47 -04001826 reiserfs_warning(inode->i_sb, "vs-5665",
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001827 "reiserfs_cut_from_item failed");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001828 reiserfs_check_path(&s_search_path);
1829 return 0;
1830 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Jeff Mahoneyee939612009-03-30 14:02:50 -04001832 RFALSE(deleted > file_size,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001833 "PAP-5670: reiserfs_cut_from_item: too many bytes deleted: deleted %d, file_size %lu, item_key %K",
Jeff Mahoneyee939612009-03-30 14:02:50 -04001834 deleted, file_size, &s_item_key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001835
1836 /* Change key to search the last file item. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001837 file_size -= deleted;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001838
Jeff Mahoneyee939612009-03-30 14:02:50 -04001839 set_cpu_key_k_offset(&s_item_key, file_size);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001840
1841 /* While there are bytes to truncate and previous file item is presented in the tree. */
1842
1843 /*
Jeff Mahoney0222e652009-03-30 14:02:44 -04001844 ** This loop could take a really long time, and could log
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001845 ** many more blocks than a transaction can hold. So, we do a polite
1846 ** journal end here, and if the transaction needs ending, we make
1847 ** sure the file is consistent before ending the current trans
1848 ** and starting a new one
1849 */
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001850 if (journal_transaction_should_end(th, 0) ||
1851 reiserfs_transaction_free_space(th) <= JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001852 int orig_len_alloc = th->t_blocks_allocated;
Jeff Mahoney3cd6dbe2009-03-30 14:02:43 -04001853 pathrelse(&s_search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001854
1855 if (update_timestamps) {
Jeff Mahoney995c7622009-03-30 14:02:47 -04001856 inode->i_mtime = CURRENT_TIME_SEC;
1857 inode->i_ctime = CURRENT_TIME_SEC;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001858 }
Jeff Mahoney995c7622009-03-30 14:02:47 -04001859 reiserfs_update_sd(th, inode);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001860
Jeff Mahoney995c7622009-03-30 14:02:47 -04001861 err = journal_end(th, inode->i_sb, orig_len_alloc);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001862 if (err)
1863 goto out;
Jeff Mahoney995c7622009-03-30 14:02:47 -04001864 err = journal_begin(th, inode->i_sb,
Alexander Zarochentzev23f9e0f2006-03-25 03:06:57 -08001865 JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD + JOURNAL_PER_BALANCE_CNT * 4) ;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001866 if (err)
1867 goto out;
Jeff Mahoney995c7622009-03-30 14:02:47 -04001868 reiserfs_update_inode_transaction(inode);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001869 }
Jeff Mahoneyee939612009-03-30 14:02:50 -04001870 } while (file_size > ROUND_UP(new_file_size) &&
Jeff Mahoney995c7622009-03-30 14:02:47 -04001871 search_for_position_by_key(inode->i_sb, &s_item_key,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001872 &s_search_path) == POSITION_FOUND);
1873
Jeff Mahoneyee939612009-03-30 14:02:50 -04001874 RFALSE(file_size > ROUND_UP(new_file_size),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001875 "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",
Jeff Mahoneyee939612009-03-30 14:02:50 -04001876 new_file_size, file_size, s_item_key.on_disk_key.k_objectid);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001877
1878 update_and_out:
1879 if (update_timestamps) {
1880 // this is truncate, not file closing
Jeff Mahoney995c7622009-03-30 14:02:47 -04001881 inode->i_mtime = CURRENT_TIME_SEC;
1882 inode->i_ctime = CURRENT_TIME_SEC;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001883 }
Jeff Mahoney995c7622009-03-30 14:02:47 -04001884 reiserfs_update_sd(th, inode);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001885
1886 out:
1887 pathrelse(&s_search_path);
1888 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889}
1890
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891#ifdef CONFIG_REISERFS_CHECK
1892// this makes sure, that we __append__, not overwrite or add holes
Josef "Jeff" Sipekfec6d052006-12-08 02:36:32 -08001893static void check_research_for_paste(struct treepath *path,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001894 const struct cpu_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001896 struct item_head *found_ih = get_ih(path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001898 if (is_direct_le_ih(found_ih)) {
1899 if (le_ih_k_offset(found_ih) +
1900 op_bytes_number(found_ih,
1901 get_last_bh(path)->b_size) !=
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001902 cpu_key_k_offset(key)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001903 || op_bytes_number(found_ih,
1904 get_last_bh(path)->b_size) !=
1905 pos_in_item(path))
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001906 reiserfs_panic(NULL, "PAP-5720", "found direct item "
1907 "%h or position (%d) does not match "
1908 "to key %K", found_ih,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001909 pos_in_item(path), key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001910 }
1911 if (is_indirect_le_ih(found_ih)) {
1912 if (le_ih_k_offset(found_ih) +
1913 op_bytes_number(found_ih,
1914 get_last_bh(path)->b_size) !=
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001915 cpu_key_k_offset(key)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001916 || I_UNFM_NUM(found_ih) != pos_in_item(path)
1917 || get_ih_free_space(found_ih) != 0)
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001918 reiserfs_panic(NULL, "PAP-5730", "found indirect "
1919 "item (%h) or position (%d) does not "
1920 "match to key (%K)",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001921 found_ih, pos_in_item(path), key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001922 }
1923}
1924#endif /* config reiserfs check */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925
1926/* Paste bytes to the existing item. Returns bytes number pasted into the item. */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001927int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *search_path, /* Path to the pasted item. */
1928 const struct cpu_key *key, /* Key to search for the needed item. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001929 struct inode *inode, /* Inode item belongs to */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001930 const char *body, /* Pointer to the bytes to paste. */
Jeff Mahoneyee939612009-03-30 14:02:50 -04001931 int pasted_size)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001932{ /* Size of pasted bytes. */
1933 struct tree_balance s_paste_balance;
1934 int retval;
1935 int fs_gen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001937 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001939 fs_gen = get_generation(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941#ifdef REISERQUOTA_DEBUG
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001942 reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
1943 "reiserquota paste_into_item(): allocating %u id=%u type=%c",
Jeff Mahoneyee939612009-03-30 14:02:50 -04001944 pasted_size, inode->i_uid,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001945 key2type(&(key->on_disk_key)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946#endif
1947
Linus Torvaldse1c50242009-03-30 12:29:21 -07001948 if (vfs_dq_alloc_space_nodirty(inode, pasted_size)) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001949 pathrelse(search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001950 return -EDQUOT;
1951 }
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001952 init_tb_struct(th, &s_paste_balance, th->t_super, search_path,
Jeff Mahoneyee939612009-03-30 14:02:50 -04001953 pasted_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954#ifdef DISPLACE_NEW_PACKING_LOCALITIES
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001955 s_paste_balance.key = key->on_disk_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956#endif
1957
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001958 /* DQUOT_* can schedule, must check before the fix_nodes */
1959 if (fs_changed(fs_gen, inode->i_sb)) {
1960 goto search_again;
1961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001963 while ((retval =
1964 fix_nodes(M_PASTE, &s_paste_balance, NULL,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001965 body)) == REPEAT_SEARCH) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001966 search_again:
1967 /* file system changed while we were in the fix_nodes */
1968 PROC_INFO_INC(th->t_super, paste_into_item_restarted);
1969 retval =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001970 search_for_position_by_key(th->t_super, key,
1971 search_path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001972 if (retval == IO_ERROR) {
1973 retval = -EIO;
1974 goto error_out;
1975 }
1976 if (retval == POSITION_FOUND) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001977 reiserfs_warning(inode->i_sb, "PAP-5710",
1978 "entry or pasted byte (%K) exists",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001979 key);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001980 retval = -EEXIST;
1981 goto error_out;
1982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001984 check_research_for_paste(search_path, key);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001988 /* Perform balancing after all resources are collected by fix_nodes, and
1989 accessing them will not risk triggering schedule. */
1990 if (retval == CARRY_ON) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04001991 do_balance(&s_paste_balance, NULL /*ih */ , body, M_PASTE);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001992 return 0;
1993 }
1994 retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
1995 error_out:
1996 /* this also releases the path */
1997 unfix_nodes(&s_paste_balance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998#ifdef REISERQUOTA_DEBUG
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001999 reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
2000 "reiserquota paste_into_item(): freeing %u id=%u type=%c",
Jeff Mahoneyee939612009-03-30 14:02:50 -04002001 pasted_size, inode->i_uid,
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002002 key2type(&(key->on_disk_key)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003#endif
Linus Torvaldse1c50242009-03-30 12:29:21 -07002004 vfs_dq_free_space_nodirty(inode, pasted_size);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002005 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006}
2007
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002008/* Insert new item into the buffer at the path.
2009 * th - active transaction handle
2010 * path - path to the inserted item
2011 * ih - pointer to the item header to insert
2012 * body - pointer to the bytes to insert
2013 */
2014int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
2015 struct treepath *path, const struct cpu_key *key,
2016 struct item_head *ih, struct inode *inode,
2017 const char *body)
2018{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002019 struct tree_balance s_ins_balance;
2020 int retval;
2021 int fs_gen = 0;
2022 int quota_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002024 BUG_ON(!th->t_trans_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002026 if (inode) { /* Do we count quotas for item? */
2027 fs_gen = get_generation(inode->i_sb);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002028 quota_bytes = ih_item_len(ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002030 /* hack so the quota code doesn't have to guess if the file has
2031 ** a tail, links are always tails, so there's no guessing needed
2032 */
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002033 if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(ih))
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002034 quota_bytes = inode->i_sb->s_blocksize + UNFM_P_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035#ifdef REISERQUOTA_DEBUG
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002036 reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
2037 "reiserquota insert_item(): allocating %u id=%u type=%c",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002038 quota_bytes, inode->i_uid, head2type(ih));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002040 /* We can't dirty inode here. It would be immediately written but
2041 * appropriate stat item isn't inserted yet... */
Jan Kara77db4f22009-01-26 17:14:18 +01002042 if (vfs_dq_alloc_space_nodirty(inode, quota_bytes)) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002043 pathrelse(path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002044 return -EDQUOT;
2045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 }
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002047 init_tb_struct(th, &s_ins_balance, th->t_super, path,
2048 IH_SIZE + ih_item_len(ih));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049#ifdef DISPLACE_NEW_PACKING_LOCALITIES
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002050 s_ins_balance.key = key->on_disk_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002052 /* DQUOT_* can schedule, must check to be sure calling fix_nodes is safe */
2053 if (inode && fs_changed(fs_gen, inode->i_sb)) {
2054 goto search_again;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 }
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002056
2057 while ((retval =
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002058 fix_nodes(M_INSERT, &s_ins_balance, ih,
2059 body)) == REPEAT_SEARCH) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002060 search_again:
2061 /* file system changed while we were in the fix_nodes */
2062 PROC_INFO_INC(th->t_super, insert_item_restarted);
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002063 retval = search_item(th->t_super, key, path);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002064 if (retval == IO_ERROR) {
2065 retval = -EIO;
2066 goto error_out;
2067 }
2068 if (retval == ITEM_FOUND) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04002069 reiserfs_warning(th->t_super, "PAP-5760",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002070 "key %K already exists in the tree",
2071 key);
2072 retval = -EEXIST;
2073 goto error_out;
2074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002077 /* make balancing after all resources will be collected at a time */
2078 if (retval == CARRY_ON) {
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002079 do_balance(&s_ins_balance, ih, body, M_INSERT);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002080 return 0;
2081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002083 retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
2084 error_out:
2085 /* also releases the path */
2086 unfix_nodes(&s_ins_balance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087#ifdef REISERQUOTA_DEBUG
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002088 reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
2089 "reiserquota insert_item(): freeing %u id=%u type=%c",
Jeff Mahoneyd68caa92009-03-30 14:02:49 -04002090 quota_bytes, inode->i_uid, head2type(ih));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091#endif
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002092 if (inode)
Jan Kara77db4f22009-01-26 17:14:18 +01002093 vfs_dq_free_space_nodirty(inode, quota_bytes);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07002094 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095}