Blame view

fs/udf/balloc.c 21.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * balloc.c
   *
   * PURPOSE
   *	Block allocation handling routines for the OSTA-UDF(tm) filesystem.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   * COPYRIGHT
   *	This file is distributed under the terms of the GNU General Public
   *	License (GPL). Copies of the GPL can be obtained from:
   *		ftp://prep.ai.mit.edu/pub/gnu/GPL
   *	Each contributing author retains all rights to their own work.
   *
   *  (C) 1999-2001 Ben Fennema
   *  (C) 1999 Stelias Computing Inc
   *
   * HISTORY
   *
   *  02/24/99 blf  Created.
   *
   */
  
  #include "udfdecl.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
  #include <linux/buffer_head.h>
  #include <linux/bitops.h>
  
  #include "udf_i.h"
  #include "udf_sb.h"
9ad1e1e40   Akinobu Mita   udf: use little-e...
28
29
30
31
  #define udf_clear_bit	__test_and_clear_bit_le
  #define udf_set_bit	__test_and_set_bit_le
  #define udf_test_bit	test_bit_le
  #define udf_find_next_one_bit	find_next_bit_le
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32

cb00ea352   Cyrill Gorcunov   UDF: coding style...
33
34
35
  static int read_block_bitmap(struct super_block *sb,
  			     struct udf_bitmap *bitmap, unsigned int block,
  			     unsigned long bitmap_nr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
  {
  	struct buffer_head *bh = NULL;
  	int retval = 0;
5ca4e4be8   Pekka Enberg   Remove struct typ...
39
  	struct kernel_lb_addr loc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  
  	loc.logicalBlockNum = bitmap->s_extPosition;
6c79e987d   Marcin Slusarz   udf: remove some ...
42
  	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

97e961fdb   Pekka Enberg   Fix the udf code ...
44
  	bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block));
