Blame view

fs/reiserfs/stree.c 64.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
   *  Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   */
  
  /*
   *  Written by Anatoly P. Pinchuk pap@namesys.botik.ru
   *  Programm System Institute
   *  Pereslavl-Zalessky Russia
   */
  
  /*
   *  This file contains functions dealing with S+tree
   *
   * B_IS_IN_TREE
   * copy_item_head
   * comp_short_keys
   * comp_keys
   * comp_short_le_keys
   * le_key2cpu_key
   * comp_le_keys
   * bin_search
   * get_lkey
   * get_rkey
   * key_in_buffer
   * decrement_bcount
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   * reiserfs_check_path
   * pathrelse_and_restore
   * pathrelse
   * search_by_key_reada
   * search_by_key
   * search_for_position_by_key
   * comp_items
   * prepare_for_direct_item
   * prepare_for_direntry_item
   * prepare_for_delete_or_cut
   * calc_deleted_bytes_number
   * init_tb_struct
   * padd_item
   * reiserfs_delete_item
   * reiserfs_delete_solid_item
   * reiserfs_delete_object
   * maybe_indirect_to_direct
   * indirect_to_direct_roll_back
   * reiserfs_cut_from_item
   * truncate_directory
   * reiserfs_do_truncate
   * reiserfs_paste_into_item
   * reiserfs_insert_item
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
  #include <linux/time.h>
  #include <linux/string.h>
  #include <linux/pagemap.h>
  #include <linux/reiserfs_fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
  #include <linux/buffer_head.h>
  #include <linux/quotaops.h>
  
  /* Does the buffer contain a disk block which is in the tree. */
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
58
  inline int B_IS_IN_TREE(const struct buffer_head *bh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  {
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
60
61
  	RFALSE(B_LEVEL(bh) > MAX_HEIGHT,
  	       "PAP-1010: block (%b) has too big level (%z)", bh, bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
63
  	return (B_LEVEL(bh) != FREE_LEVEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
  }
  
  //
  // to gets item head in le form
  //
d68caa953   Jeff Mahoney   reiserfs: rename ...
69
70
  inline void copy_item_head(struct item_head *to,
  			   const struct item_head *from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  {
d68caa953   Jeff Mahoney   reiserfs: rename ...
72
  	memcpy(to, from, IH_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  /* k1 is pointer to on-disk structure which is stored in little-endian
     form. k2 is pointer to cpu variable. For key of items of the same
     object this returns 0.
0222e6571   Jeff Mahoney   reiserfs: strip t...
77
     Returns: -1 if key1 < key2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
     0 if key1 == key2
     1 if key1 > key2 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
80
81
  inline int comp_short_keys(const struct reiserfs_key *le_key,
  			   const struct cpu_key *cpu_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
83
84
85
86
87
88
89
90
91
92
93
94
  	__u32 n;
  	n = le32_to_cpu(le_key->k_dir_id);
  	if (n < cpu_key->on_disk_key.k_dir_id)
  		return -1;
  	if (n > cpu_key->on_disk_key.k_dir_id)
  		return 1;
  	n = le32_to_cpu(le_key->k_objectid);
  	if (n < cpu_key->on_disk_key.k_objectid)
  		return -1;
  	if (n > cpu_key->on_disk_key.k_objectid)
  		return 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
  /* k1 is pointer to on-disk structure which is stored in little-endian
     form. k2 is pointer to cpu variable.
     Compare keys using all 4 key fields.
     Returns: -1 if key1 < key2 0
     if key1 = key2 1 if key1 > key2 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
101
102
  static inline int comp_keys(const struct reiserfs_key *le_key,
  			    const struct cpu_key *cpu_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  	int retval;
  
  	retval = comp_short_keys(le_key, cpu_key);
  	if (retval)
  		return retval;
  	if (le_key_k_offset(le_key_version(le_key), le_key) <
  	    cpu_key_k_offset(cpu_key))
  		return -1;
  	if (le_key_k_offset(le_key_version(le_key), le_key) >
  	    cpu_key_k_offset(cpu_key))
  		return 1;
  
  	if (cpu_key->key_length == 3)
  		return 0;
  
  	/* this part is needed only when tail conversion is in progress */
  	if (le_key_k_type(le_key_version(le_key), le_key) <
  	    cpu_key_k_type(cpu_key))
  		return -1;
  
  	if (le_key_k_type(le_key_version(le_key), le_key) >
  	    cpu_key_k_type(cpu_key))
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

bd4c625c0   Linus Torvalds   reiserfs: run scr...
128
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
130
131
  inline int comp_short_le_keys(const struct reiserfs_key *key1,
  			      const struct reiserfs_key *key2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
d68caa953   Jeff Mahoney   reiserfs: rename ...
133
  	__u32 *k1_u32, *k2_u32;
ee93961be   Jeff Mahoney   reiserfs: rename ...
134
  	int key_length = REISERFS_SHORT_KEY_LEN;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
135

d68caa953   Jeff Mahoney   reiserfs: rename ...
136
137
  	k1_u32 = (__u32 *) key1;
  	k2_u32 = (__u32 *) key2;
ee93961be   Jeff Mahoney   reiserfs: rename ...
138
  	for (; key_length--; ++k1_u32, ++k2_u32) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
139
  		if (le32_to_cpu(*k1_u32) < le32_to_cpu(*k2_u32))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
140
  			return -1;
d68caa953   Jeff Mahoney   reiserfs: rename ...
141
  		if (le32_to_cpu(*k1_u32) > le32_to_cpu(*k2_u32))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
142
143
144
  			return 1;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
146
  inline void le_key2cpu_key(struct cpu_key *to, const struct reiserfs_key *from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
148
149
150
151
152
153
154
155
156
  	int version;
  	to->on_disk_key.k_dir_id = le32_to_cpu(from->k_dir_id);
  	to->on_disk_key.k_objectid = le32_to_cpu(from->k_objectid);
  
  	// find out version of the key
  	version = le_key_version(from);
  	to->version = version;
  	to->on_disk_key.k_offset = le_key_k_offset(version, from);
  	to->on_disk_key.k_type = le_key_k_type(version, from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  // this does not say which one is bigger, it only returns 1 if keys
  // are not equal, 0 otherwise
bd4c625c0   Linus Torvalds   reiserfs: run scr...
160
161
  inline int comp_le_keys(const struct reiserfs_key *k1,
  			const struct reiserfs_key *k2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
  	return memcmp(k1, k2, sizeof(struct reiserfs_key));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
  }
  
  /**************************************************************************
   *  Binary search toolkit function                                        *
   *  Search for an item in the array by the item key                       *
   *  Returns:    1 if found,  0 if not found;                              *
d68caa953   Jeff Mahoney   reiserfs: rename ...
170
171
   *        *pos = number of the searched element if found, else the        *
   *        number of the first element that is larger than key.            *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
   **************************************************************************/
ee93961be   Jeff Mahoney   reiserfs: rename ...
173
174
175
176
  /* For those not familiar with binary search: lbound is the leftmost item that it
   could be, rbound the rightmost item that it could be.  We examine the item
   halfway between lbound and rbound, and that tells us either that we can increase
   lbound, or decrease rbound, or that we have found it, or if lbound <= rbound that
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
   there are no possible items, and we have not found it. With each examination we
   cut the number of possible items it could be by one more than half rounded down,
   or we find it. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
180
181
182
183
184
185
186
187
188
189
190
191
  static inline int bin_search(const void *key,	/* Key to search for. */
  			     const void *base,	/* First item in the array. */
  			     int num,	/* Number of items in the array. */
  			     int width,	/* Item size in the array.
  					   searched. Lest the reader be
  					   confused, note that this is crafted
  					   as a general function, and when it
  					   is applied specifically to the array
  					   of item headers in a node, width
  					   is actually the item header size not
  					   the item size. */
  			     int *pos /* Number of the searched for element. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
192
193
      )
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
194
  	int rbound, lbound, j;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
195

ee93961be   Jeff Mahoney   reiserfs: rename ...
196
197
  	for (j = ((rbound = num - 1) + (lbound = 0)) / 2;
  	     lbound <= rbound; j = (rbound + lbound) / 2)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
198
  		switch (comp_keys
ee93961be   Jeff Mahoney   reiserfs: rename ...
199
  			((struct reiserfs_key *)((char *)base + j * width),
d68caa953   Jeff Mahoney   reiserfs: rename ...
200
  			 (struct cpu_key *)key)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
201
  		case -1:
ee93961be   Jeff Mahoney   reiserfs: rename ...
202
  			lbound = j + 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
203
204
  			continue;
  		case 1:
ee93961be   Jeff Mahoney   reiserfs: rename ...
205
  			rbound = j - 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
206
207
  			continue;
  		case 0:
ee93961be   Jeff Mahoney   reiserfs: rename ...
208
  			*pos = j;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
209
210
211
212
213
  			return ITEM_FOUND;	/* Key found in the array.  */
  		}
  
  	/* bin_search did not find given key, it returns position of key,
  	   that is minimal and greater than the given one. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
214
  	*pos = lbound;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
215
  	return ITEM_NOT_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  /* Minimal possible key. It is never in the tree. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
219
  const struct reiserfs_key MIN_KEY = { 0, 0, {{0, 0},} };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  
  /* Maximal possible key. It is never in the tree. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
222
  static const struct reiserfs_key MAX_KEY = {
3e8962be9   Al Viro   [PATCH] reiserfs ...
223
224
225
  	__constant_cpu_to_le32(0xffffffff),
  	__constant_cpu_to_le32(0xffffffff),
  	{{__constant_cpu_to_le32(0xffffffff),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
226
  	  __constant_cpu_to_le32(0xffffffff)},}
3e8962be9   Al Viro   [PATCH] reiserfs ...
227
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
  /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
     of the path, and going upwards.  We must check the path's validity at each step.  If the key is not in
     the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
     case we return a special key, either MIN_KEY or MAX_KEY. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
233
234
  static inline const struct reiserfs_key *get_lkey(const struct treepath *chk_path,
  						  const struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
235
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
236
  	int position, path_offset = chk_path->path_length;
d68caa953   Jeff Mahoney   reiserfs: rename ...
237
  	struct buffer_head *parent;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
238

ee93961be   Jeff Mahoney   reiserfs: rename ...
239
  	RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
240
241
242
  	       "PAP-5010: invalid offset in the path");
  
  	/* While not higher in path than first element. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
243
  	while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
244
245
  
  		RFALSE(!buffer_uptodate
ee93961be   Jeff Mahoney   reiserfs: rename ...
246
  		       (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
247
248
249
250
  		       "PAP-5020: parent is not uptodate");
  
  		/* Parent at the path is not in the tree now. */
  		if (!B_IS_IN_TREE
d68caa953   Jeff Mahoney   reiserfs: rename ...
251
  		    (parent =
ee93961be   Jeff Mahoney   reiserfs: rename ...
252
  		     PATH_OFFSET_PBUFFER(chk_path, path_offset)))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
253
254
  			return &MAX_KEY;
  		/* Check whether position in the parent is correct. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
255
  		if ((position =
d68caa953   Jeff Mahoney   reiserfs: rename ...
256
  		     PATH_OFFSET_POSITION(chk_path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
257
  					  path_offset)) >
d68caa953   Jeff Mahoney   reiserfs: rename ...
258
  		    B_NR_ITEMS(parent))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
259
260
  			return &MAX_KEY;
  		/* Check whether parent at the path really points to the child. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
261
  		if (B_N_CHILD_NUM(parent, position) !=
d68caa953   Jeff Mahoney   reiserfs: rename ...
262
  		    PATH_OFFSET_PBUFFER(chk_path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
263
  					path_offset + 1)->b_blocknr)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
264
265
  			return &MAX_KEY;
  		/* Return delimiting key if position in the parent is not equal to zero. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
266
267
  		if (position)
  			return B_N_PDELIM_KEY(parent, position - 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
268
269
  	}
  	/* Return MIN_KEY if we are in the root of the buffer tree. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
270
  	if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
a9dd36435   Jeff Mahoney   reiserfs: rename ...
271
  	    b_blocknr == SB_ROOT_BLOCK(sb))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
272
273
  		return &MIN_KEY;
  	return &MAX_KEY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  /* Get delimiting key of the buffer at the path and its right neighbor. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
276
  inline const struct reiserfs_key *get_rkey(const struct treepath *chk_path,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
277
  					   const struct super_block *sb)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
278
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
279
  	int position, path_offset = chk_path->path_length;
d68caa953   Jeff Mahoney   reiserfs: rename ...
280
  	struct buffer_head *parent;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
281

ee93961be   Jeff Mahoney   reiserfs: rename ...
282
  	RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
283
  	       "PAP-5030: invalid offset in the path");
ee93961be   Jeff Mahoney   reiserfs: rename ...
284
  	while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
285
286
  
  		RFALSE(!buffer_uptodate
ee93961be   Jeff Mahoney   reiserfs: rename ...
287
  		       (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
288
289
290
291
  		       "PAP-5040: parent is not uptodate");
  
  		/* Parent at the path is not in the tree now. */
  		if (!B_IS_IN_TREE
d68caa953   Jeff Mahoney   reiserfs: rename ...
292
  		    (parent =
ee93961be   Jeff Mahoney   reiserfs: rename ...
293
  		     PATH_OFFSET_PBUFFER(chk_path, path_offset)))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
294
295
  			return &MIN_KEY;
  		/* Check whether position in the parent is correct. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
296
  		if ((position =
d68caa953   Jeff Mahoney   reiserfs: rename ...
297
  		     PATH_OFFSET_POSITION(chk_path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
298
  					  path_offset)) >
d68caa953   Jeff Mahoney   reiserfs: rename ...
299
  		    B_NR_ITEMS(parent))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
300
301
  			return &MIN_KEY;
  		/* Check whether parent at the path really points to the child. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
302
  		if (B_N_CHILD_NUM(parent, position) !=
d68caa953   Jeff Mahoney   reiserfs: rename ...
303
  		    PATH_OFFSET_PBUFFER(chk_path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
304
  					path_offset + 1)->b_blocknr)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
305
306
  			return &MIN_KEY;
  		/* Return delimiting key if position in the parent is not the last one. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
307
308
  		if (position != B_NR_ITEMS(parent))
  			return B_N_PDELIM_KEY(parent, position);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
309
310
  	}
  	/* Return MAX_KEY if we are in the root of the buffer tree. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
311
  	if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
a9dd36435   Jeff Mahoney   reiserfs: rename ...
312
  	    b_blocknr == SB_ROOT_BLOCK(sb))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
313
314
  		return &MAX_KEY;
  	return &MIN_KEY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
  /* Check whether a key is contained in the tree rooted from a buffer at a path. */
  /* This works by looking at the left and right delimiting keys for the buffer in the last path_element in
     the path.  These delimiting keys are stored at least one level above that buffer in the tree. If the
     buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
     this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
321
322
323
  static inline int key_in_buffer(struct treepath *chk_path,	/* Path which should be checked.  */
  				const struct cpu_key *key,	/* Key which should be checked.   */
  				struct super_block *sb
bd4c625c0   Linus Torvalds   reiserfs: run scr...
324
325
      )
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326

d68caa953   Jeff Mahoney   reiserfs: rename ...
327
328
  	RFALSE(!key || chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET
  	       || chk_path->path_length > MAX_HEIGHT,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
329
  	       "PAP-5050: pointer to the key(%p) is NULL or invalid path length(%d)",
d68caa953   Jeff Mahoney   reiserfs: rename ...
330
331
  	       key, chk_path->path_length);
  	RFALSE(!PATH_PLAST_BUFFER(chk_path)->b_bdev,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
332
  	       "PAP-5060: device must not be NODEV");
d68caa953   Jeff Mahoney   reiserfs: rename ...
333
  	if (comp_keys(get_lkey(chk_path, sb), key) == 1)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
334
335
  		/* left delimiting key is bigger, that the key we look for */
  		return 0;
d68caa953   Jeff Mahoney   reiserfs: rename ...
336
337
338
  	/*  if ( comp_keys(key, get_rkey(chk_path, sb)) != -1 ) */
  	if (comp_keys(get_rkey(chk_path, sb), key) != 1)
  		/* key must be less than right delimitiing key */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
339
340
  		return 0;
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  }
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
342
  int reiserfs_check_path(struct treepath *p)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
343
344
345
346
347
  {
  	RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
  	       "path not properly relsed");
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348

3cd6dbe6f   Jeff Mahoney   reiserfs: cleanup...
349
350
351
352
  /* Drop the reference to each buffer in a path and restore
   * dirty bits clean when preparing the buffer for the log.
   * This version should only be called from fix_nodes() */
  void pathrelse_and_restore(struct super_block *sb,
d68caa953   Jeff Mahoney   reiserfs: rename ...
353
  			   struct treepath *search_path)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
354
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
355
  	int path_offset = search_path->path_length;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
356

ee93961be   Jeff Mahoney   reiserfs: rename ...
357
  	RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
358
  	       "clm-4000: invalid path offset");
ee93961be   Jeff Mahoney   reiserfs: rename ...
359
  	while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
3cd6dbe6f   Jeff Mahoney   reiserfs: cleanup...
360
  		struct buffer_head *bh;
ee93961be   Jeff Mahoney   reiserfs: rename ...
361
  		bh = PATH_OFFSET_PBUFFER(search_path, path_offset--);
3cd6dbe6f   Jeff Mahoney   reiserfs: cleanup...
362
363
  		reiserfs_restore_prepared_buffer(sb, bh);
  		brelse(bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
364
  	}
d68caa953   Jeff Mahoney   reiserfs: rename ...
365
  	search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  }
3cd6dbe6f   Jeff Mahoney   reiserfs: cleanup...
367
  /* Drop the reference to each buffer in a path */
d68caa953   Jeff Mahoney   reiserfs: rename ...
368
  void pathrelse(struct treepath *search_path)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
369
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
370
  	int path_offset = search_path->path_length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371

ee93961be   Jeff Mahoney   reiserfs: rename ...
372
  	RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
373
  	       "PAP-5090: invalid path offset");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374

ee93961be   Jeff Mahoney   reiserfs: rename ...
375
376
  	while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET)
  		brelse(PATH_OFFSET_PBUFFER(search_path, path_offset--));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377

d68caa953   Jeff Mahoney   reiserfs: rename ...
378
  	search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
379
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380

bd4c625c0   Linus Torvalds   reiserfs: run scr...
381
382
383
384
385
386
387
388
389
390
391
  static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
  {
  	struct block_head *blkh;
  	struct item_head *ih;
  	int used_space;
  	int prev_location;
  	int i;
  	int nr;
  
  	blkh = (struct block_head *)buf;
  	if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
392
393
  		reiserfs_warning(NULL, "reiserfs-5080",
  				 "this should be caught earlier");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
394
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
396
397
398
399
  
  	nr = blkh_nr_item(blkh);
  	if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
  		/* item number is too big or too small */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
400
401
  		reiserfs_warning(NULL, "reiserfs-5081",
  				 "nr_item seems wrong: %z", bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
402
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
404
405
406
407
  	ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
  	used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location(ih));
  	if (used_space != blocksize - blkh_free_space(blkh)) {
  		/* free space does not match to calculated amount of use space */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
408
409
  		reiserfs_warning(NULL, "reiserfs-5082",
  				 "free space seems wrong: %z", bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
410
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
412
413
414
415
416
417
418
419
  	// FIXME: it is_leaf will hit performance too much - we may have
  	// return 1 here
  
  	/* check tables of item heads */
  	ih = (struct item_head *)(buf + BLKH_SIZE);
  	prev_location = blocksize;
  	for (i = 0; i < nr; i++, ih++) {
  		if (le_ih_k_type(ih) == TYPE_ANY) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
420
421
  			reiserfs_warning(NULL, "reiserfs-5083",
  					 "wrong item type for item %h",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
422
423
424
425
426
  					 ih);
  			return 0;
  		}
  		if (ih_location(ih) >= blocksize
  		    || ih_location(ih) < IH_SIZE * nr) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
427
428
  			reiserfs_warning(NULL, "reiserfs-5084",
  					 "item location seems wrong: %h",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
429
430
431
432
433
  					 ih);
  			return 0;
  		}
  		if (ih_item_len(ih) < 1
  		    || ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
434
435
  			reiserfs_warning(NULL, "reiserfs-5085",
  					 "item length seems wrong: %h",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
436
437
438
439
  					 ih);
  			return 0;
  		}
  		if (prev_location - ih_location(ih) != ih_item_len(ih)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
440
441
442
  			reiserfs_warning(NULL, "reiserfs-5086",
  					 "item location seems wrong "
  					 "(second one): %h", ih);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
443
444
445
  			return 0;
  		}
  		prev_location = ih_location(ih);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447

bd4c625c0   Linus Torvalds   reiserfs: run scr...
448
449
  	// one may imagine much more checks
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  /* returns 1 if buf looks like an internal node, 0 otherwise */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
452
  static int is_internal(char *buf, int blocksize, struct buffer_head *bh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
454
455
456
457
458
459
460
461
  	struct block_head *blkh;
  	int nr;
  	int used_space;
  
  	blkh = (struct block_head *)buf;
  	nr = blkh_level(blkh);
  	if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
  		/* this level is not possible for internal nodes */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
462
463
  		reiserfs_warning(NULL, "reiserfs-5087",
  				 "this should be caught earlier");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
464
465
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466

bd4c625c0   Linus Torvalds   reiserfs: run scr...
467
468
469
  	nr = blkh_nr_item(blkh);
  	if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
  		/* for internal which is not root we might check min number of keys */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
470
471
  		reiserfs_warning(NULL, "reiserfs-5088",
  				 "number of key seems wrong: %z", bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
472
473
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

bd4c625c0   Linus Torvalds   reiserfs: run scr...
475
476
  	used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
  	if (used_space != blocksize - blkh_free_space(blkh)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
477
478
  		reiserfs_warning(NULL, "reiserfs-5089",
  				 "free space seems wrong: %z", bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
479
480
481
482
  		return 0;
  	}
  	// one may imagine much more checks
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
  // make sure that bh contains formatted node of reiserfs tree of
  // 'level'-th level
bd4c625c0   Linus Torvalds   reiserfs: run scr...
486
  static int is_tree_node(struct buffer_head *bh, int level)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
488
  	if (B_LEVEL(bh) != level) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
489
490
  		reiserfs_warning(NULL, "reiserfs-5090", "node level %d does "
  				 "not match to the expected one %d",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
491
492
493
494
495
  				 B_LEVEL(bh), level);
  		return 0;
  	}
  	if (level == DISK_LEAF_NODE_LEVEL)
  		return is_leaf(bh->b_data, bh->b_size, bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496

bd4c625c0   Linus Torvalds   reiserfs: run scr...
497
  	return is_internal(bh->b_data, bh->b_size, bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  #define SEARCH_BY_KEY_READA 16
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
500
501
502
503
504
505
506
507
508
509
510
  /*
   * The function is NOT SCHEDULE-SAFE!
   * It might unlock the write lock if we needed to wait for a block
   * to be read. Note that in this case it won't recover the lock to avoid
   * high contention resulting from too much lock requests, especially
   * the caller (search_by_key) will perform other schedule-unsafe
   * operations just after calling this function.
   *
   * @return true if we have unlocked
   */
  static bool search_by_key_reada(struct super_block *s,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
511
  				struct buffer_head **bh,
3ee166704   Jeff Mahoney   reiserfs: fix usa...
512
  				b_blocknr_t *b, int num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
514
  	int i, j;
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
515
  	bool unlocked = false;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
516
517
518
519
  
  	for (i = 0; i < num; i++) {
  		bh[i] = sb_getblk(s, b[i]);
  	}
09eb47a7c   Frederic Weisbecker   kill-the-bkl/reis...
520
521
522
523
524
525
526
  	/*
  	 * We are going to read some blocks on which we
  	 * have a reference. It's safe, though we might be
  	 * reading blocks concurrently changed if we release
  	 * the lock. But it's still fine because we check later
  	 * if the tree changed
  	 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
527
528
529
530
531
  	for (j = 0; j < i; j++) {
  		/*
  		 * note, this needs attention if we are getting rid of the BKL
  		 * you have to make sure the prepared bit isn't set on this buffer
  		 */
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
532
533
534
535
536
  		if (!buffer_uptodate(bh[j])) {
  			if (!unlocked) {
  				reiserfs_write_unlock(s);
  				unlocked = true;
  			}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
537
  			ll_rw_block(READA, 1, bh + j);
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
538
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
539
540
  		brelse(bh[j]);
  	}
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
541
  	return unlocked;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
544
545
546
  }
  
  /**************************************************************************
   * Algorithm   SearchByKey                                                *
   *             look for item in the Disk S+Tree by its key                *
a9dd36435   Jeff Mahoney   reiserfs: rename ...
547
   * Input:  sb   -  super block                                            *
d68caa953   Jeff Mahoney   reiserfs: rename ...
548
   *         key  - pointer to the key to search                            *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
   * Output: ITEM_FOUND, ITEM_NOT_FOUND or IO_ERROR                         *
d68caa953   Jeff Mahoney   reiserfs: rename ...
550
   *         search_path - path from the root to the needed leaf            *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
   **************************************************************************/
  
  /* This function fills up the path from the root to the leaf as it
     descends the tree looking for the key.  It uses reiserfs_bread to
     try to find buffers in the cache given their block number.  If it
     does not find them in the cache it reads them from disk.  For each
     node search_by_key finds using reiserfs_bread it then uses
     bin_search to look through that node.  bin_search will find the
     position of the block_number of the next node if it is looking
     through an internal node.  If it is looking through a leaf node
     bin_search will find the position of the item which has key either
     equal to given key, or which is the maximal key less than the given
     key.  search_by_key returns a path that must be checked for the
     correctness of the top of the path but need not be checked for the
     correctness of the bottom of the path */
  /* The function is NOT SCHEDULE-SAFE! */
d68caa953   Jeff Mahoney   reiserfs: rename ...
567
568
  int search_by_key(struct super_block *sb, const struct cpu_key *key,	/* Key to search. */
  		  struct treepath *search_path,/* This structure was
bd4c625c0   Linus Torvalds   reiserfs: run scr...
569
570
571
572
  						   allocated and initialized
  						   by the calling
  						   function. It is filled up
  						   by this function.  */
ee93961be   Jeff Mahoney   reiserfs: rename ...
573
  		  int stop_level	/* How far down the tree to search. To
bd4c625c0   Linus Torvalds   reiserfs: run scr...
574
575
576
577
  					   stop at leaf level - set to
  					   DISK_LEAF_NODE_LEVEL */
      )
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
578
  	b_blocknr_t block_number;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
579
  	int expected_level;
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
580
  	struct buffer_head *bh;
d68caa953   Jeff Mahoney   reiserfs: rename ...
581
  	struct path_element *last_element;
ee93961be   Jeff Mahoney   reiserfs: rename ...
582
  	int node_level, retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
583
584
585
  	int right_neighbor_of_leaf_node;
  	int fs_gen;
  	struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
3ee166704   Jeff Mahoney   reiserfs: fix usa...
586
  	b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA];
bd4c625c0   Linus Torvalds   reiserfs: run scr...
587
  	int reada_count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
  
  #ifdef CONFIG_REISERFS_CHECK
ee93961be   Jeff Mahoney   reiserfs: rename ...
590
  	int repeat_counter = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592

a9dd36435   Jeff Mahoney   reiserfs: rename ...
593
  	PROC_INFO_INC(sb, search_by_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
594
595
596
597
  
  	/* As we add each node to a path we increase its count.  This means that
  	   we must be careful to release all nodes in a path before we either
  	   discard the path struct or re-use the path struct, as we do here. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598

d68caa953   Jeff Mahoney   reiserfs: rename ...
599
  	pathrelse(search_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600

bd4c625c0   Linus Torvalds   reiserfs: run scr...
601
602
603
604
605
  	right_neighbor_of_leaf_node = 0;
  
  	/* With each iteration of this loop we search through the items in the
  	   current node, and calculate the next current node(next path element)
  	   for the next iteration of this loop.. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
606
  	block_number = SB_ROOT_BLOCK(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
607
608
  	expected_level = -1;
  	while (1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
  
  #ifdef CONFIG_REISERFS_CHECK
ee93961be   Jeff Mahoney   reiserfs: rename ...
611
  		if (!(++repeat_counter % 50000))
a9dd36435   Jeff Mahoney   reiserfs: rename ...
612
  			reiserfs_warning(sb, "PAP-5100",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
613
614
  					 "%s: there were %d iterations of "
  					 "while loop looking for key %K",
ee93961be   Jeff Mahoney   reiserfs: rename ...
615
  					 current->comm, repeat_counter,
d68caa953   Jeff Mahoney   reiserfs: rename ...
616
  					 key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
618
  		/* prep path to have another element added to it. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
619
620
621
  		last_element =
  		    PATH_OFFSET_PELEMENT(search_path,
  					 ++search_path->path_length);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
622
  		fs_gen = get_generation(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
623
624
625
  
  		/* Read the next tree node, and set the last element in the path to
  		   have a pointer to it. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
626
  		if ((bh = last_element->pe_buffer =
ee93961be   Jeff Mahoney   reiserfs: rename ...
627
  		     sb_getblk(sb, block_number))) {
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
628
  			bool unlocked = false;
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
629
  			if (!buffer_uptodate(bh) && reada_count > 1)
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
630
631
  				/* may unlock the write lock */
  				unlocked = search_by_key_reada(sb, reada_bh,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
632
  						    reada_blocks, reada_count);
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
633
634
635
636
637
638
  			/*
  			 * If we haven't already unlocked the write lock,
  			 * then we need to do that here before reading
  			 * the current block
  			 */
  			if (!buffer_uptodate(bh) && !unlocked) {
09eb47a7c   Frederic Weisbecker   kill-the-bkl/reis...
639
  				reiserfs_write_unlock(sb);
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
640
641
  				unlocked = true;
  			}
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
642
643
  			ll_rw_block(READ, 1, &bh);
  			wait_on_buffer(bh);
2ac626955   Frederic Weisbecker   kill-the-bkl/reis...
644
645
646
  
  			if (unlocked)
  				reiserfs_write_lock(sb);
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
647
  			if (!buffer_uptodate(bh))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
648
649
650
  				goto io_error;
  		} else {
  		      io_error:
d68caa953   Jeff Mahoney   reiserfs: rename ...
651
652
  			search_path->path_length--;
  			pathrelse(search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
653
654
655
656
  			return IO_ERROR;
  		}
  		reada_count = 0;
  		if (expected_level == -1)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
657
  			expected_level = SB_TREE_HEIGHT(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
658
659
660
661
662
  		expected_level--;
  
  		/* It is possible that schedule occurred. We must check whether the key
  		   to search is still in the tree rooted from the current buffer. If
  		   not then repeat search from the root. */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
663
  		if (fs_changed(fs_gen, sb) &&
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
664
665
  		    (!B_IS_IN_TREE(bh) ||
  		     B_LEVEL(bh) != expected_level ||
d68caa953   Jeff Mahoney   reiserfs: rename ...
666
  		     !key_in_buffer(search_path, key, sb))) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
667
668
669
  			PROC_INFO_INC(sb, search_by_key_fs_changed);
  			PROC_INFO_INC(sb, search_by_key_restarted);
  			PROC_INFO_INC(sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
670
  				      sbk_restarted[expected_level - 1]);
d68caa953   Jeff Mahoney   reiserfs: rename ...
671
  			pathrelse(search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
672
673
674
  
  			/* Get the root block number so that we can repeat the search
  			   starting from the root. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
675
  			block_number = SB_ROOT_BLOCK(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
676
677
678
679
680
681
  			expected_level = -1;
  			right_neighbor_of_leaf_node = 0;
  
  			/* repeat search from the root */
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682

d68caa953   Jeff Mahoney   reiserfs: rename ...
683
  		/* only check that the key is in the buffer if key is not
bd4c625c0   Linus Torvalds   reiserfs: run scr...
684
685
  		   equal to the MAX_KEY. Latter case is only possible in
  		   "finish_unfinished()" processing during mount. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
686
687
  		RFALSE(comp_keys(&MAX_KEY, key) &&
  		       !key_in_buffer(search_path, key, sb),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
688
  		       "PAP-5130: key is not in the buffer");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  #ifdef CONFIG_REISERFS_CHECK
08f14fc89   Frederic Weisbecker   kill-the-bkl/reis...
690
  		if (REISERFS_SB(sb)->cur_tb) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
691
  			print_cur_tb("5140");
a9dd36435   Jeff Mahoney   reiserfs: rename ...
692
  			reiserfs_panic(sb, "PAP-5140",
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
693
  				       "schedule occurred in do_balance!");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
694
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
696
697
  		// make sure, that the node contents look like a node of
  		// certain level
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
698
  		if (!is_tree_node(bh, expected_level)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
699
  			reiserfs_error(sb, "vs-5150",
0030b6457   Jeff Mahoney   reiserfs: use rei...
700
  				       "invalid format found in block %ld. "
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
701
  				       "Fsck?", bh->b_blocknr);
d68caa953   Jeff Mahoney   reiserfs: rename ...
702
  			pathrelse(search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
703
704
  			return IO_ERROR;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705

bd4c625c0   Linus Torvalds   reiserfs: run scr...
706
  		/* ok, we have acquired next formatted node in the tree */
ee93961be   Jeff Mahoney   reiserfs: rename ...
707
  		node_level = B_LEVEL(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708

ee93961be   Jeff Mahoney   reiserfs: rename ...
709
  		PROC_INFO_BH_STAT(sb, bh, node_level - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710

ee93961be   Jeff Mahoney   reiserfs: rename ...
711
  		RFALSE(node_level < stop_level,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
712
  		       "vs-5152: tree level (%d) is less than stop level (%d)",
ee93961be   Jeff Mahoney   reiserfs: rename ...
713
  		       node_level, stop_level);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714

ee93961be   Jeff Mahoney   reiserfs: rename ...
715
  		retval = bin_search(key, B_N_PITEM_HEAD(bh, 0),
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
716
  				      B_NR_ITEMS(bh),
ee93961be   Jeff Mahoney   reiserfs: rename ...
717
  				      (node_level ==
bd4c625c0   Linus Torvalds   reiserfs: run scr...
718
719
  				       DISK_LEAF_NODE_LEVEL) ? IH_SIZE :
  				      KEY_SIZE,
d68caa953   Jeff Mahoney   reiserfs: rename ...
720
  				      &(last_element->pe_position));
ee93961be   Jeff Mahoney   reiserfs: rename ...
721
722
  		if (node_level == stop_level) {
  			return retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
723
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724

bd4c625c0   Linus Torvalds   reiserfs: run scr...
725
  		/* we are not in the stop level */
ee93961be   Jeff Mahoney   reiserfs: rename ...
726
  		if (retval == ITEM_FOUND)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
727
  			/* item has been found, so we choose the pointer which is to the right of the found one */
d68caa953   Jeff Mahoney   reiserfs: rename ...
728
  			last_element->pe_position++;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
729
730
731
732
733
734
735
736
  
  		/* if item was not found we choose the position which is to
  		   the left of the found item. This requires no code,
  		   bin_search did it already. */
  
  		/* So we have chosen a position in the current node which is
  		   an internal node.  Now we calculate child block number by
  		   position in the node. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
737
  		block_number =
d68caa953   Jeff Mahoney   reiserfs: rename ...
738
  		    B_N_CHILD_NUM(bh, last_element->pe_position);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
739
740
  
  		/* if we are going to read leaf nodes, try for read ahead as well */
d68caa953   Jeff Mahoney   reiserfs: rename ...
741
  		if ((search_path->reada & PATH_READA) &&
ee93961be   Jeff Mahoney   reiserfs: rename ...
742
  		    node_level == DISK_LEAF_NODE_LEVEL + 1) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
743
  			int pos = last_element->pe_position;
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
744
  			int limit = B_NR_ITEMS(bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
745
  			struct reiserfs_key *le_key;
d68caa953   Jeff Mahoney   reiserfs: rename ...
746
  			if (search_path->reada & PATH_READA_BACK)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
747
748
749
750
751
  				limit = 0;
  			while (reada_count < SEARCH_BY_KEY_READA) {
  				if (pos == limit)
  					break;
  				reada_blocks[reada_count++] =
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
752
  				    B_N_CHILD_NUM(bh, pos);
d68caa953   Jeff Mahoney   reiserfs: rename ...
753
  				if (search_path->reada & PATH_READA_BACK)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
754
755
756
757
758
759
760
  					pos--;
  				else
  					pos++;
  
  				/*
  				 * check to make sure we're in the same object
  				 */
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
761
  				le_key = B_N_PDELIM_KEY(bh, pos);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
762
  				if (le32_to_cpu(le_key->k_objectid) !=
d68caa953   Jeff Mahoney   reiserfs: rename ...
763
  				    key->on_disk_key.k_objectid) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
764
765
766
  					break;
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
768
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
  /* Form the path to an item and position in this item which contains
d68caa953   Jeff Mahoney   reiserfs: rename ...
771
     file byte defined by key. If there is no such item
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
     corresponding to the key, we point the path to the item with
d68caa953   Jeff Mahoney   reiserfs: rename ...
773
     maximal key less than key, and *pos_in_item is set to one
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
     past the last entry/byte in the item.  If searching for entry in a
d68caa953   Jeff Mahoney   reiserfs: rename ...
775
     directory item, and it is not found, *pos_in_item is set to one
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
779
780
781
782
783
784
785
     entry more than the entry with maximal key which is less than the
     sought key.
  
     Note that if there is no entry in this same node which is one more,
     then we point to an imaginary entry.  for direct items, the
     position is in units of bytes, for indirect items the position is
     in units of blocknr entries, for directory items the position is in
     units of directory entries.  */
  
  /* The function is NOT SCHEDULE-SAFE! */
a9dd36435   Jeff Mahoney   reiserfs: rename ...
786
  int search_for_position_by_key(struct super_block *sb,	/* Pointer to the super block.          */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
787
  			       const struct cpu_key *p_cpu_key,	/* Key to search (cpu variable)         */
d68caa953   Jeff Mahoney   reiserfs: rename ...
788
  			       struct treepath *search_path	/* Filled up by this function.          */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
789
790
791
      )
  {
  	struct item_head *p_le_ih;	/* pointer to on-disk structure */
ee93961be   Jeff Mahoney   reiserfs: rename ...
792
  	int blk_size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
793
794
795
796
797
798
  	loff_t item_offset, offset;
  	struct reiserfs_dir_entry de;
  	int retval;
  
  	/* If searching for directory entry. */
  	if (is_direntry_cpu_key(p_cpu_key))
d68caa953   Jeff Mahoney   reiserfs: rename ...
799
  		return search_by_entry_key(sb, p_cpu_key, search_path,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
800
801
802
803
804
  					   &de);
  
  	/* If not searching for directory entry. */
  
  	/* If item is found. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
805
  	retval = search_item(sb, p_cpu_key, search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
806
807
808
  	if (retval == IO_ERROR)
  		return retval;
  	if (retval == ITEM_FOUND) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809

bd4c625c0   Linus Torvalds   reiserfs: run scr...
810
811
  		RFALSE(!ih_item_len
  		       (B_N_PITEM_HEAD
d68caa953   Jeff Mahoney   reiserfs: rename ...
812
813
  			(PATH_PLAST_BUFFER(search_path),
  			 PATH_LAST_POSITION(search_path))),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
814
  		       "PAP-5165: item length equals zero");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815

d68caa953   Jeff Mahoney   reiserfs: rename ...
816
  		pos_in_item(search_path) = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
817
818
  		return POSITION_FOUND;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819

d68caa953   Jeff Mahoney   reiserfs: rename ...
820
  	RFALSE(!PATH_LAST_POSITION(search_path),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
821
  	       "PAP-5170: position equals zero");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822

bd4c625c0   Linus Torvalds   reiserfs: run scr...
823
824
  	/* Item is not found. Set path to the previous item. */
  	p_le_ih =
d68caa953   Jeff Mahoney   reiserfs: rename ...
825
826
  	    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(search_path),
  			   --PATH_LAST_POSITION(search_path));
ee93961be   Jeff Mahoney   reiserfs: rename ...
827
  	blk_size = sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828

bd4c625c0   Linus Torvalds   reiserfs: run scr...
829
830
831
832
  	if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
  		return FILE_NOT_FOUND;
  	}
  	// FIXME: quite ugly this far
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833

bd4c625c0   Linus Torvalds   reiserfs: run scr...
834
835
  	item_offset = le_ih_k_offset(p_le_ih);
  	offset = cpu_key_k_offset(p_cpu_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836

bd4c625c0   Linus Torvalds   reiserfs: run scr...
837
838
  	/* Needed byte is contained in the item pointed to by the path. */
  	if (item_offset <= offset &&
ee93961be   Jeff Mahoney   reiserfs: rename ...
839
  	    item_offset + op_bytes_number(p_le_ih, blk_size) > offset) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
840
  		pos_in_item(search_path) = offset - item_offset;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
841
  		if (is_indirect_le_ih(p_le_ih)) {
ee93961be   Jeff Mahoney   reiserfs: rename ...
842
  			pos_in_item(search_path) /= blk_size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
843
844
  		}
  		return POSITION_FOUND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846

bd4c625c0   Linus Torvalds   reiserfs: run scr...
847
848
849
  	/* Needed byte is not contained in the item pointed to by the
  	   path. Set pos_in_item out of the item. */
  	if (is_indirect_le_ih(p_le_ih))
d68caa953   Jeff Mahoney   reiserfs: rename ...
850
  		pos_in_item(search_path) =
bd4c625c0   Linus Torvalds   reiserfs: run scr...
851
852
  		    ih_item_len(p_le_ih) / UNFM_P_SIZE;
  	else
d68caa953   Jeff Mahoney   reiserfs: rename ...
853
  		pos_in_item(search_path) = ih_item_len(p_le_ih);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
854
855
856
  
  	return POSITION_NOT_FOUND;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
  
  /* Compare given item and item pointed to by the path. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
859
  int comp_items(const struct item_head *stored_ih, const struct treepath *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  {
d68caa953   Jeff Mahoney   reiserfs: rename ...
861
  	struct buffer_head *bh = PATH_PLAST_BUFFER(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
862
  	struct item_head *ih;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863

bd4c625c0   Linus Torvalds   reiserfs: run scr...
864
  	/* Last buffer at the path is not in the tree. */
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
865
  	if (!B_IS_IN_TREE(bh))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
866
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867

bd4c625c0   Linus Torvalds   reiserfs: run scr...
868
  	/* Last path position is invalid. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
869
  	if (PATH_LAST_POSITION(path) >= B_NR_ITEMS(bh))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
870
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871

bd4c625c0   Linus Torvalds   reiserfs: run scr...
872
  	/* we need only to know, whether it is the same item */
d68caa953   Jeff Mahoney   reiserfs: rename ...
873
  	ih = get_ih(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
874
  	return memcmp(stored_ih, ih, IH_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
878
879
880
881
882
  /* unformatted nodes are not logged anymore, ever.  This is safe
  ** now
  */
  #define held_by_others(bh) (atomic_read(&(bh)->b_count) > 1)
  
  // block can not be forgotten as it is in I/O or held by someone
  #define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  // prepare for delete or cut of direct item
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
884
  static inline int prepare_for_direct_item(struct treepath *path,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
885
886
887
  					  struct item_head *le_ih,
  					  struct inode *inode,
  					  loff_t new_file_length, int *cut_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
889
890
891
892
893
894
895
896
897
  	loff_t round_len;
  
  	if (new_file_length == max_reiserfs_offset(inode)) {
  		/* item has to be deleted */
  		*cut_size = -(IH_SIZE + ih_item_len(le_ih));
  		return M_DELETE;
  	}
  	// new file gets truncated
  	if (get_inode_item_key_version(inode) == KEY_FORMAT_3_6) {
0222e6571   Jeff Mahoney   reiserfs: strip t...
898
  		//
bd4c625c0   Linus Torvalds   reiserfs: run scr...
899
  		round_len = ROUND_UP(new_file_length);
ee93961be   Jeff Mahoney   reiserfs: rename ...
900
  		/* this was new_file_length < le_ih ... */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
  		if (round_len < le_ih_k_offset(le_ih)) {
  			*cut_size = -(IH_SIZE + ih_item_len(le_ih));
  			return M_DELETE;	/* Delete this item. */
  		}
  		/* Calculate first position and size for cutting from item. */
  		pos_in_item(path) = round_len - (le_ih_k_offset(le_ih) - 1);
  		*cut_size = -(ih_item_len(le_ih) - pos_in_item(path));
  
  		return M_CUT;	/* Cut from this item. */
  	}
  
  	// old file: items may have any length
  
  	if (new_file_length < le_ih_k_offset(le_ih)) {
  		*cut_size = -(IH_SIZE + ih_item_len(le_ih));
  		return M_DELETE;	/* Delete this item. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
  	}
  	/* Calculate first position and size for cutting from item. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
919
920
921
922
  	*cut_size = -(ih_item_len(le_ih) -
  		      (pos_in_item(path) =
  		       new_file_length + 1 - le_ih_k_offset(le_ih)));
  	return M_CUT;		/* Cut from this item. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
  }
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
924
  static inline int prepare_for_direntry_item(struct treepath *path,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
925
926
927
928
  					    struct item_head *le_ih,
  					    struct inode *inode,
  					    loff_t new_file_length,
  					    int *cut_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
930
931
932
933
934
935
936
  	if (le_ih_k_offset(le_ih) == DOT_OFFSET &&
  	    new_file_length == max_reiserfs_offset(inode)) {
  		RFALSE(ih_entry_count(le_ih) != 2,
  		       "PAP-5220: incorrect empty directory item (%h)", le_ih);
  		*cut_size = -(IH_SIZE + ih_item_len(le_ih));
  		return M_DELETE;	/* Delete the directory item containing "." and ".." entry. */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937

bd4c625c0   Linus Torvalds   reiserfs: run scr...
938
939
940
941
942
943
944
945
946
947
948
949
950
  	if (ih_entry_count(le_ih) == 1) {
  		/* Delete the directory item such as there is one record only
  		   in this item */
  		*cut_size = -(IH_SIZE + ih_item_len(le_ih));
  		return M_DELETE;
  	}
  
  	/* Cut one record from the directory item. */
  	*cut_size =
  	    -(DEH_SIZE +
  	      entry_length(get_last_bh(path), le_ih, pos_in_item(path)));
  	return M_CUT;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951

23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
952
  #define JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD (2 * JOURNAL_PER_BALANCE_CNT + 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
955
956
957
  /*  If the path points to a directory or direct item, calculate mode and the size cut, for balance.
      If the path points to an indirect item, remove some number of its unformatted nodes.
      In case of file truncate calculate whether this item must be deleted/truncated or last
      unformatted node of this item will be converted to a direct item.
      This function returns a determination of what balance mode the calling function should employ. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
958
  static 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
bd4c625c0   Linus Torvalds   reiserfs: run scr...
959
  																						   from end of the file. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
960
  				      int *cut_size, unsigned long long new_file_length	/* MAX_KEY_OFFSET in case of delete. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
961
962
      )
  {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
963
  	struct super_block *sb = inode->i_sb;
d68caa953   Jeff Mahoney   reiserfs: rename ...
964
965
  	struct item_head *p_le_ih = PATH_PITEM_HEAD(path);
  	struct buffer_head *bh = PATH_PLAST_BUFFER(path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966

bd4c625c0   Linus Torvalds   reiserfs: run scr...
967
  	BUG_ON(!th->t_trans_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

bd4c625c0   Linus Torvalds   reiserfs: run scr...
969
970
  	/* Stat_data item. */
  	if (is_statdata_le_ih(p_le_ih)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971

ee93961be   Jeff Mahoney   reiserfs: rename ...
972
  		RFALSE(new_file_length != max_reiserfs_offset(inode),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
973
  		       "PAP-5210: mode must be M_DELETE");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974

d68caa953   Jeff Mahoney   reiserfs: rename ...
975
  		*cut_size = -(IH_SIZE + ih_item_len(p_le_ih));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
976
977
  		return M_DELETE;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978

bd4c625c0   Linus Torvalds   reiserfs: run scr...
979
980
  	/* Directory item. */
  	if (is_direntry_le_ih(p_le_ih))
d68caa953   Jeff Mahoney   reiserfs: rename ...
981
  		return prepare_for_direntry_item(path, p_le_ih, inode,
ee93961be   Jeff Mahoney   reiserfs: rename ...
982
  						 new_file_length,
d68caa953   Jeff Mahoney   reiserfs: rename ...
983
  						 cut_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984

bd4c625c0   Linus Torvalds   reiserfs: run scr...
985
986
  	/* Direct item. */
  	if (is_direct_le_ih(p_le_ih))
d68caa953   Jeff Mahoney   reiserfs: rename ...
987
  		return prepare_for_direct_item(path, p_le_ih, inode,
ee93961be   Jeff Mahoney   reiserfs: rename ...
988
  					       new_file_length, cut_size);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
989
990
991
  
  	/* Case of an indirect item. */
  	{
a9dd36435   Jeff Mahoney   reiserfs: rename ...
992
  	    int blk_size = sb->s_blocksize;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
993
994
995
996
997
  	    struct item_head s_ih;
  	    int need_re_search;
  	    int delete = 0;
  	    int result = M_CUT;
  	    int pos = 0;
ee93961be   Jeff Mahoney   reiserfs: rename ...
998
  	    if ( new_file_length == max_reiserfs_offset (inode) ) {
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
999
1000
  		/* prepare_for_delete_or_cut() is called by
  		 * reiserfs_delete_item() */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1001
  		new_file_length = 0;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1002
1003
1004
1005
1006
  		delete = 1;
  	    }
  
  	    do {
  		need_re_search = 0;
d68caa953   Jeff Mahoney   reiserfs: rename ...
1007
1008
1009
  		*cut_size = 0;
  		bh = PATH_PLAST_BUFFER(path);
  		copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1010
  		pos = I_UNFM_NUM(&s_ih);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1011

ee93961be   Jeff Mahoney   reiserfs: rename ...
1012
  		while (le_ih_k_offset (&s_ih) + (pos - 1) * blk_size > new_file_length) {
87588dd66   Al Viro   more reiserfs end...
1013
1014
  		    __le32 *unfm;
  		    __u32 block;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1015

23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1016
1017
1018
  		    /* Each unformatted block deletion may involve one additional
  		     * bitmap block into the transaction, thereby the initial
  		     * journal space reservation might not be enough. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1019
1020
  		    if (!delete && (*cut_size) != 0 &&
  			reiserfs_transaction_free_space(th) < JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD)
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1021
  			break;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1022

ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
1023
  		    unfm = (__le32 *)B_I_PITEM(bh, &s_ih) + pos - 1;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1024
  		    block = get_block_num(unfm, 0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1025

23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1026
  		    if (block != 0) {
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
1027
  			reiserfs_prepare_for_journal(sb, bh, 1);
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1028
  			put_block_num(unfm, 0, 0);
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
1029
  			journal_mark_dirty(th, sb, bh);
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1030
1031
  			reiserfs_free_block(th, inode, block, 1);
  		    }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1032

5e69e3a44   Frederic Weisbecker   kill-the-BKL/reis...
1033
  		    reiserfs_write_unlock(sb);
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1034
  		    cond_resched();
5e69e3a44   Frederic Weisbecker   kill-the-BKL/reis...
1035
  		    reiserfs_write_lock(sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1036

d68caa953   Jeff Mahoney   reiserfs: rename ...
1037
  		    if (item_moved (&s_ih, path))  {
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1038
1039
1040
1041
1042
  			need_re_search = 1;
  			break;
  		    }
  
  		    pos --;
d68caa953   Jeff Mahoney   reiserfs: rename ...
1043
1044
  		    (*removed)++;
  		    (*cut_size) -= UNFM_P_SIZE;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1045
1046
  
  		    if (pos == 0) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
1047
  			(*cut_size) -= IH_SIZE;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1048
1049
1050
1051
1052
1053
1054
  			result = M_DELETE;
  			break;
  		    }
  		}
  		/* a trick.  If the buffer has been logged, this will do nothing.  If
  		** we've broken the loop without logging it, it will restore the
  		** buffer */
ad31a4fc0   Jeff Mahoney   reiserfs: rename ...
1055
  		reiserfs_restore_prepared_buffer(sb, bh);
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1056
  	    } while (need_re_search &&
d68caa953   Jeff Mahoney   reiserfs: rename ...
1057
1058
  		     search_for_position_by_key(sb, item_key, path) == POSITION_FOUND);
  	    pos_in_item(path) = pos * UNFM_P_SIZE;
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1059

d68caa953   Jeff Mahoney   reiserfs: rename ...
1060
  	    if (*cut_size == 0) {
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1061
1062
1063
1064
1065
  		/* Nothing were cut. maybe convert last unformatted node to the
  		 * direct item? */
  		result = M_CONVERT;
  	    }
  	    return result;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1066
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
  }
  
  /* Calculate number of bytes which will be deleted or cut during balance */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1070
  static int calc_deleted_bytes_number(struct tree_balance *tb, char mode)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1071
  {
ee93961be   Jeff Mahoney   reiserfs: rename ...
1072
  	int del_size;
a063ae179   Jeff Mahoney   reiserfs: rename ...
1073
  	struct item_head *p_le_ih = PATH_PITEM_HEAD(tb->tb_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1074
1075
1076
  
  	if (is_statdata_le_ih(p_le_ih))
  		return 0;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1077
1078
  	del_size =
  	    (mode ==
a063ae179   Jeff Mahoney   reiserfs: rename ...
1079
  	     M_DELETE) ? ih_item_len(p_le_ih) : -tb->insert_size[0];
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1080
  	if (is_direntry_le_ih(p_le_ih)) {
ee93961be   Jeff Mahoney   reiserfs: rename ...
1081
1082
1083
1084
  		/* return EMPTY_DIR_SIZE; We delete emty directoris only.
  		 * we can't use EMPTY_DIR_SIZE, as old format dirs have a different
  		 * empty size.  ick. FIXME, is this right? */
  		return del_size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1085
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1087
  	if (is_indirect_le_ih(p_le_ih))
ee93961be   Jeff Mahoney   reiserfs: rename ...
1088
  		del_size = (del_size / UNFM_P_SIZE) *
a063ae179   Jeff Mahoney   reiserfs: rename ...
1089
  				(PATH_PLAST_BUFFER(tb->tb_path)->b_size);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1090
  	return del_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1092
  static void init_tb_struct(struct reiserfs_transaction_handle *th,
a063ae179   Jeff Mahoney   reiserfs: rename ...
1093
  			   struct tree_balance *tb,
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1094
  			   struct super_block *sb,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1095
  			   struct treepath *path, int size)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1096
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1098
  	BUG_ON(!th->t_trans_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099

a063ae179   Jeff Mahoney   reiserfs: rename ...
1100
1101
1102
  	memset(tb, '\0', sizeof(struct tree_balance));
  	tb->transaction_handle = th;
  	tb->tb_sb = sb;
d68caa953   Jeff Mahoney   reiserfs: rename ...
1103
1104
1105
  	tb->tb_path = path;
  	PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
  	PATH_OFFSET_POSITION(path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1106
  	tb->insert_size[0] = size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1107
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1109
  void padd_item(char *item, int total_length, int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1111
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1113
1114
  	for (i = total_length; i > length;)
  		item[--i] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
1119
  }
  
  #ifdef REISERQUOTA_DEBUG
  char key2type(struct reiserfs_key *ih)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1120
1121
1122
1123
1124
1125
1126
1127
1128
  	if (is_direntry_le_key(2, ih))
  		return 'd';
  	if (is_direct_le_key(2, ih))
  		return 'D';
  	if (is_indirect_le_key(2, ih))
  		return 'i';
  	if (is_statdata_le_key(2, ih))
  		return 's';
  	return 'u';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
1130
1131
1132
  }
  
  char head2type(struct item_head *ih)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1133
1134
1135
1136
1137
1138
1139
1140
1141
  	if (is_direntry_le_ih(ih))
  		return 'd';
  	if (is_direct_le_ih(ih))
  		return 'D';
  	if (is_indirect_le_ih(ih))
  		return 'i';
  	if (is_statdata_le_ih(ih))
  		return 's';
  	return 'u';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
1143
  }
  #endif
d68caa953   Jeff Mahoney   reiserfs: rename ...
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
  /* Delete object item.
   * th       - active transaction handle
   * path     - path to the deleted item
   * item_key - key to search for the deleted item
   * indode   - used for updating i_blocks and quotas
   * un_bh    - NULL or unformatted node pointer
   */
  int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
  			 struct treepath *path, const struct cpu_key *item_key,
  			 struct inode *inode, struct buffer_head *un_bh)
  {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1155
  	struct super_block *sb = inode->i_sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1156
1157
1158
1159
  	struct tree_balance s_del_balance;
  	struct item_head s_ih;
  	struct item_head *q_ih;
  	int quota_cut_bytes;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1160
  	int ret_value, del_size, removed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
  
  #ifdef CONFIG_REISERFS_CHECK
ee93961be   Jeff Mahoney   reiserfs: rename ...
1163
1164
  	char mode;
  	int iter = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1166
  	BUG_ON(!th->t_trans_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167

d68caa953   Jeff Mahoney   reiserfs: rename ...
1168
  	init_tb_struct(th, &s_del_balance, sb, path,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1169
  		       0 /*size is unknown */ );
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1171
  	while (1) {
ee93961be   Jeff Mahoney   reiserfs: rename ...
1172
  		removed = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
1174
  
  #ifdef CONFIG_REISERFS_CHECK
ee93961be   Jeff Mahoney   reiserfs: rename ...
1175
1176
  		iter++;
  		mode =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  #endif
d68caa953   Jeff Mahoney   reiserfs: rename ...
1178
  		    prepare_for_delete_or_cut(th, inode, path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1179
1180
  					      item_key, &removed,
  					      &del_size,
995c762ea   Jeff Mahoney   reiserfs: rename ...
1181
  					      max_reiserfs_offset(inode));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1182

ee93961be   Jeff Mahoney   reiserfs: rename ...
1183
  		RFALSE(mode != M_DELETE, "PAP-5320: mode must be M_DELETE");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1184

d68caa953   Jeff Mahoney   reiserfs: rename ...
1185
  		copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
ee93961be   Jeff Mahoney   reiserfs: rename ...
1186
  		s_del_balance.insert_size[0] = del_size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1187

ee93961be   Jeff Mahoney   reiserfs: rename ...
1188
1189
  		ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);
  		if (ret_value != REPEAT_SEARCH)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1190
  			break;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1191
  		PROC_INFO_INC(sb, delete_item_restarted);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1192
1193
  
  		// file system changed, repeat search
ee93961be   Jeff Mahoney   reiserfs: rename ...
1194
  		ret_value =
d68caa953   Jeff Mahoney   reiserfs: rename ...
1195
  		    search_for_position_by_key(sb, item_key, path);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1196
  		if (ret_value == IO_ERROR)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1197
  			break;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1198
  		if (ret_value == FILE_NOT_FOUND) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1199
  			reiserfs_warning(sb, "vs-5340",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1200
  					 "no items of the file %K found",
d68caa953   Jeff Mahoney   reiserfs: rename ...
1201
  					 item_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1202
1203
1204
  			break;
  		}
  	}			/* while (1) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205

ee93961be   Jeff Mahoney   reiserfs: rename ...
1206
  	if (ret_value != CARRY_ON) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1207
1208
1209
1210
  		unfix_nodes(&s_del_balance);
  		return 0;
  	}
  	// reiserfs_delete_item returns item length when success
ee93961be   Jeff Mahoney   reiserfs: rename ...
1211
  	ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
d68caa953   Jeff Mahoney   reiserfs: rename ...
1212
  	q_ih = get_ih(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1213
1214
1215
1216
1217
1218
1219
1220
  	quota_cut_bytes = ih_item_len(q_ih);
  
  	/* hack so the quota code doesn't have to guess if the file
  	 ** has a tail.  On tail insert, we allocate quota for 1 unformatted node.
  	 ** We test the offset because the tail might have been
  	 ** split into multiple items, and we only want to decrement for
  	 ** the unfm node once
  	 */
995c762ea   Jeff Mahoney   reiserfs: rename ...
1221
  	if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(q_ih)) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1222
1223
  		if ((le_ih_k_offset(q_ih) & (sb->s_blocksize - 1)) == 1) {
  			quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1224
1225
1226
  		} else {
  			quota_cut_bytes = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228

d68caa953   Jeff Mahoney   reiserfs: rename ...
1229
  	if (un_bh) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
  		int off;
  		char *data;
  
  		/* We are in direct2indirect conversion, so move tail contents
  		   to the unformatted node */
  		/* note, we do the copy before preparing the buffer because we
  		 ** don't care about the contents of the unformatted node yet.
  		 ** the only thing we really care about is the direct item's data
  		 ** is in the unformatted node.
  		 **
  		 ** Otherwise, we would have to call reiserfs_prepare_for_journal on
  		 ** the unformatted node, which might schedule, meaning we'd have to
  		 ** loop all the way back up to the start of the while loop.
  		 **
  		 ** The unformatted node must be dirtied later on.  We can't be
  		 ** sure here if the entire tail has been deleted yet.
  		 **
d68caa953   Jeff Mahoney   reiserfs: rename ...
1247
  		 ** un_bh is from the page cache (all unformatted nodes are
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1248
  		 ** from the page cache) and might be a highmem page.  So, we
d68caa953   Jeff Mahoney   reiserfs: rename ...
1249
  		 ** can't use un_bh->b_data.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1250
1251
  		 ** -clm
  		 */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1252
  		data = kmap_atomic(un_bh->b_page, KM_USER0);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1253
1254
  		off = ((le_ih_k_offset(&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));
  		memcpy(data + off,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1255
  		       B_I_PITEM(PATH_PLAST_BUFFER(path), &s_ih),
ee93961be   Jeff Mahoney   reiserfs: rename ...
1256
  		       ret_value);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1257
  		kunmap_atomic(data, KM_USER0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1259
1260
  	/* Perform balancing after all resources have been collected at once. */
  	do_balance(&s_del_balance, NULL, NULL, M_DELETE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
1262
  
  #ifdef REISERQUOTA_DEBUG
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1263
  	reiserfs_debug(sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1264
  		       "reiserquota delete_item(): freeing %u, id=%u type=%c",
995c762ea   Jeff Mahoney   reiserfs: rename ...
1265
  		       quota_cut_bytes, inode->i_uid, head2type(&s_ih));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
  #endif
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1267
  	dquot_free_space_nodirty(inode, quota_cut_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1269
  	/* Return deleted body length */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1270
  	return ret_value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  /* Summary Of Mechanisms For Handling Collisions Between Processes:
  
   deletion of the body of the object is performed by iput(), with the
   result that if multiple processes are operating on a file, the
   deletion of the body of the file is deferred until the last process
   that has an open inode performs its iput().
  
   writes and truncates are protected from collisions by use of
   semaphores.
  
   creates, linking, and mknod are protected from collisions with other
   processes by making the reiserfs_add_entry() the last step in the
   creation, and then rolling back all changes if there was a collision.
   - Hans
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  /* this deletes item which never gets split */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1288
1289
  void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
  				struct inode *inode, struct reiserfs_key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
  	struct tree_balance tb;
  	INITIALIZE_PATH(path);
  	int item_len = 0;
  	int tb_init = 0;
  	struct cpu_key cpu_key;
  	int retval;
  	int quota_cut_bytes = 0;
  
  	BUG_ON(!th->t_trans_id);
  
  	le_key2cpu_key(&cpu_key, key);
  
  	while (1) {
  		retval = search_item(th->t_super, &cpu_key, &path);
  		if (retval == IO_ERROR) {
0030b6457   Jeff Mahoney   reiserfs: use rei...
1306
1307
1308
  			reiserfs_error(th->t_super, "vs-5350",
  				       "i/o failure occurred trying "
  				       "to delete %K", &cpu_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
  			break;
  		}
  		if (retval != ITEM_FOUND) {
  			pathrelse(&path);
  			// No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
  			if (!
  			    ((unsigned long long)
  			     GET_HASH_VALUE(le_key_k_offset
  					    (le_key_version(key), key)) == 0
  			     && (unsigned long long)
  			     GET_GENERATION_NUMBER(le_key_k_offset
  						   (le_key_version(key),
  						    key)) == 1))
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1322
1323
  				reiserfs_warning(th->t_super, "vs-5355",
  						 "%k not found", key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1324
1325
1326
1327
1328
1329
1330
1331
1332
  			break;
  		}
  		if (!tb_init) {
  			tb_init = 1;
  			item_len = ih_item_len(PATH_PITEM_HEAD(&path));
  			init_tb_struct(th, &tb, th->t_super, &path,
  				       -(IH_SIZE + item_len));
  		}
  		quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1334
1335
1336
1337
1338
  		retval = fix_nodes(M_DELETE, &tb, NULL, NULL);
  		if (retval == REPEAT_SEARCH) {
  			PROC_INFO_INC(th->t_super, delete_solid_item_restarted);
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1340
1341
1342
  		if (retval == CARRY_ON) {
  			do_balance(&tb, NULL, NULL, M_DELETE);
  			if (inode) {	/* Should we count quota for item? (we don't count quotas for save-links) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
  #ifdef REISERQUOTA_DEBUG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1344
1345
1346
1347
  				reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
  					       "reiserquota delete_solid_item(): freeing %u id=%u type=%c",
  					       quota_cut_bytes, inode->i_uid,
  					       key2type(key));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
  #endif
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1349
  				dquot_free_space_nodirty(inode,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1350
1351
1352
1353
1354
  							 quota_cut_bytes);
  			}
  			break;
  		}
  		// IO_ERROR, NO_DISK_SPACE, etc
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1355
  		reiserfs_warning(th->t_super, "vs-5360",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1356
1357
1358
1359
  				 "could not delete %K due to fix_nodes failure",
  				 &cpu_key);
  		unfix_nodes(&tb);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1361
  	reiserfs_check_path(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1363
1364
  int reiserfs_delete_object(struct reiserfs_transaction_handle *th,
  			   struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1366
1367
1368
1369
1370
1371
1372
1373
1374
  	int err;
  	inode->i_size = 0;
  	BUG_ON(!th->t_trans_id);
  
  	/* for directory this deletes item containing "." and ".." */
  	err =
  	    reiserfs_do_truncate(th, inode, NULL, 0 /*no timestamp updates */ );
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
  #if defined( USE_INODE_GENERATION_COUNTER )
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1376
1377
1378
1379
1380
  	if (!old_format_only(th->t_super)) {
  		__le32 *inode_generation;
  
  		inode_generation =
  		    &REISERFS_SB(th->t_super)->s_rs->s_inode_generation;
9e902df6b   Marcin Slusarz   reiserfs: le*_add...
1381
  		le32_add_cpu(inode_generation, 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1382
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
1384
  /* USE_INODE_GENERATION_COUNTER */
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1385
  	reiserfs_delete_solid_item(th, inode, INODE_PKEY(inode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1387
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
  static void unmap_buffers(struct page *page, loff_t pos)
  {
  	struct buffer_head *bh;
  	struct buffer_head *head;
  	struct buffer_head *next;
  	unsigned long tail_index;
  	unsigned long cur_index;
  
  	if (page) {
  		if (page_has_buffers(page)) {
  			tail_index = pos & (PAGE_CACHE_SIZE - 1);
  			cur_index = 0;
  			head = page_buffers(page);
  			bh = head;
  			do {
  				next = bh->b_this_page;
  
  				/* we want to unmap the buffers that contain the tail, and
  				 ** all the buffers after it (since the tail must be at the
  				 ** end of the file).  We don't want to unmap file data
  				 ** before the tail, since it might be dirty and waiting to
  				 ** reach disk
  				 */
  				cur_index += bh->b_size;
  				if (cur_index > tail_index) {
  					reiserfs_unmap_buffer(bh);
  				}
  				bh = next;
  			} while (bh != head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1421
  static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
995c762ea   Jeff Mahoney   reiserfs: rename ...
1422
  				    struct inode *inode,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1423
  				    struct page *page,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1424
1425
  				    struct treepath *path,
  				    const struct cpu_key *item_key,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1426
  				    loff_t new_file_size, char *mode)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1427
  {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1428
  	struct super_block *sb = inode->i_sb;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1429
  	int block_size = sb->s_blocksize;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1430
1431
  	int cut_bytes;
  	BUG_ON(!th->t_trans_id);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1432
  	BUG_ON(new_file_size != inode->i_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1434
1435
1436
1437
  	/* the page being sent in could be NULL if there was an i/o error
  	 ** reading in the last block.  The user will hit problems trying to
  	 ** read the file, but for now we just skip the indirect2direct
  	 */
995c762ea   Jeff Mahoney   reiserfs: rename ...
1438
1439
1440
  	if (atomic_read(&inode->i_count) > 1 ||
  	    !tail_has_to_be_packed(inode) ||
  	    !page || (REISERFS_I(inode)->i_flags & i_nopack_mask)) {
0222e6571   Jeff Mahoney   reiserfs: strip t...
1441
  		/* leave tail in an unformatted node */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1442
  		*mode = M_SKIP_BALANCING;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1443
  		cut_bytes =
ee93961be   Jeff Mahoney   reiserfs: rename ...
1444
  		    block_size - (new_file_size & (block_size - 1));
d68caa953   Jeff Mahoney   reiserfs: rename ...
1445
  		pathrelse(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1446
1447
  		return cut_bytes;
  	}
d68caa953   Jeff Mahoney   reiserfs: rename ...
1448
1449
  	/* Perform the conversion to a direct_item. */
  	/* return indirect_to_direct(inode, path, item_key,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1450
  				  new_file_size, mode); */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1451
  	return indirect2direct(th, inode, page, path, item_key,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1452
  			       new_file_size, mode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1453
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
1456
1457
1458
  
  /* we did indirect_to_direct conversion. And we have inserted direct
     item successesfully, but there were no disk space to cut unfm
     pointer being converted. Therefore we have to delete inserted
     direct item(s) */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1459
  static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
1460
  					 struct inode *inode, struct treepath *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
  	struct cpu_key tail_key;
  	int tail_len;
  	int removed;
  	BUG_ON(!th->t_trans_id);
  
  	make_cpu_key(&tail_key, inode, inode->i_size + 1, TYPE_DIRECT, 4);	// !!!!
  	tail_key.key_length = 4;
  
  	tail_len =
  	    (cpu_key_k_offset(&tail_key) & (inode->i_sb->s_blocksize - 1)) - 1;
  	while (tail_len) {
  		/* look for the last byte of the tail */
  		if (search_for_position_by_key(inode->i_sb, &tail_key, path) ==
  		    POSITION_NOT_FOUND)
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1476
1477
  			reiserfs_panic(inode->i_sb, "vs-5615",
  				       "found invalid item");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
  		RFALSE(path->pos_in_item !=
  		       ih_item_len(PATH_PITEM_HEAD(path)) - 1,
  		       "vs-5616: appended bytes found");
  		PATH_LAST_POSITION(path)--;
  
  		removed =
  		    reiserfs_delete_item(th, path, &tail_key, inode,
  					 NULL /*unbh not needed */ );
  		RFALSE(removed <= 0
  		       || removed > tail_len,
  		       "vs-5617: there was tail %d bytes, removed item length %d bytes",
  		       tail_len, removed);
  		tail_len -= removed;
  		set_cpu_key_k_offset(&tail_key,
  				     cpu_key_k_offset(&tail_key) - removed);
  	}
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1494
1495
1496
  	reiserfs_warning(inode->i_sb, "reiserfs-5091", "indirect_to_direct "
  			 "conversion has been rolled back due to "
  			 "lack of disk space");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1497
1498
  	//mark_file_without_tail (inode);
  	mark_inode_dirty(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
  /* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1501
  int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1502
1503
  			   struct treepath *path,
  			   struct cpu_key *item_key,
995c762ea   Jeff Mahoney   reiserfs: rename ...
1504
  			   struct inode *inode,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1505
  			   struct page *page, loff_t new_file_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1506
  {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1507
  	struct super_block *sb = inode->i_sb;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1508
1509
1510
1511
1512
1513
  	/* Every function which is going to call do_balance must first
  	   create a tree_balance structure.  Then it must fill up this
  	   structure by using the init_tb_struct and fix_nodes functions.
  	   After that we can make tree balancing. */
  	struct tree_balance s_cut_balance;
  	struct item_head *p_le_ih;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1514
1515
1516
1517
  	int cut_size = 0,	/* Amount to be cut. */
  	    ret_value = CARRY_ON, removed = 0,	/* Number of the removed unformatted nodes. */
  	    is_inode_locked = 0;
  	char mode;		/* Mode of the balance. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1518
1519
1520
1521
1522
  	int retval2 = -1;
  	int quota_cut_bytes;
  	loff_t tail_pos = 0;
  
  	BUG_ON(!th->t_trans_id);
d68caa953   Jeff Mahoney   reiserfs: rename ...
1523
  	init_tb_struct(th, &s_cut_balance, inode->i_sb, path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1524
  		       cut_size);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1525
1526
1527
1528
1529
1530
1531
1532
  
  	/* Repeat this loop until we either cut the item without needing
  	   to balance, or we fix_nodes without schedule occurring */
  	while (1) {
  		/* Determine the balance mode, position of the first byte to
  		   be cut, and size to be cut.  In case of the indirect item
  		   free unformatted nodes which are pointed to by the cut
  		   pointers. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1533
  		mode =
d68caa953   Jeff Mahoney   reiserfs: rename ...
1534
  		    prepare_for_delete_or_cut(th, inode, path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1535
1536
1537
  					      item_key, &removed,
  					      &cut_size, new_file_size);
  		if (mode == M_CONVERT) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1538
1539
  			/* convert last unformatted node to direct item or leave
  			   tail in the unformatted node */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1540
  			RFALSE(ret_value != CARRY_ON,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1541
  			       "PAP-5570: can not convert twice");
ee93961be   Jeff Mahoney   reiserfs: rename ...
1542
  			ret_value =
995c762ea   Jeff Mahoney   reiserfs: rename ...
1543
  			    maybe_indirect_to_direct(th, inode, page,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1544
  						     path, item_key,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1545
1546
  						     new_file_size, &mode);
  			if (mode == M_SKIP_BALANCING)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1547
  				/* tail has been left in the unformatted node */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1548
  				return ret_value;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1549

ee93961be   Jeff Mahoney   reiserfs: rename ...
1550
  			is_inode_locked = 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1551
1552
1553
  
  			/* removing of last unformatted node will change value we
  			   have to return to truncate. Save it */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1554
1555
  			retval2 = ret_value;
  			/*retval2 = sb->s_blocksize - (new_file_size & (sb->s_blocksize - 1)); */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1556
1557
1558
1559
1560
  
  			/* So, we have performed the first part of the conversion:
  			   inserting the new direct item.  Now we are removing the
  			   last unformatted node pointer. Set key to search for
  			   it. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1561
1562
  			set_cpu_key_k_type(item_key, TYPE_INDIRECT);
  			item_key->key_length = 4;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1563
1564
1565
1566
  			new_file_size -=
  			    (new_file_size & (sb->s_blocksize - 1));
  			tail_pos = new_file_size;
  			set_cpu_key_k_offset(item_key, new_file_size + 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1567
  			if (search_for_position_by_key
d68caa953   Jeff Mahoney   reiserfs: rename ...
1568
1569
1570
1571
1572
  			    (sb, item_key,
  			     path) == POSITION_NOT_FOUND) {
  				print_block(PATH_PLAST_BUFFER(path), 3,
  					    PATH_LAST_POSITION(path) - 1,
  					    PATH_LAST_POSITION(path) + 1);
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1573
  				reiserfs_panic(sb, "PAP-5580", "item to "
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1574
  					       "convert does not exist (%K)",
d68caa953   Jeff Mahoney   reiserfs: rename ...
1575
  					       item_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1576
1577
1578
  			}
  			continue;
  		}
ee93961be   Jeff Mahoney   reiserfs: rename ...
1579
  		if (cut_size == 0) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
1580
  			pathrelse(path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1581
1582
  			return 0;
  		}
ee93961be   Jeff Mahoney   reiserfs: rename ...
1583
  		s_cut_balance.insert_size[0] = cut_size;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1584

ee93961be   Jeff Mahoney   reiserfs: rename ...
1585
1586
  		ret_value = fix_nodes(mode, &s_cut_balance, NULL, NULL);
  		if (ret_value != REPEAT_SEARCH)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1587
  			break;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1588
  		PROC_INFO_INC(sb, cut_from_item_restarted);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1589

ee93961be   Jeff Mahoney   reiserfs: rename ...
1590
  		ret_value =
d68caa953   Jeff Mahoney   reiserfs: rename ...
1591
  		    search_for_position_by_key(sb, item_key, path);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1592
  		if (ret_value == POSITION_FOUND)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1593
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594

a9dd36435   Jeff Mahoney   reiserfs: rename ...
1595
  		reiserfs_warning(sb, "PAP-5610", "item %K not found",
d68caa953   Jeff Mahoney   reiserfs: rename ...
1596
  				 item_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1597
  		unfix_nodes(&s_cut_balance);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1598
  		return (ret_value == IO_ERROR) ? -EIO : -ENOENT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1599
1600
1601
  	}			/* while */
  
  	// check fix_nodes results (IO_ERROR or NO_DISK_SPACE)
ee93961be   Jeff Mahoney   reiserfs: rename ...
1602
1603
  	if (ret_value != CARRY_ON) {
  		if (is_inode_locked) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1604
1605
  			// FIXME: this seems to be not needed: we are always able
  			// to cut item
d68caa953   Jeff Mahoney   reiserfs: rename ...
1606
  			indirect_to_direct_roll_back(th, inode, path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1607
  		}
ee93961be   Jeff Mahoney   reiserfs: rename ...
1608
  		if (ret_value == NO_DISK_SPACE)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1609
  			reiserfs_warning(sb, "reiserfs-5092",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1610
  					 "NO_DISK_SPACE");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1611
1612
  		unfix_nodes(&s_cut_balance);
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1614
1615
  
  	/* go ahead and perform balancing */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1616
  	RFALSE(mode == M_PASTE || mode == M_INSERT, "invalid mode");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1617
1618
1619
  
  	/* Calculate number of bytes that need to be cut from the item. */
  	quota_cut_bytes =
ee93961be   Jeff Mahoney   reiserfs: rename ...
1620
  	    (mode ==
d68caa953   Jeff Mahoney   reiserfs: rename ...
1621
  	     M_DELETE) ? ih_item_len(get_ih(path)) : -s_cut_balance.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1622
1623
  	    insert_size[0];
  	if (retval2 == -1)
ee93961be   Jeff Mahoney   reiserfs: rename ...
1624
  		ret_value = calc_deleted_bytes_number(&s_cut_balance, mode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1625
  	else
ee93961be   Jeff Mahoney   reiserfs: rename ...
1626
  		ret_value = retval2;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1627
1628
1629
1630
1631
  
  	/* For direct items, we only change the quota when deleting the last
  	 ** item.
  	 */
  	p_le_ih = PATH_PITEM_HEAD(s_cut_balance.tb_path);
995c762ea   Jeff Mahoney   reiserfs: rename ...
1632
  	if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(p_le_ih)) {
ee93961be   Jeff Mahoney   reiserfs: rename ...
1633
  		if (mode == M_DELETE &&
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1634
  		    (le_ih_k_offset(p_le_ih) & (sb->s_blocksize - 1)) ==
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1635
1636
  		    1) {
  			// FIXME: this is to keep 3.5 happy
995c762ea   Jeff Mahoney   reiserfs: rename ...
1637
  			REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1638
  			quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1639
1640
1641
  		} else {
  			quota_cut_bytes = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1642
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
  #ifdef CONFIG_REISERFS_CHECK
ee93961be   Jeff Mahoney   reiserfs: rename ...
1644
  	if (is_inode_locked) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1645
1646
1647
1648
1649
1650
  		struct item_head *le_ih =
  		    PATH_PITEM_HEAD(s_cut_balance.tb_path);
  		/* we are going to complete indirect2direct conversion. Make
  		   sure, that we exactly remove last unformatted node pointer
  		   of the item */
  		if (!is_indirect_le_ih(le_ih))
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1651
  			reiserfs_panic(sb, "vs-5652",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1652
  				       "item must be indirect %h", le_ih);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1653
  		if (mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1654
  			reiserfs_panic(sb, "vs-5653", "completing "
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1655
1656
1657
  				       "indirect2direct conversion indirect "
  				       "item %h being deleted must be of "
  				       "4 byte long", le_ih);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1658

ee93961be   Jeff Mahoney   reiserfs: rename ...
1659
  		if (mode == M_CUT
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1660
  		    && s_cut_balance.insert_size[0] != -UNFM_P_SIZE) {
a9dd36435   Jeff Mahoney   reiserfs: rename ...
1661
  			reiserfs_panic(sb, "vs-5654", "can not complete "
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1662
1663
  				       "indirect2direct conversion of %h "
  				       "(CUT, insert_size==%d)",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1664
1665
1666
1667
  				       le_ih, s_cut_balance.insert_size[0]);
  		}
  		/* it would be useful to make sure, that right neighboring
  		   item is direct item of this file */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1670

ee93961be   Jeff Mahoney   reiserfs: rename ...
1671
1672
  	do_balance(&s_cut_balance, NULL, NULL, mode);
  	if (is_inode_locked) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1673
1674
1675
1676
1677
1678
  		/* we've done an indirect->direct conversion.  when the data block
  		 ** was freed, it was removed from the list of blocks that must
  		 ** be flushed before the transaction commits, make sure to
  		 ** unmap and invalidate it
  		 */
  		unmap_buffers(page, tail_pos);
995c762ea   Jeff Mahoney   reiserfs: rename ...
1679
  		REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1680
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
  #ifdef REISERQUOTA_DEBUG
995c762ea   Jeff Mahoney   reiserfs: rename ...
1682
  	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1683
  		       "reiserquota cut_from_item(): freeing %u id=%u type=%c",
995c762ea   Jeff Mahoney   reiserfs: rename ...
1684
  		       quota_cut_bytes, inode->i_uid, '?');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
  #endif
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1686
  	dquot_free_space_nodirty(inode, quota_cut_bytes);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1687
  	return ret_value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1689
1690
  static void truncate_directory(struct reiserfs_transaction_handle *th,
  			       struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1692
1693
  	BUG_ON(!th->t_trans_id);
  	if (inode->i_nlink)
0030b6457   Jeff Mahoney   reiserfs: use rei...
1694
  		reiserfs_error(inode->i_sb, "vs-5655", "link count != 0");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1695
1696
1697
1698
1699
1700
1701
  
  	set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), DOT_OFFSET);
  	set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_DIRENTRY);
  	reiserfs_delete_solid_item(th, inode, INODE_PKEY(inode));
  	reiserfs_update_sd(th, inode);
  	set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), SD_OFFSET);
  	set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_STAT_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1703
1704
  /* Truncate file to the new size. Note, this must be called with a transaction
     already started */
995c762ea   Jeff Mahoney   reiserfs: rename ...
1705
1706
  int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
  			  struct inode *inode,	/* ->i_size contains new size */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
  			 struct page *page,	/* up to date for last block */
  			 int update_timestamps	/* when it is called by
  						   file_release to convert
  						   the tail - no timestamps
  						   should be updated */
      )
  {
  	INITIALIZE_PATH(s_search_path);	/* Path to the current object item. */
  	struct item_head *p_le_ih;	/* Pointer to an item header. */
  	struct cpu_key s_item_key;	/* Key to search for a previous file item. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1717
1718
1719
  	loff_t file_size,	/* Old file size. */
  	 new_file_size;	/* New file size. */
  	int deleted;		/* Number of deleted or truncated bytes. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1720
1721
1722
1723
1724
  	int retval;
  	int err = 0;
  
  	BUG_ON(!th->t_trans_id);
  	if (!
995c762ea   Jeff Mahoney   reiserfs: rename ...
1725
1726
  	    (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
  	     || S_ISLNK(inode->i_mode)))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1727
  		return 0;
995c762ea   Jeff Mahoney   reiserfs: rename ...
1728
  	if (S_ISDIR(inode->i_mode)) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1729
  		// deletion of directory - no need to update timestamps
995c762ea   Jeff Mahoney   reiserfs: rename ...
1730
  		truncate_directory(th, inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1731
1732
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1733

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1734
  	/* Get new file size. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1735
  	new_file_size = inode->i_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1737
  	// FIXME: note, that key type is unimportant here
995c762ea   Jeff Mahoney   reiserfs: rename ...
1738
  	make_cpu_key(&s_item_key, inode, max_reiserfs_offset(inode),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1739
  		     TYPE_DIRECT, 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1741
  	retval =
995c762ea   Jeff Mahoney   reiserfs: rename ...
1742
  	    search_for_position_by_key(inode->i_sb, &s_item_key,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1743
1744
  				       &s_search_path);
  	if (retval == IO_ERROR) {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1745
  		reiserfs_error(inode->i_sb, "vs-5657",
0030b6457   Jeff Mahoney   reiserfs: use rei...
1746
1747
  			       "i/o failure occurred trying to truncate %K",
  			       &s_item_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1748
1749
1750
1751
  		err = -EIO;
  		goto out;
  	}
  	if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1752
  		reiserfs_error(inode->i_sb, "PAP-5660",
0030b6457   Jeff Mahoney   reiserfs: use rei...
1753
1754
  			       "wrong result %d of search for %K", retval,
  			       &s_item_key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1755
1756
1757
1758
  
  		err = -EIO;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1760
1761
1762
1763
1764
  	s_search_path.pos_in_item--;
  
  	/* Get real file size (total length of all file items) */
  	p_le_ih = PATH_PITEM_HEAD(&s_search_path);
  	if (is_statdata_le_ih(p_le_ih))
ee93961be   Jeff Mahoney   reiserfs: rename ...
1765
  		file_size = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1766
1767
1768
  	else {
  		loff_t offset = le_ih_k_offset(p_le_ih);
  		int bytes =
995c762ea   Jeff Mahoney   reiserfs: rename ...
1769
  		    op_bytes_number(p_le_ih, inode->i_sb->s_blocksize);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1770
1771
1772
1773
  
  		/* this may mismatch with real file size: if last direct item
  		   had no padding zeros and last unformatted node had no free
  		   space, this file would have this file size */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1774
  		file_size = offset + bytes - 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1775
1776
1777
1778
1779
  	}
  	/*
  	 * are we doing a full truncate or delete, if so
  	 * kick in the reada code
  	 */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1780
  	if (new_file_size == 0)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1781
  		s_search_path.reada = PATH_READA | PATH_READA_BACK;
ee93961be   Jeff Mahoney   reiserfs: rename ...
1782
  	if (file_size == 0 || file_size < new_file_size) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1783
  		goto update_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1785
  	/* Update key to search for the last file item. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1786
  	set_cpu_key_k_offset(&s_item_key, file_size);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1787
1788
1789
  
  	do {
  		/* Cut or delete file item. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1790
  		deleted =
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1791
  		    reiserfs_cut_from_item(th, &s_search_path, &s_item_key,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1792
1793
  					   inode, page, new_file_size);
  		if (deleted < 0) {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1794
  			reiserfs_warning(inode->i_sb, "vs-5665",
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1795
  					 "reiserfs_cut_from_item failed");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1796
1797
1798
  			reiserfs_check_path(&s_search_path);
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799

ee93961be   Jeff Mahoney   reiserfs: rename ...
1800
  		RFALSE(deleted > file_size,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1801
  		       "PAP-5670: reiserfs_cut_from_item: too many bytes deleted: deleted %d, file_size %lu, item_key %K",
ee93961be   Jeff Mahoney   reiserfs: rename ...
1802
  		       deleted, file_size, &s_item_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1804
  		/* Change key to search the last file item. */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1805
  		file_size -= deleted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806

ee93961be   Jeff Mahoney   reiserfs: rename ...
1807
  		set_cpu_key_k_offset(&s_item_key, file_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1808

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1809
1810
1811
  		/* While there are bytes to truncate and previous file item is presented in the tree. */
  
  		/*
0222e6571   Jeff Mahoney   reiserfs: strip t...
1812
  		 ** This loop could take a really long time, and could log
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1813
1814
1815
1816
1817
  		 ** many more blocks than a transaction can hold.  So, we do a polite
  		 ** journal end here, and if the transaction needs ending, we make
  		 ** sure the file is consistent before ending the current trans
  		 ** and starting a new one
  		 */
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1818
1819
  		if (journal_transaction_should_end(th, 0) ||
  		    reiserfs_transaction_free_space(th) <= JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1820
  			int orig_len_alloc = th->t_blocks_allocated;
3cd6dbe6f   Jeff Mahoney   reiserfs: cleanup...
1821
  			pathrelse(&s_search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1822
1823
  
  			if (update_timestamps) {
995c762ea   Jeff Mahoney   reiserfs: rename ...
1824
1825
  				inode->i_mtime = CURRENT_TIME_SEC;
  				inode->i_ctime = CURRENT_TIME_SEC;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1826
  			}
995c762ea   Jeff Mahoney   reiserfs: rename ...
1827
  			reiserfs_update_sd(th, inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1828

995c762ea   Jeff Mahoney   reiserfs: rename ...
1829
  			err = journal_end(th, inode->i_sb, orig_len_alloc);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1830
1831
  			if (err)
  				goto out;
995c762ea   Jeff Mahoney   reiserfs: rename ...
1832
  			err = journal_begin(th, inode->i_sb,
23f9e0f89   Alexander Zarochentzev   [PATCH] reiserfs:...
1833
  					    JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD + JOURNAL_PER_BALANCE_CNT * 4) ;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1834
1835
  			if (err)
  				goto out;
995c762ea   Jeff Mahoney   reiserfs: rename ...
1836
  			reiserfs_update_inode_transaction(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1837
  		}
ee93961be   Jeff Mahoney   reiserfs: rename ...
1838
  	} while (file_size > ROUND_UP(new_file_size) &&
995c762ea   Jeff Mahoney   reiserfs: rename ...
1839
  		 search_for_position_by_key(inode->i_sb, &s_item_key,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1840
  					    &s_search_path) == POSITION_FOUND);
ee93961be   Jeff Mahoney   reiserfs: rename ...
1841
  	RFALSE(file_size > ROUND_UP(new_file_size),
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1842
  	       "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",
ee93961be   Jeff Mahoney   reiserfs: rename ...
1843
  	       new_file_size, file_size, s_item_key.on_disk_key.k_objectid);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1844
1845
1846
1847
  
        update_and_out:
  	if (update_timestamps) {
  		// this is truncate, not file closing
995c762ea   Jeff Mahoney   reiserfs: rename ...
1848
1849
  		inode->i_mtime = CURRENT_TIME_SEC;
  		inode->i_ctime = CURRENT_TIME_SEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1850
  	}
995c762ea   Jeff Mahoney   reiserfs: rename ...
1851
  	reiserfs_update_sd(th, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1853
1854
1855
1856
        out:
  	pathrelse(&s_search_path);
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1857
1858
1859
  
  #ifdef CONFIG_REISERFS_CHECK
  // this makes sure, that we __append__, not overwrite or add holes
fec6d055d   Josef "Jeff" Sipek   [PATCH] struct pa...
1860
  static void check_research_for_paste(struct treepath *path,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1861
  				     const struct cpu_key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1863
1864
1865
1866
1867
1868
  	struct item_head *found_ih = get_ih(path);
  
  	if (is_direct_le_ih(found_ih)) {
  		if (le_ih_k_offset(found_ih) +
  		    op_bytes_number(found_ih,
  				    get_last_bh(path)->b_size) !=
d68caa953   Jeff Mahoney   reiserfs: rename ...
1869
  		    cpu_key_k_offset(key)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1870
1871
1872
  		    || op_bytes_number(found_ih,
  				       get_last_bh(path)->b_size) !=
  		    pos_in_item(path))
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1873
1874
1875
  			reiserfs_panic(NULL, "PAP-5720", "found direct item "
  				       "%h or position (%d) does not match "
  				       "to key %K", found_ih,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1876
  				       pos_in_item(path), key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1877
1878
1879
1880
1881
  	}
  	if (is_indirect_le_ih(found_ih)) {
  		if (le_ih_k_offset(found_ih) +
  		    op_bytes_number(found_ih,
  				    get_last_bh(path)->b_size) !=
d68caa953   Jeff Mahoney   reiserfs: rename ...
1882
  		    cpu_key_k_offset(key)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1883
1884
  		    || I_UNFM_NUM(found_ih) != pos_in_item(path)
  		    || get_ih_free_space(found_ih) != 0)
c3a9c2109   Jeff Mahoney   reiserfs: rework ...
1885
1886
1887
  			reiserfs_panic(NULL, "PAP-5730", "found indirect "
  				       "item (%h) or position (%d) does not "
  				       "match to key (%K)",
d68caa953   Jeff Mahoney   reiserfs: rename ...
1888
  				       found_ih, pos_in_item(path), key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1889
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1891
  #endif				/* config reiserfs check */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892
1893
  
  /* Paste bytes to the existing item. Returns bytes number pasted into the item. */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1894
1895
  int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *search_path,	/* Path to the pasted item.	  */
  			     const struct cpu_key *key,	/* Key to search for the needed item. */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1896
  			     struct inode *inode,	/* Inode item belongs to */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1897
  			     const char *body,	/* Pointer to the bytes to paste.    */
ee93961be   Jeff Mahoney   reiserfs: rename ...
1898
  			     int pasted_size)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1899
1900
1901
1902
1903
1904
  {				/* Size of pasted bytes.             */
  	struct tree_balance s_paste_balance;
  	int retval;
  	int fs_gen;
  
  	BUG_ON(!th->t_trans_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1906
  	fs_gen = get_generation(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
  
  #ifdef REISERQUOTA_DEBUG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1909
1910
  	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
  		       "reiserquota paste_into_item(): allocating %u id=%u type=%c",
ee93961be   Jeff Mahoney   reiserfs: rename ...
1911
  		       pasted_size, inode->i_uid,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1912
  		       key2type(&(key->on_disk_key)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
  #endif
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1914
1915
  	retval = dquot_alloc_space_nodirty(inode, pasted_size);
  	if (retval) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
1916
  		pathrelse(search_path);
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1917
  		return retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1918
  	}
d68caa953   Jeff Mahoney   reiserfs: rename ...
1919
  	init_tb_struct(th, &s_paste_balance, th->t_super, search_path,
ee93961be   Jeff Mahoney   reiserfs: rename ...
1920
  		       pasted_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  #ifdef DISPLACE_NEW_PACKING_LOCALITIES
d68caa953   Jeff Mahoney   reiserfs: rename ...
1922
  	s_paste_balance.key = key->on_disk_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1924
1925
1926
  	/* DQUOT_* can schedule, must check before the fix_nodes */
  	if (fs_changed(fs_gen, inode->i_sb)) {
  		goto search_again;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1928
1929
1930
  
  	while ((retval =
  		fix_nodes(M_PASTE, &s_paste_balance, NULL,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1931
  			  body)) == REPEAT_SEARCH) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1932
1933
1934
1935
  	      search_again:
  		/* file system changed while we were in the fix_nodes */
  		PROC_INFO_INC(th->t_super, paste_into_item_restarted);
  		retval =
d68caa953   Jeff Mahoney   reiserfs: rename ...
1936
1937
  		    search_for_position_by_key(th->t_super, key,
  					       search_path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1938
1939
1940
1941
1942
  		if (retval == IO_ERROR) {
  			retval = -EIO;
  			goto error_out;
  		}
  		if (retval == POSITION_FOUND) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1943
1944
  			reiserfs_warning(inode->i_sb, "PAP-5710",
  					 "entry or pasted byte (%K) exists",
d68caa953   Jeff Mahoney   reiserfs: rename ...
1945
  					 key);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1946
1947
1948
  			retval = -EEXIST;
  			goto error_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1949
  #ifdef CONFIG_REISERFS_CHECK
d68caa953   Jeff Mahoney   reiserfs: rename ...
1950
  		check_research_for_paste(search_path, key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1952
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1953

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1954
1955
1956
  	/* Perform balancing after all resources are collected by fix_nodes, and
  	   accessing them will not risk triggering schedule. */
  	if (retval == CARRY_ON) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
1957
  		do_balance(&s_paste_balance, NULL /*ih */ , body, M_PASTE);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1958
1959
1960
1961
1962
1963
  		return 0;
  	}
  	retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
        error_out:
  	/* this also releases the path */
  	unfix_nodes(&s_paste_balance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964
  #ifdef REISERQUOTA_DEBUG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1965
1966
  	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
  		       "reiserquota paste_into_item(): freeing %u id=%u type=%c",
ee93961be   Jeff Mahoney   reiserfs: rename ...
1967
  		       pasted_size, inode->i_uid,
d68caa953   Jeff Mahoney   reiserfs: rename ...
1968
  		       key2type(&(key->on_disk_key)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
  #endif
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
1970
  	dquot_free_space_nodirty(inode, pasted_size);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1971
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1972
  }
d68caa953   Jeff Mahoney   reiserfs: rename ...
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
  /* Insert new item into the buffer at the path.
   * th   - active transaction handle
   * path - path to the inserted item
   * ih   - pointer to the item header to insert
   * body - pointer to the bytes to insert
   */
  int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
  			 struct treepath *path, const struct cpu_key *key,
  			 struct item_head *ih, struct inode *inode,
  			 const char *body)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1984
1985
1986
1987
1988
1989
1990
1991
1992
  	struct tree_balance s_ins_balance;
  	int retval;
  	int fs_gen = 0;
  	int quota_bytes = 0;
  
  	BUG_ON(!th->t_trans_id);
  
  	if (inode) {		/* Do we count quotas for item? */
  		fs_gen = get_generation(inode->i_sb);
d68caa953   Jeff Mahoney   reiserfs: rename ...
1993
  		quota_bytes = ih_item_len(ih);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1994
1995
1996
1997
  
  		/* hack so the quota code doesn't have to guess if the file has
  		 ** a tail, links are always tails, so there's no guessing needed
  		 */
d68caa953   Jeff Mahoney   reiserfs: rename ...
1998
  		if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(ih))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1999
  			quota_bytes = inode->i_sb->s_blocksize + UNFM_P_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2000
  #ifdef REISERQUOTA_DEBUG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2001
2002
  		reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
  			       "reiserquota insert_item(): allocating %u id=%u type=%c",
d68caa953   Jeff Mahoney   reiserfs: rename ...
2003
  			       quota_bytes, inode->i_uid, head2type(ih));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2004
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2005
2006
  		/* We can't dirty inode here. It would be immediately written but
  		 * appropriate stat item isn't inserted yet... */
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
2007
2008
  		retval = dquot_alloc_space_nodirty(inode, quota_bytes);
  		if (retval) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
2009
  			pathrelse(path);
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
2010
  			return retval;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2011
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2012
  	}
d68caa953   Jeff Mahoney   reiserfs: rename ...
2013
2014
  	init_tb_struct(th, &s_ins_balance, th->t_super, path,
  		       IH_SIZE + ih_item_len(ih));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
  #ifdef DISPLACE_NEW_PACKING_LOCALITIES
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2016
  	s_ins_balance.key = key->on_disk_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2017
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2018
2019
2020
  	/* DQUOT_* can schedule, must check to be sure calling fix_nodes is safe */
  	if (inode && fs_changed(fs_gen, inode->i_sb)) {
  		goto search_again;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2022
2023
  
  	while ((retval =
d68caa953   Jeff Mahoney   reiserfs: rename ...
2024
2025
  		fix_nodes(M_INSERT, &s_ins_balance, ih,
  			  body)) == REPEAT_SEARCH) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2026
2027
2028
  	      search_again:
  		/* file system changed while we were in the fix_nodes */
  		PROC_INFO_INC(th->t_super, insert_item_restarted);
d68caa953   Jeff Mahoney   reiserfs: rename ...
2029
  		retval = search_item(th->t_super, key, path);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2030
2031
2032
2033
2034
  		if (retval == IO_ERROR) {
  			retval = -EIO;
  			goto error_out;
  		}
  		if (retval == ITEM_FOUND) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2035
  			reiserfs_warning(th->t_super, "PAP-5760",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2036
2037
2038
2039
2040
  					 "key %K already exists in the tree",
  					 key);
  			retval = -EEXIST;
  			goto error_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2041
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2043
2044
  	/* make balancing after all resources will be collected at a time */
  	if (retval == CARRY_ON) {
d68caa953   Jeff Mahoney   reiserfs: rename ...
2045
  		do_balance(&s_ins_balance, ih, body, M_INSERT);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2046
2047
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2049
2050
2051
2052
  	retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
        error_out:
  	/* also releases the path */
  	unfix_nodes(&s_ins_balance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2053
  #ifdef REISERQUOTA_DEBUG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2054
2055
  	reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
  		       "reiserquota insert_item(): freeing %u id=%u type=%c",
d68caa953   Jeff Mahoney   reiserfs: rename ...
2056
  		       quota_bytes, inode->i_uid, head2type(ih));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2057
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2058
  	if (inode)
5dd4056db   Christoph Hellwig   dquot: cleanup sp...
2059
  		dquot_free_space_nodirty(inode, quota_bytes);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2060
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2061
  }