4b11111ab   Marcin Slusarz   udf: fix coding s...
45
  	if (!bh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  		retval = -EIO;
4b11111ab   Marcin Slusarz   udf: fix coding s...
47

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
  	bitmap->s_block_bitmap[bitmap_nr] = bh;
  	return retval;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
51
52
53
  static int __load_block_bitmap(struct super_block *sb,
  			       struct udf_bitmap *bitmap,
  			       unsigned int block_group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
  {
  	int retval = 0;
  	int nr_groups = bitmap->s_nr_groups;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
57
  	if (block_group >= nr_groups) {
a983f368f   Joe Perches   udf: Neaten udf_d...
58
59
60
  		udf_debug("block_group (%d) > nr_groups (%d)
  ",
  			  block_group, nr_groups);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
62
  	if (bitmap->s_block_bitmap[block_group]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  		return block_group;
28de7948a   Cyrill Gorcunov   UDF: coding style...
64
65
66
  	} else {
  		retval = read_block_bitmap(sb, bitmap, block_group,
  					   block_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
71
  		if (retval < 0)
  			return retval;
  		return block_group;
  	}
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
72
73
74
  static inline int load_block_bitmap(struct super_block *sb,
  				    struct udf_bitmap *bitmap,
  				    unsigned int block_group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
81
82
83
84
85
86
87
  {
  	int slot;
  
  	slot = __load_block_bitmap(sb, bitmap, block_group);
  
  	if (slot < 0)
  		return slot;
  
  	if (!bitmap->s_block_bitmap[slot])
  		return -EIO;
  
  	return slot;
  }
146bca72c   Jan Kara   udf: Don't write ...
88
  static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)
742ba02a5   Marcin Slusarz   udf: create commo...
89
  {
146bca72c   Jan Kara   udf: Don't write ...
90
  	struct udf_sb_info *sbi = UDF_SB(sb);
742ba02a5   Marcin Slusarz   udf: create commo...
91
  	struct logicalVolIntegrityDesc *lvid;
146bca72c   Jan Kara   udf: Don't write ...
92
93
  	if (!sbi->s_lvid_bh)
  		return;
742ba02a5   Marcin Slusarz   udf: create commo...
94
95
  
  	lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
96
  	le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
146bca72c   Jan Kara   udf: Don't write ...
97
  	udf_updated_lvid(sb);
742ba02a5   Marcin Slusarz   udf: create commo...
98
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
99
100
101
  static void udf_bitmap_free_blocks(struct super_block *sb,
  				   struct inode *inode,
  				   struct udf_bitmap *bitmap,
97e961fdb   Pekka Enberg   Fix the udf code ...
102
103
  				   struct kernel_lb_addr *bloc,
  				   uint32_t offset,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
104
  				   uint32_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
107
  	struct buffer_head *bh = NULL;
97e961fdb   Pekka Enberg   Fix the udf code ...
108
  	struct udf_part_map *partmap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
  	unsigned long block;
  	unsigned long block_group;
  	unsigned long bit;
  	unsigned long i;
  	int bitmap_nr;
  	unsigned long overflow;
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
115
  	mutex_lock(&sbi->s_alloc_mutex);
97e961fdb   Pekka Enberg   Fix the udf code ...
116
  	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
69ecbbeda   Dan Carpenter   udf: potential in...
117
118
  	if (bloc->logicalBlockNum + count < count ||
  	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
119
120
  		udf_debug("%d < %d || %d + %d > %d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
121
122
123
  			  bloc->logicalBlockNum, 0,
  			  bloc->logicalBlockNum, count,
  			  partmap->s_partition_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  		goto error_return;
  	}
97e961fdb   Pekka Enberg   Fix the udf code ...
126
  	block = bloc->logicalBlockNum + offset +
4b11111ab   Marcin Slusarz   udf: fix coding s...
127
  		(sizeof(struct spaceBitmapDesc) << 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

4daa1b879   Marcin Slusarz   udf: replace loop...
129
130
131
132
133
134
135
136
137
138
139
  	do {
  		overflow = 0;
  		block_group = block >> (sb->s_blocksize_bits + 3);
  		bit = block % (sb->s_blocksize << 3);
  
  		/*
  		* Check to see if we are freeing blocks across a group boundary.
  		*/
  		if (bit + count > (sb->s_blocksize << 3)) {
  			overflow = bit + count - (sb->s_blocksize << 3);
  			count -= overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  		}
4daa1b879   Marcin Slusarz   udf: replace loop...
141
142
143
144
145
146
147
148
149
150
151
  		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
  		if (bitmap_nr < 0)
  			goto error_return;
  
  		bh = bitmap->s_block_bitmap[bitmap_nr];
  		for (i = 0; i < count; i++) {
  			if (udf_set_bit(bit + i, bh->b_data)) {
  				udf_debug("bit %ld already set
  ", bit + i);
  				udf_debug("byte=%2x
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
152
  					  ((char *)bh->b_data)[(bit + i) >> 3]);
4daa1b879   Marcin Slusarz   udf: replace loop...
153
154
  			}
  		}
7abc2e45e   Jan Kara   udf: Call udf_add...
155
  		udf_add_free_space(sb, sbi->s_partition, count);
4daa1b879   Marcin Slusarz   udf: replace loop...
156
157
158
159
160
161
  		mark_buffer_dirty(bh);
  		if (overflow) {
  			block += count;
  			count = overflow;
  		}
  	} while (overflow);
28de7948a   Cyrill Gorcunov   UDF: coding style...
162
  error_return:
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
163
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
165
166
167
168
169
  static int udf_bitmap_prealloc_blocks(struct super_block *sb,
  				      struct inode *inode,
  				      struct udf_bitmap *bitmap,
  				      uint16_t partition, uint32_t first_block,
  				      uint32_t block_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	int alloc_count = 0;
  	int bit, block, block_group, group_start;
  	int nr_groups, bitmap_nr;
  	struct buffer_head *bh;
6c79e987d   Marcin Slusarz   udf: remove some ...
176
  	__u32 part_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

1e7933def   Ingo Molnar   [PATCH] sem2mutex...
178
  	mutex_lock(&sbi->s_alloc_mutex);
6c79e987d   Marcin Slusarz   udf: remove some ...
179
  	part_len = sbi->s_partmaps[partition].s_partition_len;
3391faa4f   Roel Kluin   udf: remove redun...
180
  	if (first_block >= part_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  		goto out;
6c79e987d   Marcin Slusarz   udf: remove some ...
182
183
  	if (first_block + block_count > part_len)
  		block_count = part_len - first_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

4daa1b879   Marcin Slusarz   udf: replace loop...
185
186
187
188
189
  	do {
  		nr_groups = udf_compute_nr_groups(sb, partition);
  		block = first_block + (sizeof(struct spaceBitmapDesc) << 3);
  		block_group = block >> (sb->s_blocksize_bits + 3);
  		group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

4daa1b879   Marcin Slusarz   udf: replace loop...
191
192
193
194
  		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
  		if (bitmap_nr < 0)
  			goto out;
  		bh = bitmap->s_block_bitmap[bitmap_nr];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

4daa1b879   Marcin Slusarz   udf: replace loop...
196
  		bit = block % (sb->s_blocksize << 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

4daa1b879   Marcin Slusarz   udf: replace loop...
198
  		while (bit < (sb->s_blocksize << 3) && block_count > 0) {
363504628   Jan Kara   udf: Remove dead ...
199
  			if (!udf_clear_bit(bit, bh->b_data))
4daa1b879   Marcin Slusarz   udf: replace loop...
200
  				goto out;
4daa1b879   Marcin Slusarz   udf: replace loop...
201
202
203
204
  			block_count--;
  			alloc_count++;
  			bit++;
  			block++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  		}
4daa1b879   Marcin Slusarz   udf: replace loop...
206
207
  		mark_buffer_dirty(bh);
  	} while (block_count > 0);
28de7948a   Cyrill Gorcunov   UDF: coding style...
208
  out:
146bca72c   Jan Kara   udf: Don't write ...
209
  	udf_add_free_space(sb, partition, -alloc_count);
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
210
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  	return alloc_count;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
213
214
215
216
  static int udf_bitmap_new_block(struct super_block *sb,
  				struct inode *inode,
  				struct udf_bitmap *bitmap, uint16_t partition,
  				uint32_t goal, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
219
  	int newbit, bit = 0, block, block_group, group_start;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
222
223
224
225
  	int end_goal, nr_groups, bitmap_nr, i;
  	struct buffer_head *bh = NULL;
  	char *ptr;
  	int newblock = 0;
  
  	*err = -ENOSPC;
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
226
  	mutex_lock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227

28de7948a   Cyrill Gorcunov   UDF: coding style...
228
  repeat:
3391faa4f   Roel Kluin   udf: remove redun...
229
  	if (goal >= sbi->s_partmaps[partition].s_partition_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
237
238
239
240
  		goal = 0;
  
  	nr_groups = bitmap->s_nr_groups;
  	block = goal + (sizeof(struct spaceBitmapDesc) << 3);
  	block_group = block >> (sb->s_blocksize_bits + 3);
  	group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc);
  
  	bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
  	if (bitmap_nr < 0)
  		goto error_return;
  	bh = bitmap->s_block_bitmap[bitmap_nr];
28de7948a   Cyrill Gorcunov   UDF: coding style...
241
242
  	ptr = memscan((char *)bh->b_data + group_start, 0xFF,
  		      sb->s_blocksize - group_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

cb00ea352   Cyrill Gorcunov   UDF: coding style...
244
  	if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  		bit = block % (sb->s_blocksize << 3);
28de7948a   Cyrill Gorcunov   UDF: coding style...
246
  		if (udf_test_bit(bit, bh->b_data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  			goto got_block;
28de7948a   Cyrill Gorcunov   UDF: coding style...
248

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  		end_goal = (bit + 63) & ~63;
  		bit = udf_find_next_one_bit(bh->b_data, end_goal, bit);
  		if (bit < end_goal)
  			goto got_block;
28de7948a   Cyrill Gorcunov   UDF: coding style...
253

4b11111ab   Marcin Slusarz   udf: fix coding s...
254
255
  		ptr = memscan((char *)bh->b_data + (bit >> 3), 0xFF,
  			      sb->s_blocksize - ((bit + 7) >> 3));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  		newbit = (ptr - ((char *)bh->b_data)) << 3;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
257
  		if (newbit < sb->s_blocksize << 3) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  			bit = newbit;
  			goto search_back;
  		}
28de7948a   Cyrill Gorcunov   UDF: coding style...
261

4b11111ab   Marcin Slusarz   udf: fix coding s...
262
263
  		newbit = udf_find_next_one_bit(bh->b_data,
  					       sb->s_blocksize << 3, bit);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
264
  		if (newbit < sb->s_blocksize << 3) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
  			bit = newbit;
  			goto got_block;
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
269
270
  	for (i = 0; i < (nr_groups * 2); i++) {
  		block_group++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
276
277
278
  		if (block_group >= nr_groups)
  			block_group = 0;
  		group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc);
  
  		bitmap_nr = load_block_bitmap(sb, bitmap, block_group);
  		if (bitmap_nr < 0)
  			goto error_return;
  		bh = bitmap->s_block_bitmap[bitmap_nr];
cb00ea352   Cyrill Gorcunov   UDF: coding style...
279
  		if (i < nr_groups) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
280
281
  			ptr = memscan((char *)bh->b_data + group_start, 0xFF,
  				      sb->s_blocksize - group_start);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
282
  			if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
  				bit = (ptr - ((char *)bh->b_data)) << 3;
  				break;
  			}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
286
  		} else {
6f644e5f9   Dirk Behme   UDF: Fix compiler...
287
  			bit = udf_find_next_one_bit(bh->b_data,
28de7948a   Cyrill Gorcunov   UDF: coding style...
288
289
  						    sb->s_blocksize << 3,
  						    group_start << 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
  			if (bit < sb->s_blocksize << 3)
  				break;
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
294
  	if (i >= (nr_groups * 2)) {
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
295
  		mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  		return newblock;
  	}
  	if (bit < sb->s_blocksize << 3)
  		goto search_back;
  	else
4b11111ab   Marcin Slusarz   udf: fix coding s...
301
302
  		bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3,
  					    group_start << 3);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
303
  	if (bit >= sb->s_blocksize << 3) {
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
304
  		mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  		return 0;
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
307
  search_back:
4b11111ab   Marcin Slusarz   udf: fix coding s...
308
309
310
311
312
313
  	i = 0;
  	while (i < 7 && bit > (group_start << 3) &&
  	       udf_test_bit(bit - 1, bh->b_data)) {
  		++i;
  		--bit;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

28de7948a   Cyrill Gorcunov   UDF: coding style...
315
  got_block:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  	newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
28de7948a   Cyrill Gorcunov   UDF: coding style...
317
  		(sizeof(struct spaceBitmapDesc) << 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

cb00ea352   Cyrill Gorcunov   UDF: coding style...
319
  	if (!udf_clear_bit(bit, bh->b_data)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
323
324
325
  		udf_debug("bit already cleared for block %d
  ", bit);
  		goto repeat;
  	}
  
  	mark_buffer_dirty(bh);
146bca72c   Jan Kara   udf: Don't write ...
326
  	udf_add_free_space(sb, partition, -1);
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
327
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  	*err = 0;
  	return newblock;
28de7948a   Cyrill Gorcunov   UDF: coding style...
330
  error_return:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  	*err = -EIO;
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
332
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
  	return 0;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
335
336
337
  static void udf_table_free_blocks(struct super_block *sb,
  				  struct inode *inode,
  				  struct inode *table,
97e961fdb   Pekka Enberg   Fix the udf code ...
338
339
  				  struct kernel_lb_addr *bloc,
  				  uint32_t offset,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
340
  				  uint32_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
97e961fdb   Pekka Enberg   Fix the udf code ...
343
  	struct udf_part_map *partmap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  	uint32_t start, end;
ff116fc8d   Jan Kara   UDF: introduce st...
345
  	uint32_t elen;
5ca4e4be8   Pekka Enberg   Remove struct typ...
346
  	struct kernel_lb_addr eloc;
ff116fc8d   Jan Kara   UDF: introduce st...
347
  	struct extent_position oepos, epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
  	int8_t etype;
  	int i;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
350
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

1e7933def   Ingo Molnar   [PATCH] sem2mutex...
352
  	mutex_lock(&sbi->s_alloc_mutex);
97e961fdb   Pekka Enberg   Fix the udf code ...
353
  	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
69ecbbeda   Dan Carpenter   udf: potential in...
354
355
  	if (bloc->logicalBlockNum + count < count ||
  	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
356
357
  		udf_debug("%d < %d || %d + %d > %d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
358
359
  			  bloc->logicalBlockNum, 0,
  			  bloc->logicalBlockNum, count,
97e961fdb   Pekka Enberg   Fix the udf code ...
360
  			  partmap->s_partition_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
  		goto error_return;
  	}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
363
  	iinfo = UDF_I(table);
146bca72c   Jan Kara   udf: Don't write ...
364
  	udf_add_free_space(sb, sbi->s_partition, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365

97e961fdb   Pekka Enberg   Fix the udf code ...
366
367
  	start = bloc->logicalBlockNum + offset;
  	end = bloc->logicalBlockNum + offset + count - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

ff116fc8d   Jan Kara   UDF: introduce st...
369
  	epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  	elen = 0;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
371
  	epos.block = oepos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
372
  	epos.bh = oepos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373

28de7948a   Cyrill Gorcunov   UDF: coding style...
374
375
  	while (count &&
  	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
376
377
378
379
380
381
382
383
384
385
  		if (((eloc.logicalBlockNum +
  			(elen >> sb->s_blocksize_bits)) == start)) {
  			if ((0x3FFFFFFF - elen) <
  					(count << sb->s_blocksize_bits)) {
  				uint32_t tmp = ((0x3FFFFFFF - elen) >>
  							sb->s_blocksize_bits);
  				count -= tmp;
  				start += tmp;
  				elen = (etype << 30) |
  					(0x40000000 - sb->s_blocksize);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
386
  			} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
387
388
389
  				elen = (etype << 30) |
  					(elen +
  					(count << sb->s_blocksize_bits));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
  				start += count;
  				count = 0;
  			}
97e961fdb   Pekka Enberg   Fix the udf code ...
393
  			udf_write_aext(table, &oepos, &eloc, elen, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
394
  		} else if (eloc.logicalBlockNum == (end + 1)) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
395
396
397
398
399
400
401
402
403
  			if ((0x3FFFFFFF - elen) <
  					(count << sb->s_blocksize_bits)) {
  				uint32_t tmp = ((0x3FFFFFFF - elen) >>
  						sb->s_blocksize_bits);
  				count -= tmp;
  				end -= tmp;
  				eloc.logicalBlockNum -= tmp;
  				elen = (etype << 30) |
  					(0x40000000 - sb->s_blocksize);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
404
  			} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  				eloc.logicalBlockNum = start;
4b11111ab   Marcin Slusarz   udf: fix coding s...
406
407
408
  				elen = (etype << 30) |
  					(elen +
  					(count << sb->s_blocksize_bits));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
  				end -= count;
  				count = 0;
  			}
97e961fdb   Pekka Enberg   Fix the udf code ...
412
  			udf_write_aext(table, &oepos, &eloc, elen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
414
  		if (epos.bh != oepos.bh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  			i = -1;
ff116fc8d   Jan Kara   UDF: introduce st...
416
  			oepos.block = epos.block;
3bf25cb40   Jan Kara   udf: use get_bh()
417
418
  			brelse(oepos.bh);
  			get_bh(epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
419
420
  			oepos.bh = epos.bh;
  			oepos.offset = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
421
  		} else {
ff116fc8d   Jan Kara   UDF: introduce st...
422
  			oepos.offset = epos.offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
423
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
425
  	if (count) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
426
  		/*
4b11111ab   Marcin Slusarz   udf: fix coding s...
427
428
429
  		 * NOTE: we CANNOT use udf_add_aext here, as it can try to
  		 * allocate a new block, and since we hold the super block
  		 * lock already very bad things would happen :)
28de7948a   Cyrill Gorcunov   UDF: coding style...
430
431
432
433
434
435
436
  		 *
  		 * We copy the behavior of udf_add_aext, but instead of
  		 * trying to allocate a new block close to the existing one,
  		 * we just steal a block from the extent we are trying to add.
  		 *
  		 * It would be nice if the blocks were close together, but it
  		 * isn't required.
cb00ea352   Cyrill Gorcunov   UDF: coding style...
437
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  
  		int adsize;
5ca4e4be8   Pekka Enberg   Remove struct typ...
440
441
  		struct short_ad *sad = NULL;
  		struct long_ad *lad = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
  		struct allocExtDesc *aed;
  
  		eloc.logicalBlockNum = start;
28de7948a   Cyrill Gorcunov   UDF: coding style...
445
446
  		elen = EXT_RECORDED_ALLOCATED |
  			(count << sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447

48d6d8ff7   Marcin Slusarz   udf: cache struct...
448
  		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
449
  			adsize = sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
450
  		else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
451
  			adsize = sizeof(struct long_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
452
  		else {
3bf25cb40   Jan Kara   udf: use get_bh()
453
454
  			brelse(oepos.bh);
  			brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
  			goto error_return;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
457
  		if (epos.offset + (2 * adsize) > sb->s_blocksize) {
391e8bbd3   Al Viro   sanitize const/si...
458
  			unsigned char *sptr, *dptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  			int loffset;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
460

3bf25cb40   Jan Kara   udf: use get_bh()
461
  			brelse(oepos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
462
  			oepos = epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
  
  			/* Steal a block from the extent being free'd */
ff116fc8d   Jan Kara   UDF: introduce st...
465
  			epos.block.logicalBlockNum = eloc.logicalBlockNum;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
466
  			eloc.logicalBlockNum++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  			elen -= sb->s_blocksize;
4b11111ab   Marcin Slusarz   udf: fix coding s...
468
  			epos.bh = udf_tread(sb,
97e961fdb   Pekka Enberg   Fix the udf code ...
469
  					udf_get_lb_pblock(sb, &epos.block, 0));
4b11111ab   Marcin Slusarz   udf: fix coding s...
470
  			if (!epos.bh) {
3bf25cb40   Jan Kara   udf: use get_bh()
471
  				brelse(oepos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
  				goto error_return;
  			}
ff116fc8d   Jan Kara   UDF: introduce st...
474
  			aed = (struct allocExtDesc *)(epos.bh->b_data);
4b11111ab   Marcin Slusarz   udf: fix coding s...
475
476
  			aed->previousAllocExtLocation =
  				cpu_to_le32(oepos.block.logicalBlockNum);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
477
  			if (epos.offset + adsize > sb->s_blocksize) {
ff116fc8d   Jan Kara   UDF: introduce st...
478
  				loffset = epos.offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  				aed->lengthAllocDescs = cpu_to_le32(adsize);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
480
  				sptr = iinfo->i_ext.i_data + epos.offset
c0b344385   Marcin Slusarz   udf: remove UDF_I...
481
  								- adsize;
4b11111ab   Marcin Slusarz   udf: fix coding s...
482
483
  				dptr = epos.bh->b_data +
  					sizeof(struct allocExtDesc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  				memcpy(dptr, sptr, adsize);
4b11111ab   Marcin Slusarz   udf: fix coding s...
485
486
  				epos.offset = sizeof(struct allocExtDesc) +
  						adsize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
487
  			} else {
ff116fc8d   Jan Kara   UDF: introduce st...
488
  				loffset = epos.offset + adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  				aed->lengthAllocDescs = cpu_to_le32(0);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
490
  				if (oepos.bh) {
f5cc15dac   Jan Kara   Fix possible NULL...
491
  					sptr = oepos.bh->b_data + epos.offset;
4b11111ab   Marcin Slusarz   udf: fix coding s...
492
493
  					aed = (struct allocExtDesc *)
  						oepos.bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
494
495
  					le32_add_cpu(&aed->lengthAllocDescs,
  							adsize);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
496
  				} else {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
497
  					sptr = iinfo->i_ext.i_data +
c0b344385   Marcin Slusarz   udf: remove UDF_I...
498
  								epos.offset;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
499
  					iinfo->i_lenAlloc += adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
  					mark_inode_dirty(table);
  				}
f5cc15dac   Jan Kara   Fix possible NULL...
502
  				epos.offset = sizeof(struct allocExtDesc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  			}
6c79e987d   Marcin Slusarz   udf: remove some ...
504
  			if (sbi->s_udfrev >= 0x0200)
4b11111ab   Marcin Slusarz   udf: fix coding s...
505
506
  				udf_new_tag(epos.bh->b_data, TAG_IDENT_AED,
  					    3, 1, epos.block.logicalBlockNum,
5ca4e4be8   Pekka Enberg   Remove struct typ...
507
  					    sizeof(struct tag));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  			else
4b11111ab   Marcin Slusarz   udf: fix coding s...
509
510
  				udf_new_tag(epos.bh->b_data, TAG_IDENT_AED,
  					    2, 1, epos.block.logicalBlockNum,
5ca4e4be8   Pekka Enberg   Remove struct typ...
511
  					    sizeof(struct tag));
28de7948a   Cyrill Gorcunov   UDF: coding style...
512

48d6d8ff7   Marcin Slusarz   udf: cache struct...
513
  			switch (iinfo->i_alloc_type) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
514
  			case ICBTAG_FLAG_AD_SHORT:
5ca4e4be8   Pekka Enberg   Remove struct typ...
515
  				sad = (struct short_ad *)sptr;
4b11111ab   Marcin Slusarz   udf: fix coding s...
516
517
518
519
520
521
522
  				sad->extLength = cpu_to_le32(
  					EXT_NEXT_EXTENT_ALLOCDECS |
  					sb->s_blocksize);
  				sad->extPosition =
  					cpu_to_le32(epos.block.logicalBlockNum);
  				break;
  			case ICBTAG_FLAG_AD_LONG:
5ca4e4be8   Pekka Enberg   Remove struct typ...
523
  				lad = (struct long_ad *)sptr;
4b11111ab   Marcin Slusarz   udf: fix coding s...
524
525
526
527
528
529
  				lad->extLength = cpu_to_le32(
  					EXT_NEXT_EXTENT_ALLOCDECS |
  					sb->s_blocksize);
  				lad->extLocation =
  					cpu_to_lelb(epos.block);
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  			}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
531
  			if (oepos.bh) {
ff116fc8d   Jan Kara   UDF: introduce st...
532
533
  				udf_update_tag(oepos.bh->b_data, loffset);
  				mark_buffer_dirty(oepos.bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
534
  			} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  				mark_inode_dirty(table);
28de7948a   Cyrill Gorcunov   UDF: coding style...
536
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  		}
4b11111ab   Marcin Slusarz   udf: fix coding s...
538
539
  		/* It's possible that stealing the block emptied the extent */
  		if (elen) {
97e961fdb   Pekka Enberg   Fix the udf code ...
540
  			udf_write_aext(table, &epos, &eloc, elen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541

cb00ea352   Cyrill Gorcunov   UDF: coding style...
542
  			if (!epos.bh) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
543
  				iinfo->i_lenAlloc += adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  				mark_inode_dirty(table);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
545
  			} else {
ff116fc8d   Jan Kara   UDF: introduce st...
546
  				aed = (struct allocExtDesc *)epos.bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
547
  				le32_add_cpu(&aed->lengthAllocDescs, adsize);
ff116fc8d   Jan Kara   UDF: introduce st...
548
549
  				udf_update_tag(epos.bh->b_data, epos.offset);
  				mark_buffer_dirty(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
  			}
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
553
554
  	brelse(epos.bh);
  	brelse(oepos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555

28de7948a   Cyrill Gorcunov   UDF: coding style...
556
  error_return:
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
557
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
  	return;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
560
561
562
563
  static int udf_table_prealloc_blocks(struct super_block *sb,
  				     struct inode *inode,
  				     struct inode *table, uint16_t partition,
  				     uint32_t first_block, uint32_t block_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	int alloc_count = 0;
ff116fc8d   Jan Kara   UDF: introduce st...
567
  	uint32_t elen, adsize;
5ca4e4be8   Pekka Enberg   Remove struct typ...
568
  	struct kernel_lb_addr eloc;
ff116fc8d   Jan Kara   UDF: introduce st...
569
  	struct extent_position epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
  	int8_t etype = -1;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
571
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572

3391faa4f   Roel Kluin   udf: remove redun...
573
  	if (first_block >= sbi->s_partmaps[partition].s_partition_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  		return 0;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
575
576
  	iinfo = UDF_I(table);
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
577
  		adsize = sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
578
  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
579
  		adsize = sizeof(struct long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  	else
  		return 0;
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
582
  	mutex_lock(&sbi->s_alloc_mutex);
ff116fc8d   Jan Kara   UDF: introduce st...
583
  	epos.offset = sizeof(struct unallocSpaceEntry);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
584
  	epos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
585
  	epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	eloc.logicalBlockNum = 0xFFFFFFFF;
28de7948a   Cyrill Gorcunov   UDF: coding style...
587
588
  	while (first_block != eloc.logicalBlockNum &&
  	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
  		udf_debug("eloc=%d, elen=%d, first_block=%d
  ",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
591
  			  eloc.logicalBlockNum, elen, first_block);
28de7948a   Cyrill Gorcunov   UDF: coding style...
592
  		; /* empty loop body */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
594
  	if (first_block == eloc.logicalBlockNum) {
ff116fc8d   Jan Kara   UDF: introduce st...
595
  		epos.offset -= adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  
  		alloc_count = (elen >> sb->s_blocksize_bits);
363504628   Jan Kara   udf: Remove dead ...
598
  		if (alloc_count > block_count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
  			alloc_count = block_count;
  			eloc.logicalBlockNum += alloc_count;
  			elen -= (alloc_count << sb->s_blocksize_bits);
97e961fdb   Pekka Enberg   Fix the udf code ...
602
  			udf_write_aext(table, &epos, &eloc,
4b11111ab   Marcin Slusarz   udf: fix coding s...
603
604
605
606
  					(etype << 30) | elen, 1);
  		} else
  			udf_delete_aext(table, epos, eloc,
  					(etype << 30) | elen);
28de7948a   Cyrill Gorcunov   UDF: coding style...
607
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  		alloc_count = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
609
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610

3bf25cb40   Jan Kara   udf: use get_bh()
611
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612

146bca72c   Jan Kara   udf: Don't write ...
613
614
  	if (alloc_count)
  		udf_add_free_space(sb, partition, -alloc_count);
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
615
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
  	return alloc_count;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
618
619
620
621
  static int udf_table_new_block(struct super_block *sb,
  			       struct inode *inode,
  			       struct inode *table, uint16_t partition,
  			       uint32_t goal, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
625
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
  	uint32_t newblock = 0, adsize;
ff116fc8d   Jan Kara   UDF: introduce st...
626
  	uint32_t elen, goal_elen = 0;
5ca4e4be8   Pekka Enberg   Remove struct typ...
627
  	struct kernel_lb_addr eloc, uninitialized_var(goal_eloc);
ff116fc8d   Jan Kara   UDF: introduce st...
628
  	struct extent_position epos, goal_epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  	int8_t etype;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
630
  	struct udf_inode_info *iinfo = UDF_I(table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
  
  	*err = -ENOSPC;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
633
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
634
  		adsize = sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
635
  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
636
  		adsize = sizeof(struct long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
  	else
  		return newblock;
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
639
  	mutex_lock(&sbi->s_alloc_mutex);
3391faa4f   Roel Kluin   udf: remove redun...
640
  	if (goal >= sbi->s_partmaps[partition].s_partition_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
  		goal = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
642
643
644
645
  	/* We search for the closest matching block to goal. If we find
  	   a exact hit, we stop. Otherwise we keep going till we run out
  	   of extents. We store the buffer_head, bloc, and extoffset
  	   of the current closest match and use that when we are done.
cb00ea352   Cyrill Gorcunov   UDF: coding style...
646
  	 */
ff116fc8d   Jan Kara   UDF: introduce st...
647
  	epos.offset = sizeof(struct unallocSpaceEntry);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
648
  	epos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
649
  	epos.bh = goal_epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650

28de7948a   Cyrill Gorcunov   UDF: coding style...
651
652
  	while (spread &&
  	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
653
  		if (goal >= eloc.logicalBlockNum) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
654
655
  			if (goal < eloc.logicalBlockNum +
  					(elen >> sb->s_blocksize_bits))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
  				nspread = 0;
  			else
  				nspread = goal - eloc.logicalBlockNum -
28de7948a   Cyrill Gorcunov   UDF: coding style...
659
660
  					(elen >> sb->s_blocksize_bits);
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
  			nspread = eloc.logicalBlockNum - goal;
28de7948a   Cyrill Gorcunov   UDF: coding style...
662
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663

cb00ea352   Cyrill Gorcunov   UDF: coding style...
664
  		if (nspread < spread) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  			spread = nspread;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
666
  			if (goal_epos.bh != epos.bh) {
3bf25cb40   Jan Kara   udf: use get_bh()
667
  				brelse(goal_epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
668
  				goal_epos.bh = epos.bh;
3bf25cb40   Jan Kara   udf: use get_bh()
669
  				get_bh(goal_epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  			}
ff116fc8d   Jan Kara   UDF: introduce st...
671
672
  			goal_epos.block = epos.block;
  			goal_epos.offset = epos.offset - adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  			goal_eloc = eloc;
  			goal_elen = (etype << 30) | elen;
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
677
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678

cb00ea352   Cyrill Gorcunov   UDF: coding style...
679
  	if (spread == 0xFFFFFFFF) {
3bf25cb40   Jan Kara   udf: use get_bh()
680
  		brelse(goal_epos.bh);
1e7933def   Ingo Molnar   [PATCH] sem2mutex...
681
  		mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
689
690
  		return 0;
  	}
  
  	/* Only allocate blocks from the beginning of the extent.
  	   That way, we only delete (empty) extents, never have to insert an
  	   extent because of splitting */
  	/* This works, but very poorly.... */
  
  	newblock = goal_eloc.logicalBlockNum;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
691
  	goal_eloc.logicalBlockNum++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  	goal_elen -= sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
  
  	if (goal_elen)
97e961fdb   Pekka Enberg   Fix the udf code ...
695
  		udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  	else
ff116fc8d   Jan Kara   UDF: introduce st...
697
  		udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
3bf25cb40   Jan Kara   udf: use get_bh()
698
  	brelse(goal_epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699

146bca72c   Jan Kara   udf: Don't write ...
700
  	udf_add_free_space(sb, partition, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701

1e7933def   Ingo Molnar   [PATCH] sem2mutex...
702
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
  	*err = 0;
  	return newblock;
  }
97e961fdb   Pekka Enberg   Fix the udf code ...
706
707
708
  void udf_free_blocks(struct super_block *sb, struct inode *inode,
  		     struct kernel_lb_addr *bloc, uint32_t offset,
  		     uint32_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
  {
97e961fdb   Pekka Enberg   Fix the udf code ...
710
  	uint16_t partition = bloc->partitionReferenceNum;
6c79e987d   Marcin Slusarz   udf: remove some ...
711
  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712

6c79e987d   Marcin Slusarz   udf: remove some ...
713
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
e650b94ad   Jan Kara   udf: fix sparse w...
714
715
  		udf_bitmap_free_blocks(sb, inode, map->s_uspace.s_bitmap,
  				       bloc, offset, count);
6c79e987d   Marcin Slusarz   udf: remove some ...
716
  	} else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) {
e650b94ad   Jan Kara   udf: fix sparse w...
717
718
  		udf_table_free_blocks(sb, inode, map->s_uspace.s_table,
  				      bloc, offset, count);
6c79e987d   Marcin Slusarz   udf: remove some ...
719
  	} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) {
e650b94ad   Jan Kara   udf: fix sparse w...
720
721
  		udf_bitmap_free_blocks(sb, inode, map->s_fspace.s_bitmap,
  				       bloc, offset, count);
6c79e987d   Marcin Slusarz   udf: remove some ...
722
  	} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) {
e650b94ad   Jan Kara   udf: fix sparse w...
723
724
  		udf_table_free_blocks(sb, inode, map->s_fspace.s_table,
  				      bloc, offset, count);
28de7948a   Cyrill Gorcunov   UDF: coding style...
725
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
727
728
729
730
  inline int udf_prealloc_blocks(struct super_block *sb,
  			       struct inode *inode,
  			       uint16_t partition, uint32_t first_block,
  			       uint32_t block_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
732
  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
4b11111ab   Marcin Slusarz   udf: fix coding s...
733
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  		return udf_bitmap_prealloc_blocks(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
735
  						  map->s_uspace.s_bitmap,
4b11111ab   Marcin Slusarz   udf: fix coding s...
736
737
738
  						  partition, first_block,
  						  block_count);
  	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  		return udf_table_prealloc_blocks(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
740
  						 map->s_uspace.s_table,
4b11111ab   Marcin Slusarz   udf: fix coding s...
741
742
743
  						 partition, first_block,
  						 block_count);
  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  		return udf_bitmap_prealloc_blocks(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
745
  						  map->s_fspace.s_bitmap,
4b11111ab   Marcin Slusarz   udf: fix coding s...
746
747
748
  						  partition, first_block,
  						  block_count);
  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
  		return udf_table_prealloc_blocks(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
750
  						 map->s_fspace.s_table,
4b11111ab   Marcin Slusarz   udf: fix coding s...
751
752
753
  						 partition, first_block,
  						 block_count);
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
  		return 0;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
756
757
758
  inline int udf_new_block(struct super_block *sb,
  			 struct inode *inode,
  			 uint16_t partition, uint32_t goal, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
760
  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
3bf25cb40   Jan Kara   udf: use get_bh()
761

4b11111ab   Marcin Slusarz   udf: fix coding s...
762
763
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
  		return udf_bitmap_new_block(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
764
  					   map->s_uspace.s_bitmap,
28de7948a   Cyrill Gorcunov   UDF: coding style...
765
  					   partition, goal, err);
4b11111ab   Marcin Slusarz   udf: fix coding s...
766
  	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  		return udf_table_new_block(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
768
  					   map->s_uspace.s_table,
28de7948a   Cyrill Gorcunov   UDF: coding style...
769
  					   partition, goal, err);
4b11111ab   Marcin Slusarz   udf: fix coding s...
770
  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  		return udf_bitmap_new_block(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
772
  					    map->s_fspace.s_bitmap,
28de7948a   Cyrill Gorcunov   UDF: coding style...
773
  					    partition, goal, err);
4b11111ab   Marcin Slusarz   udf: fix coding s...
774
  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
  		return udf_table_new_block(sb, inode,
6c79e987d   Marcin Slusarz   udf: remove some ...
776
  					   map->s_fspace.s_table,
28de7948a   Cyrill Gorcunov   UDF: coding style...
777
  					   partition, goal, err);
4b11111ab   Marcin Slusarz   udf: fix coding s...
778
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
782
  		*err = -EIO;
  		return 0;
  	}
  }