Blame view

fs/udf/inode.c 65.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * inode.c
   *
   * PURPOSE
   *  Inode 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
   * 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) 1998 Dave Boynton
   *  (C) 1998-2004 Ben Fennema
   *  (C) 1999-2000 Stelias Computing Inc
   *
   * HISTORY
   *
   *  10/04/98 dgb  Added rudimentary directory functions
   *  10/07/98      Fully working udf_block_map! It works!
   *  11/25/98      bmap altered to better support extents
4b11111ab   Marcin Slusarz   udf: fix coding s...
22
23
   *  12/06/98 blf  partition support in udf_iget, udf_block_map
   *                and udf_read_inode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
30
31
32
33
   *  12/12/98      rewrote udf_block_map to handle next extents and descs across
   *                block boundaries (which is not actually allowed)
   *  12/20/98      added support for strategy 4096
   *  03/07/99      rewrote udf_block_map (again)
   *                New funcs, inode_bmap, udf_next_aext
   *  04/19/99      Support for writing device EA's for major/minor #
   */
  
  #include "udfdecl.h"
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  #include <linux/module.h>
  #include <linux/pagemap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  #include <linux/writeback.h>
  #include <linux/slab.h>
f845fced9   Bob Copeland   udf: use crc_itu_...
38
  #include <linux/crc-itu-t.h>
bc1123239   Namjae Jeon   udf: Add readpage...
39
  #include <linux/mpage.h>
e2e40f2c1   Christoph Hellwig   fs: move struct k...
40
  #include <linux/uio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
  
  #include "udf_i.h"
  #include "udf_sb.h"
  
  MODULE_AUTHOR("Ben Fennema");
  MODULE_DESCRIPTION("Universal Disk Format Filesystem");
  MODULE_LICENSE("GPL");
  
  #define EXTENT_MERGE_SIZE 5
faa17292f   Al Viro   udf: propagate um...
50
  static umode_t udf_convert_permissions(struct fileEntry *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  static int udf_update_inode(struct inode *, int);
49521de11   Jan Kara   udf: Remove BKL f...
52
  static int udf_sync_inode(struct inode *inode);
647bd61a5   Cyrill Gorcunov   UDF: check for al...
53
  static int udf_alloc_i_data(struct inode *inode, size_t size);
7b0b0933a   Jan Kara   udf: Cleanup call...
54
  static sector_t inode_getblk(struct inode *, sector_t, int *, int *);
ff116fc8d   Jan Kara   UDF: introduce st...
55
  static int8_t udf_insert_aext(struct inode *, struct extent_position,
5ca4e4be8   Pekka Enberg   Remove struct typ...
56
  			      struct kernel_lb_addr, uint32_t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  static void udf_split_extents(struct inode *, int *, int, int,
5ca4e4be8   Pekka Enberg   Remove struct typ...
58
  			      struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  static void udf_prealloc_extents(struct inode *, int, int,
5ca4e4be8   Pekka Enberg   Remove struct typ...
60
  				 struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  static void udf_merge_extents(struct inode *,
5ca4e4be8   Pekka Enberg   Remove struct typ...
62
  			      struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  static void udf_update_extents(struct inode *,
5ca4e4be8   Pekka Enberg   Remove struct typ...
64
  			       struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
65
  			       struct extent_position *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
99600051b   Namjae Jeon   udf: add extent c...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  static void __udf_clear_extent_cache(struct inode *inode)
  {
  	struct udf_inode_info *iinfo = UDF_I(inode);
  
  	if (iinfo->cached_extent.lstart != -1) {
  		brelse(iinfo->cached_extent.epos.bh);
  		iinfo->cached_extent.lstart = -1;
  	}
  }
  
  /* Invalidate extent cache */
  static void udf_clear_extent_cache(struct inode *inode)
  {
  	struct udf_inode_info *iinfo = UDF_I(inode);
  
  	spin_lock(&iinfo->i_extent_cache_lock);
  	__udf_clear_extent_cache(inode);
  	spin_unlock(&iinfo->i_extent_cache_lock);
  }
  
  /* Return contents of extent cache */
  static int udf_read_extent_cache(struct inode *inode, loff_t bcount,
  				 loff_t *lbcount, struct extent_position *pos)
  {
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	int ret = 0;
  
  	spin_lock(&iinfo->i_extent_cache_lock);
  	if ((iinfo->cached_extent.lstart <= bcount) &&
  	    (iinfo->cached_extent.lstart != -1)) {
  		/* Cache hit */
  		*lbcount = iinfo->cached_extent.lstart;
  		memcpy(pos, &iinfo->cached_extent.epos,
  		       sizeof(struct extent_position));
  		if (pos->bh)
  			get_bh(pos->bh);
  		ret = 1;
  	}
  	spin_unlock(&iinfo->i_extent_cache_lock);
  	return ret;
  }
  
  /* Add extent to extent cache */
  static void udf_update_extent_cache(struct inode *inode, loff_t estart,
  				    struct extent_position *pos, int next_epos)
  {
  	struct udf_inode_info *iinfo = UDF_I(inode);
  
  	spin_lock(&iinfo->i_extent_cache_lock);
  	/* Invalidate previously cached extent */
  	__udf_clear_extent_cache(inode);
  	if (pos->bh)
  		get_bh(pos->bh);
  	memcpy(&iinfo->cached_extent.epos, pos,
  	       sizeof(struct extent_position));
  	iinfo->cached_extent.lstart = estart;
  	if (next_epos)
  		switch (iinfo->i_alloc_type) {
  		case ICBTAG_FLAG_AD_SHORT:
  			iinfo->cached_extent.epos.offset -=
  			sizeof(struct short_ad);
  			break;
  		case ICBTAG_FLAG_AD_LONG:
  			iinfo->cached_extent.epos.offset -=
  			sizeof(struct long_ad);
  		}
  	spin_unlock(&iinfo->i_extent_cache_lock);
  }
b1e321266   Christoph Hellwig   udf: kill useless...
135

3aac2b62e   Al Viro   switch udf to ->e...
136
  void udf_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  {
2c948b3f8   Jan Kara   udf: Avoid IO in ...
138
  	struct udf_inode_info *iinfo = UDF_I(inode);
3aac2b62e   Al Viro   switch udf to ->e...
139
  	int want_delete = 0;
3aac2b62e   Al Viro   switch udf to ->e...
140
141
  	if (!inode->i_nlink && !is_bad_inode(inode)) {
  		want_delete = 1;
7e49b6f24   Jan Kara   udf: Convert UDF ...
142
  		udf_setsize(inode, 0);
3aac2b62e   Al Viro   switch udf to ->e...
143
  		udf_update_inode(inode, IS_SYNC(inode));
91b0abe36   Johannes Weiner   mm + fs: store sh...
144
145
  	}
  	truncate_inode_pages_final(&inode->i_data);
3aac2b62e   Al Viro   switch udf to ->e...
146
  	invalidate_inode_buffers(inode);
dbd5768f8   Jan Kara   vfs: Rename end_w...
147
  	clear_inode(inode);
2c948b3f8   Jan Kara   udf: Avoid IO in ...
148
149
  	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
  	    inode->i_size != iinfo->i_lenExtents) {
78ace70c4   Joe Perches   udf: Convert prin...
150
151
152
153
154
  		udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.
  ",
  			 inode->i_ino, inode->i_mode,
  			 (unsigned long long)inode->i_size,
  			 (unsigned long long)iinfo->i_lenExtents);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  	}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
156
157
  	kfree(iinfo->i_ext.i_data);
  	iinfo->i_ext.i_data = NULL;
99600051b   Namjae Jeon   udf: add extent c...
158
  	udf_clear_extent_cache(inode);
3aac2b62e   Al Viro   switch udf to ->e...
159
  	if (want_delete) {
3aac2b62e   Al Viro   switch udf to ->e...
160
  		udf_free_inode(inode);
3aac2b62e   Al Viro   switch udf to ->e...
161
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  }
5eec54fcd   Ian Abbott   UDF: Add support ...
163
164
165
166
167
168
169
  static void udf_write_failed(struct address_space *mapping, loff_t to)
  {
  	struct inode *inode = mapping->host;
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	loff_t isize = inode->i_size;
  
  	if (to > isize) {
7caef2676   Kirill A. Shutemov   truncate: drop 'o...
170
  		truncate_pagecache(inode, isize);
5eec54fcd   Ian Abbott   UDF: Add support ...
171
172
  		if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
  			down_write(&iinfo->i_data_sem);
99600051b   Namjae Jeon   udf: add extent c...
173
  			udf_clear_extent_cache(inode);
5eec54fcd   Ian Abbott   UDF: Add support ...
174
175
176
177
178
  			udf_truncate_extents(inode);
  			up_write(&iinfo->i_data_sem);
  		}
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
  static int udf_writepage(struct page *page, struct writeback_control *wbc)
  {
  	return block_write_full_page(page, udf_get_block, wbc);
  }
378b8e1ad   Namjae Jeon   udf: add writepag...
183
184
185
186
187
  static int udf_writepages(struct address_space *mapping,
  			struct writeback_control *wbc)
  {
  	return mpage_writepages(mapping, wbc, udf_get_block);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  static int udf_readpage(struct file *file, struct page *page)
  {
bc1123239   Namjae Jeon   udf: Add readpage...
190
191
192
193
194
195
196
  	return mpage_readpage(page, udf_get_block);
  }
  
  static int udf_readpages(struct file *file, struct address_space *mapping,
  			struct list_head *pages, unsigned nr_pages)
  {
  	return mpage_readpages(mapping, pages, nr_pages, udf_get_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  }
be021ee41   Nick Piggin   udf: convert to n...
198
199
200
  static int udf_write_begin(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  {
155130a4f   Christoph Hellwig   get rid of block_...
202
203
204
  	int ret;
  
  	ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block);
5eec54fcd   Ian Abbott   UDF: Add support ...
205
206
207
208
  	if (unlikely(ret))
  		udf_write_failed(mapping, pos + len);
  	return ret;
  }
155130a4f   Christoph Hellwig   get rid of block_...
209

c8b8e32d7   Christoph Hellwig   direct-io: elimin...
210
  static ssize_t udf_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
5eec54fcd   Ian Abbott   UDF: Add support ...
211
212
213
214
  {
  	struct file *file = iocb->ki_filp;
  	struct address_space *mapping = file->f_mapping;
  	struct inode *inode = mapping->host;
a6cbcd4a4   Al Viro   get rid of pointl...
215
  	size_t count = iov_iter_count(iter);
5eec54fcd   Ian Abbott   UDF: Add support ...
216
  	ssize_t ret;
c8b8e32d7   Christoph Hellwig   direct-io: elimin...
217
  	ret = blockdev_direct_IO(iocb, inode, iter, udf_get_block);
6f6737631   Omar Sandoval   direct_IO: use io...
218
  	if (unlikely(ret < 0 && iov_iter_rw(iter) == WRITE))
c8b8e32d7   Christoph Hellwig   direct-io: elimin...
219
  		udf_write_failed(mapping, iocb->ki_pos + count);
155130a4f   Christoph Hellwig   get rid of block_...
220
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
  }
  
  static sector_t udf_bmap(struct address_space *mapping, sector_t block)
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
225
  	return generic_block_bmap(mapping, block, udf_get_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  }
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
227
  const struct address_space_operations udf_aops = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
228
  	.readpage	= udf_readpage,
bc1123239   Namjae Jeon   udf: Add readpage...
229
  	.readpages	= udf_readpages,
28de7948a   Cyrill Gorcunov   UDF: coding style...
230
  	.writepage	= udf_writepage,
378b8e1ad   Namjae Jeon   udf: add writepag...
231
  	.writepages	= udf_writepages,
5eec54fcd   Ian Abbott   UDF: Add support ...
232
233
234
  	.write_begin	= udf_write_begin,
  	.write_end	= generic_write_end,
  	.direct_IO	= udf_direct_IO,
28de7948a   Cyrill Gorcunov   UDF: coding style...
235
  	.bmap		= udf_bmap,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  };
d2eb8c359   Jan Kara   udf: Fix deadlock...
237
238
239
240
241
242
  /*
   * Expand file stored in ICB to a normal one-block-file
   *
   * This function requires i_data_sem for writing and releases it.
   * This function requires i_mutex held
   */
7e49b6f24   Jan Kara   udf: Convert UDF ...
243
  int udf_expand_file_adinicb(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
246
  {
  	struct page *page;
  	char *kaddr;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
247
  	struct udf_inode_info *iinfo = UDF_I(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
248
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  	struct writeback_control udf_wbc = {
  		.sync_mode = WB_SYNC_NONE,
  		.nr_to_write = 1,
  	};
5955102c9   Al Viro   wrappers for ->i_...
253
  	WARN_ON_ONCE(!inode_is_locked(inode));
48d6d8ff7   Marcin Slusarz   udf: cache struct...
254
  	if (!iinfo->i_lenAlloc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
48d6d8ff7   Marcin Slusarz   udf: cache struct...
256
  			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  		else
48d6d8ff7   Marcin Slusarz   udf: cache struct...
258
  			iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
7e49b6f24   Jan Kara   udf: Convert UDF ...
259
260
  		/* from now on we have normal address_space methods */
  		inode->i_data.a_ops = &udf_aops;
d2eb8c359   Jan Kara   udf: Fix deadlock...
261
  		up_write(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  		mark_inode_dirty(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
263
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  	}
d2eb8c359   Jan Kara   udf: Fix deadlock...
265
266
267
268
269
  	/*
  	 * Release i_data_sem so that we can lock a page - page lock ranks
  	 * above i_data_sem. i_mutex still protects us against file changes.
  	 */
  	up_write(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270

7e49b6f24   Jan Kara   udf: Convert UDF ...
271
272
273
  	page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
  	if (!page)
  		return -ENOMEM;
cd7619d6b   Matt Mackall   [PATCH] Extermina...
274

cb00ea352   Cyrill Gorcunov   UDF: coding style...
275
  	if (!PageUptodate(page)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  		kaddr = kmap(page);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
277
  		memset(kaddr + iinfo->i_lenAlloc, 0x00,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
278
  		       PAGE_SIZE - iinfo->i_lenAlloc);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
279
280
  		memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr,
  			iinfo->i_lenAlloc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
  		flush_dcache_page(page);
  		SetPageUptodate(page);
  		kunmap(page);
  	}
d2eb8c359   Jan Kara   udf: Fix deadlock...
285
  	down_write(&iinfo->i_data_sem);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
286
287
288
  	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00,
  	       iinfo->i_lenAlloc);
  	iinfo->i_lenAlloc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
48d6d8ff7   Marcin Slusarz   udf: cache struct...
290
  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  	else
48d6d8ff7   Marcin Slusarz   udf: cache struct...
292
  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
7e49b6f24   Jan Kara   udf: Convert UDF ...
293
294
  	/* from now on we have normal address_space methods */
  	inode->i_data.a_ops = &udf_aops;
d2eb8c359   Jan Kara   udf: Fix deadlock...
295
  	up_write(&iinfo->i_data_sem);
7e49b6f24   Jan Kara   udf: Convert UDF ...
296
297
298
299
300
  	err = inode->i_data.a_ops->writepage(page, &udf_wbc);
  	if (err) {
  		/* Restore everything back so that we don't lose data... */
  		lock_page(page);
  		kaddr = kmap(page);
d2eb8c359   Jan Kara   udf: Fix deadlock...
301
  		down_write(&iinfo->i_data_sem);
7e49b6f24   Jan Kara   udf: Convert UDF ...
302
303
304
305
306
307
  		memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr,
  		       inode->i_size);
  		kunmap(page);
  		unlock_page(page);
  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
  		inode->i_data.a_ops = &udf_adinicb_aops;
d2eb8c359   Jan Kara   udf: Fix deadlock...
308
  		up_write(&iinfo->i_data_sem);
7e49b6f24   Jan Kara   udf: Convert UDF ...
309
  	}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
310
  	put_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  	mark_inode_dirty(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
312
313
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
315
316
  struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
  					   int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  {
  	int newblock;
ff116fc8d   Jan Kara   UDF: introduce st...
319
  	struct buffer_head *dbh = NULL;
5ca4e4be8   Pekka Enberg   Remove struct typ...
320
  	struct kernel_lb_addr eloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	uint8_t alloctype;
ff116fc8d   Jan Kara   UDF: introduce st...
322
  	struct extent_position epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
  
  	struct udf_fileident_bh sfibh, dfibh;
af793295b   Jan Kara   udf: cleanup dire...
325
326
  	loff_t f_pos = udf_ext0_offset(inode);
  	int size = udf_ext0_offset(inode) + inode->i_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  	struct fileIdentDesc cfi, *sfi, *dfi;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
328
  	struct udf_inode_info *iinfo = UDF_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
333
  
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
  		alloctype = ICBTAG_FLAG_AD_SHORT;
  	else
  		alloctype = ICBTAG_FLAG_AD_LONG;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
334
  	if (!inode->i_size) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
335
  		iinfo->i_alloc_type = alloctype;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
341
  		mark_inode_dirty(inode);
  		return NULL;
  	}
  
  	/* alloc block, and copy data to it */
  	*block = udf_new_block(inode->i_sb, inode,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
342
343
  			       iinfo->i_location.partitionReferenceNum,
  			       iinfo->i_location.logicalBlockNum, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
  	if (!(*block))
  		return NULL;
  	newblock = udf_get_pblock(inode->i_sb, *block,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
347
  				  iinfo->i_location.partitionReferenceNum,
c0b344385   Marcin Slusarz   udf: remove UDF_I...
348
  				0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
353
354
355
356
357
358
  	if (!newblock)
  		return NULL;
  	dbh = udf_tgetblk(inode->i_sb, newblock);
  	if (!dbh)
  		return NULL;
  	lock_buffer(dbh);
  	memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize);
  	set_buffer_uptodate(dbh);
  	unlock_buffer(dbh);
  	mark_buffer_dirty_inode(dbh, inode);
4b11111ab   Marcin Slusarz   udf: fix coding s...
359
  	sfibh.soffset = sfibh.eoffset =
af793295b   Jan Kara   udf: cleanup dire...
360
  			f_pos & (inode->i_sb->s_blocksize - 1);
ff116fc8d   Jan Kara   UDF: introduce st...
361
  	sfibh.sbh = sfibh.ebh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
  	dfibh.soffset = dfibh.eoffset = 0;
  	dfibh.sbh = dfibh.ebh = dbh;
af793295b   Jan Kara   udf: cleanup dire...
364
  	while (f_pos < size) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
365
  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
4b11111ab   Marcin Slusarz   udf: fix coding s...
366
367
  		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL,
  					 NULL, NULL, NULL);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
368
  		if (!sfi) {
3bf25cb40   Jan Kara   udf: use get_bh()
369
  			brelse(dbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  			return NULL;
  		}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
372
  		iinfo->i_alloc_type = alloctype;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
377
  		sfi->descTag.tagLocation = cpu_to_le32(*block);
  		dfibh.soffset = dfibh.eoffset;
  		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
  		dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
  		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
4b11111ab   Marcin Slusarz   udf: fix coding s...
378
379
  				 sfi->fileIdent +
  					le16_to_cpu(sfi->lengthOfImpUse))) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
380
  			iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
3bf25cb40   Jan Kara   udf: use get_bh()
381
  			brelse(dbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
  			return NULL;
  		}
  	}
  	mark_buffer_dirty_inode(dbh, inode);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
386
387
388
  	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0,
  		iinfo->i_lenAlloc);
  	iinfo->i_lenAlloc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  	eloc.logicalBlockNum = *block;
4b11111ab   Marcin Slusarz   udf: fix coding s...
390
  	eloc.partitionReferenceNum =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
391
  				iinfo->i_location.partitionReferenceNum;
2c948b3f8   Jan Kara   udf: Avoid IO in ...
392
  	iinfo->i_lenExtents = inode->i_size;
ff116fc8d   Jan Kara   UDF: introduce st...
393
  	epos.bh = NULL;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
394
  	epos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
395
  	epos.offset = udf_file_entry_alloc_offset(inode);
2c948b3f8   Jan Kara   udf: Avoid IO in ...
396
  	udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  	/* UniqueID stuff */
3bf25cb40   Jan Kara   udf: use get_bh()
398
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  	mark_inode_dirty(inode);
  	return dbh;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
402
403
  static int udf_get_block(struct inode *inode, sector_t block,
  			 struct buffer_head *bh_result, int create)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
  {
  	int err, new;
1ed161718   Marcin Slusarz   udf: fix 3 signed...
406
  	sector_t phys = 0;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
407
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408

cb00ea352   Cyrill Gorcunov   UDF: coding style...
409
  	if (!create) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
412
413
414
415
416
417
  		phys = udf_block_map(inode, block);
  		if (phys)
  			map_bh(bh_result, inode->i_sb, phys);
  		return 0;
  	}
  
  	err = -EIO;
  	new = 0;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
418
  	iinfo = UDF_I(inode);
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
419
420
  
  	down_write(&iinfo->i_data_sem);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
421
422
423
  	if (block == iinfo->i_next_alloc_block + 1) {
  		iinfo->i_next_alloc_block++;
  		iinfo->i_next_alloc_goal++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  	}
99600051b   Namjae Jeon   udf: add extent c...
425
  	udf_clear_extent_cache(inode);
7b0b0933a   Jan Kara   udf: Cleanup call...
426
427
  	phys = inode_getblk(inode, block, &err, &new);
  	if (!phys)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  		goto abort;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
  
  	if (new)
  		set_buffer_new(bh_result);
  	map_bh(bh_result, inode->i_sb, phys);
28de7948a   Cyrill Gorcunov   UDF: coding style...
433
434
  
  abort:
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
435
  	up_write(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
438
439
  static struct buffer_head *udf_getblk(struct inode *inode, long block,
  				      int create, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  {
28de7948a   Cyrill Gorcunov   UDF: coding style...
441
  	struct buffer_head *bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
445
446
  	struct buffer_head dummy;
  
  	dummy.b_state = 0;
  	dummy.b_blocknr = -1000;
  	*err = udf_get_block(inode, block, &dummy, create);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
447
  	if (!*err && buffer_mapped(&dummy)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
449
  		if (buffer_new(&dummy)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
454
455
456
457
  			lock_buffer(bh);
  			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
  			set_buffer_uptodate(bh);
  			unlock_buffer(bh);
  			mark_buffer_dirty_inode(bh, inode);
  		}
  		return bh;
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
458

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
  	return NULL;
  }
31170b6ad   Jan Kara   udf: support file...
461
  /* Extend the file by 'blocks' blocks, return the number of extents added */
7e49b6f24   Jan Kara   udf: Convert UDF ...
462
463
464
465
  static int udf_do_extend_file(struct inode *inode,
  			      struct extent_position *last_pos,
  			      struct kernel_long_ad *last_ext,
  			      sector_t blocks)
31170b6ad   Jan Kara   udf: support file...
466
467
468
469
  {
  	sector_t add;
  	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
  	struct super_block *sb = inode->i_sb;
5ca4e4be8   Pekka Enberg   Remove struct typ...
470
  	struct kernel_lb_addr prealloc_loc = {};
31170b6ad   Jan Kara   udf: support file...
471
  	int prealloc_len = 0;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
472
  	struct udf_inode_info *iinfo;
7e49b6f24   Jan Kara   udf: Convert UDF ...
473
  	int err;
31170b6ad   Jan Kara   udf: support file...
474
475
476
477
478
  
  	/* The previous extent is fake and we should not extend by anything
  	 * - there's nothing to do... */
  	if (!blocks && fake)
  		return 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
479

48d6d8ff7   Marcin Slusarz   udf: cache struct...
480
  	iinfo = UDF_I(inode);
31170b6ad   Jan Kara   udf: support file...
481
482
483
  	/* Round the last extent up to a multiple of block size */
  	if (last_ext->extLength & (sb->s_blocksize - 1)) {
  		last_ext->extLength =
28de7948a   Cyrill Gorcunov   UDF: coding style...
484
485
486
  			(last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
  			(((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
  			  sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
48d6d8ff7   Marcin Slusarz   udf: cache struct...
487
488
  		iinfo->i_lenExtents =
  			(iinfo->i_lenExtents + sb->s_blocksize - 1) &
28de7948a   Cyrill Gorcunov   UDF: coding style...
489
  			~(sb->s_blocksize - 1);
31170b6ad   Jan Kara   udf: support file...
490
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
491

31170b6ad   Jan Kara   udf: support file...
492
  	/* Last extent are just preallocated blocks? */
4b11111ab   Marcin Slusarz   udf: fix coding s...
493
494
  	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
  						EXT_NOT_RECORDED_ALLOCATED) {
31170b6ad   Jan Kara   udf: support file...
495
496
497
498
499
  		/* Save the extent so that we can reattach it to the end */
  		prealloc_loc = last_ext->extLocation;
  		prealloc_len = last_ext->extLength;
  		/* Mark the extent as a hole */
  		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
28de7948a   Cyrill Gorcunov   UDF: coding style...
500
  			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
31170b6ad   Jan Kara   udf: support file...
501
  		last_ext->extLocation.logicalBlockNum = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
502
  		last_ext->extLocation.partitionReferenceNum = 0;
31170b6ad   Jan Kara   udf: support file...
503
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
504

31170b6ad   Jan Kara   udf: support file...
505
  	/* Can we merge with the previous extent? */
4b11111ab   Marcin Slusarz   udf: fix coding s...
506
507
508
509
510
  	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
  					EXT_NOT_RECORDED_NOT_ALLOCATED) {
  		add = ((1 << 30) - sb->s_blocksize -
  			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >>
  			sb->s_blocksize_bits;
31170b6ad   Jan Kara   udf: support file...
511
512
513
514
515
516
517
  		if (add > blocks)
  			add = blocks;
  		blocks -= add;
  		last_ext->extLength += add << sb->s_blocksize_bits;
  	}
  
  	if (fake) {
97e961fdb   Pekka Enberg   Fix the udf code ...
518
  		udf_add_aext(inode, last_pos, &last_ext->extLocation,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
519
  			     last_ext->extLength, 1);
31170b6ad   Jan Kara   udf: support file...
520
  		count++;
6c3715787   Jan Kara   udf: Fix lost ind...
521
522
523
  	} else {
  		struct kernel_lb_addr tmploc;
  		uint32_t tmplen;
97e961fdb   Pekka Enberg   Fix the udf code ...
524
  		udf_write_aext(inode, last_pos, &last_ext->extLocation,
4b11111ab   Marcin Slusarz   udf: fix coding s...
525
  				last_ext->extLength, 1);
6c3715787   Jan Kara   udf: Fix lost ind...
526
527
528
529
530
531
  		/*
  		 * We've rewritten the last extent but there may be empty
  		 * indirect extent after it - enter it.
  		 */
  		udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0);
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
532

31170b6ad   Jan Kara   udf: support file...
533
534
535
536
537
538
  	/* Managed to do everything necessary? */
  	if (!blocks)
  		goto out;
  
  	/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
  	last_ext->extLocation.logicalBlockNum = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
539
  	last_ext->extLocation.partitionReferenceNum = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
540
  	add = (1 << (30-sb->s_blocksize_bits)) - 1;
4b11111ab   Marcin Slusarz   udf: fix coding s...
541
542
  	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
  				(add << sb->s_blocksize_bits);
28de7948a   Cyrill Gorcunov   UDF: coding style...
543

31170b6ad   Jan Kara   udf: support file...
544
545
546
  	/* Create enough extents to cover the whole hole */
  	while (blocks > add) {
  		blocks -= add;
7e49b6f24   Jan Kara   udf: Convert UDF ...
547
548
549
550
  		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
  				   last_ext->extLength, 1);
  		if (err)
  			return err;
31170b6ad   Jan Kara   udf: support file...
551
552
553
554
  		count++;
  	}
  	if (blocks) {
  		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
28de7948a   Cyrill Gorcunov   UDF: coding style...
555
  			(blocks << sb->s_blocksize_bits);
7e49b6f24   Jan Kara   udf: Convert UDF ...
556
557
558
559
  		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
  				   last_ext->extLength, 1);
  		if (err)
  			return err;
31170b6ad   Jan Kara   udf: support file...
560
561
  		count++;
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
562
563
  
  out:
31170b6ad   Jan Kara   udf: support file...
564
565
  	/* Do we have some preallocated blocks saved? */
  	if (prealloc_len) {
7e49b6f24   Jan Kara   udf: Convert UDF ...
566
567
568
569
  		err = udf_add_aext(inode, last_pos, &prealloc_loc,
  				   prealloc_len, 1);
  		if (err)
  			return err;
31170b6ad   Jan Kara   udf: support file...
570
571
572
573
  		last_ext->extLocation = prealloc_loc;
  		last_ext->extLength = prealloc_len;
  		count++;
  	}
28de7948a   Cyrill Gorcunov   UDF: coding style...
574

31170b6ad   Jan Kara   udf: support file...
575
  	/* last_pos should point to the last written extent... */
48d6d8ff7   Marcin Slusarz   udf: cache struct...
576
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
577
  		last_pos->offset -= 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
  		last_pos->offset -= sizeof(struct long_ad);
31170b6ad   Jan Kara   udf: support file...
580
  	else
7e49b6f24   Jan Kara   udf: Convert UDF ...
581
  		return -EIO;
28de7948a   Cyrill Gorcunov   UDF: coding style...
582

31170b6ad   Jan Kara   udf: support file...
583
584
  	return count;
  }
7e49b6f24   Jan Kara   udf: Convert UDF ...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  static int udf_extend_file(struct inode *inode, loff_t newsize)
  {
  
  	struct extent_position epos;
  	struct kernel_lb_addr eloc;
  	uint32_t elen;
  	int8_t etype;
  	struct super_block *sb = inode->i_sb;
  	sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
  	int adsize;
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	struct kernel_long_ad extent;
  	int err;
  
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  		adsize = sizeof(struct short_ad);
  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  		adsize = sizeof(struct long_ad);
  	else
  		BUG();
  
  	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
  
  	/* File has extent covering the new size (could happen when extending
  	 * inside a block)? */
  	if (etype != -1)
  		return 0;
  	if (newsize & (sb->s_blocksize - 1))
  		offset++;
  	/* Extended file just to the boundary of the last file block? */
  	if (offset == 0)
  		return 0;
  
  	/* Truncate is extending the file by 'offset' blocks */
  	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
  	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
  		/* File has no extents at all or has empty last
  		 * indirect extent! Create a fake extent... */
  		extent.extLocation.logicalBlockNum = 0;
  		extent.extLocation.partitionReferenceNum = 0;
  		extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
  	} else {
  		epos.offset -= adsize;
  		etype = udf_next_aext(inode, &epos, &extent.extLocation,
  				      &extent.extLength, 0);
  		extent.extLength |= etype << 30;
  	}
  	err = udf_do_extend_file(inode, &epos, &extent, offset);
  	if (err < 0)
  		goto out;
  	err = 0;
  	iinfo->i_lenExtents = newsize;
  out:
  	brelse(epos.bh);
  	return err;
  }
7b0b0933a   Jan Kara   udf: Cleanup call...
641
642
  static sector_t inode_getblk(struct inode *inode, sector_t block,
  			     int *err, int *new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  {
5ca4e4be8   Pekka Enberg   Remove struct typ...
644
  	struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];
ff116fc8d   Jan Kara   UDF: introduce st...
645
  	struct extent_position prev_epos, cur_epos, next_epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  	int count = 0, startnum = 0, endnum = 0;
85d71244f   Jan Kara   Fix possible UDF ...
647
  	uint32_t elen = 0, tmpelen;
5ca4e4be8   Pekka Enberg   Remove struct typ...
648
  	struct kernel_lb_addr eloc, tmpeloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  	int c = 1;
60448b1d6   Jan Kara   udf: use sector_t...
650
651
652
  	loff_t lbcount = 0, b_off = 0;
  	uint32_t newblocknum, newblock;
  	sector_t offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
  	int8_t etype;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
654
655
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
31170b6ad   Jan Kara   udf: support file...
656
  	int lastblock = 0;
fb719c59b   Namjae Jeon   udf: don't increm...
657
  	bool isBeyondEOF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658

7b0b0933a   Jan Kara   udf: Cleanup call...
659
660
  	*err = 0;
  	*new = 0;
ff116fc8d   Jan Kara   UDF: introduce st...
661
  	prev_epos.offset = udf_file_entry_alloc_offset(inode);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
662
  	prev_epos.block = iinfo->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
663
664
  	prev_epos.bh = NULL;
  	cur_epos = next_epos = prev_epos;
28de7948a   Cyrill Gorcunov   UDF: coding style...
665
  	b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
  
  	/* find the extent which contains the block we are looking for.
cb00ea352   Cyrill Gorcunov   UDF: coding style...
668
669
670
671
  	   alternate between laarr[0] and laarr[1] for locations of the
  	   current extent, and the previous extent */
  	do {
  		if (prev_epos.bh != cur_epos.bh) {
3bf25cb40   Jan Kara   udf: use get_bh()
672
673
  			brelse(prev_epos.bh);
  			get_bh(cur_epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
674
  			prev_epos.bh = cur_epos.bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
676
  		if (cur_epos.bh != next_epos.bh) {
3bf25cb40   Jan Kara   udf: use get_bh()
677
678
  			brelse(cur_epos.bh);
  			get_bh(next_epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
679
  			cur_epos.bh = next_epos.bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
  		}
  
  		lbcount += elen;
ff116fc8d   Jan Kara   UDF: introduce st...
683
684
  		prev_epos.block = cur_epos.block;
  		cur_epos.block = next_epos.block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685

ff116fc8d   Jan Kara   UDF: introduce st...
686
687
  		prev_epos.offset = cur_epos.offset;
  		cur_epos.offset = next_epos.offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688

4b11111ab   Marcin Slusarz   udf: fix coding s...
689
690
  		etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1);
  		if (etype == -1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
696
697
698
699
  			break;
  
  		c = !c;
  
  		laarr[c].extLength = (etype << 30) | elen;
  		laarr[c].extLocation = eloc;
  
  		if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
  			pgoal = eloc.logicalBlockNum +
28de7948a   Cyrill Gorcunov   UDF: coding style...
700
701
  				((elen + inode->i_sb->s_blocksize - 1) >>
  				 inode->i_sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702

cb00ea352   Cyrill Gorcunov   UDF: coding style...
703
  		count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
707
  	} while (lbcount + elen <= b_off);
  
  	b_off -= lbcount;
  	offset = b_off >> inode->i_sb->s_blocksize_bits;
85d71244f   Jan Kara   Fix possible UDF ...
708
709
710
711
712
713
  	/*
  	 * Move prev_epos and cur_epos into indirect extent if we are at
  	 * the pointer to it
  	 */
  	udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
  	udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
  
  	/* if the extent is allocated and recorded, return the block
cb00ea352   Cyrill Gorcunov   UDF: coding style...
716
  	   if the extent is not a multiple of the blocksize, round up */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717

cb00ea352   Cyrill Gorcunov   UDF: coding style...
718
719
  	if (etype == (EXT_RECORDED_ALLOCATED >> 30)) {
  		if (elen & (inode->i_sb->s_blocksize - 1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  			elen = EXT_RECORDED_ALLOCATED |
28de7948a   Cyrill Gorcunov   UDF: coding style...
721
722
  				((elen + inode->i_sb->s_blocksize - 1) &
  				 ~(inode->i_sb->s_blocksize - 1));
7e49b6f24   Jan Kara   udf: Convert UDF ...
723
  			udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  		}
3bf25cb40   Jan Kara   udf: use get_bh()
725
726
727
  		brelse(prev_epos.bh);
  		brelse(cur_epos.bh);
  		brelse(next_epos.bh);
97e961fdb   Pekka Enberg   Fix the udf code ...
728
  		newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
7b0b0933a   Jan Kara   udf: Cleanup call...
729
  		return newblock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  	}
31170b6ad   Jan Kara   udf: support file...
731
  	/* Are we beyond EOF? */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
732
  	if (etype == -1) {
31170b6ad   Jan Kara   udf: support file...
733
  		int ret;
6981498d7   Fabian Frederick   udf: remove bool ...
734
  		isBeyondEOF = true;
31170b6ad   Jan Kara   udf: support file...
735
736
737
738
  		if (count) {
  			if (c)
  				laarr[0] = laarr[1];
  			startnum = 1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
739
  		} else {
31170b6ad   Jan Kara   udf: support file...
740
  			/* Create a fake extent when there's not one */
4b11111ab   Marcin Slusarz   udf: fix coding s...
741
  			memset(&laarr[0].extLocation, 0x00,
5ca4e4be8   Pekka Enberg   Remove struct typ...
742
  				sizeof(struct kernel_lb_addr));
31170b6ad   Jan Kara   udf: support file...
743
  			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
7e49b6f24   Jan Kara   udf: Convert UDF ...
744
  			/* Will udf_do_extend_file() create real extent from
4b11111ab   Marcin Slusarz   udf: fix coding s...
745
  			   a fake one? */
31170b6ad   Jan Kara   udf: support file...
746
747
748
  			startnum = (offset > 0);
  		}
  		/* Create extents for the hole between EOF and offset */
7e49b6f24   Jan Kara   udf: Convert UDF ...
749
750
  		ret = udf_do_extend_file(inode, &prev_epos, laarr, offset);
  		if (ret < 0) {
31170b6ad   Jan Kara   udf: support file...
751
752
753
  			brelse(prev_epos.bh);
  			brelse(cur_epos.bh);
  			brelse(next_epos.bh);
7e49b6f24   Jan Kara   udf: Convert UDF ...
754
  			*err = ret;
7b0b0933a   Jan Kara   udf: Cleanup call...
755
  			return 0;
31170b6ad   Jan Kara   udf: support file...
756
757
758
759
760
  		}
  		c = 0;
  		offset = 0;
  		count += ret;
  		/* We are not covered by a preallocated extent? */
4b11111ab   Marcin Slusarz   udf: fix coding s...
761
762
  		if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) !=
  						EXT_NOT_RECORDED_ALLOCATED) {
31170b6ad   Jan Kara   udf: support file...
763
764
765
766
767
  			/* Is there any real extent? - otherwise we overwrite
  			 * the fake one... */
  			if (count)
  				c = !c;
  			laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
28de7948a   Cyrill Gorcunov   UDF: coding style...
768
  				inode->i_sb->s_blocksize;
4b11111ab   Marcin Slusarz   udf: fix coding s...
769
  			memset(&laarr[c].extLocation, 0x00,
5ca4e4be8   Pekka Enberg   Remove struct typ...
770
  				sizeof(struct kernel_lb_addr));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
771
  			count++;
31170b6ad   Jan Kara   udf: support file...
772
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
773
  		endnum = c + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  		lastblock = 1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
775
  	} else {
6981498d7   Fabian Frederick   udf: remove bool ...
776
  		isBeyondEOF = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  		endnum = startnum = ((count > 2) ? 2 : count);
4b11111ab   Marcin Slusarz   udf: fix coding s...
778
779
  		/* if the current extent is in position 0,
  		   swap it with the previous */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
780
  		if (!c && count != 1) {
31170b6ad   Jan Kara   udf: support file...
781
782
783
784
785
  			laarr[2] = laarr[0];
  			laarr[0] = laarr[1];
  			laarr[1] = laarr[2];
  			c = 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786

4b11111ab   Marcin Slusarz   udf: fix coding s...
787
788
789
790
  		/* if the current block is located in an extent,
  		   read the next extent */
  		etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0);
  		if (etype != -1) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
791
792
793
794
795
  			laarr[c + 1].extLength = (etype << 30) | elen;
  			laarr[c + 1].extLocation = eloc;
  			count++;
  			startnum++;
  			endnum++;
4b11111ab   Marcin Slusarz   udf: fix coding s...
796
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
  			lastblock = 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
  
  	/* if the current extent is not recorded but allocated, get the
28de7948a   Cyrill Gorcunov   UDF: coding style...
801
  	 * block in the extent corresponding to the requested block */
4b11111ab   Marcin Slusarz   udf: fix coding s...
802
  	if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
4b11111ab   Marcin Slusarz   udf: fix coding s...
804
  	else { /* otherwise, allocate a new block */
48d6d8ff7   Marcin Slusarz   udf: cache struct...
805
806
  		if (iinfo->i_next_alloc_block == block)
  			goal = iinfo->i_next_alloc_goal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807

cb00ea352   Cyrill Gorcunov   UDF: coding style...
808
  		if (!goal) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
809
  			if (!(goal = pgoal)) /* XXX: what was intended here? */
48d6d8ff7   Marcin Slusarz   udf: cache struct...
810
  				goal = iinfo->i_location.logicalBlockNum + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  		}
4b11111ab   Marcin Slusarz   udf: fix coding s...
812
  		newblocknum = udf_new_block(inode->i_sb, inode,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
813
  				iinfo->i_location.partitionReferenceNum,
4b11111ab   Marcin Slusarz   udf: fix coding s...
814
815
  				goal, err);
  		if (!newblocknum) {
3bf25cb40   Jan Kara   udf: use get_bh()
816
  			brelse(prev_epos.bh);
2fb7d99d0   Namjae Jeon   udf: fix memory l...
817
818
  			brelse(cur_epos.bh);
  			brelse(next_epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  			*err = -ENOSPC;
7b0b0933a   Jan Kara   udf: Cleanup call...
820
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  		}
fb719c59b   Namjae Jeon   udf: don't increm...
822
823
  		if (isBeyondEOF)
  			iinfo->i_lenExtents += inode->i_sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	}
4b11111ab   Marcin Slusarz   udf: fix coding s...
825
826
827
828
  	/* if the extent the requsted block is located in contains multiple
  	 * blocks, split the extent into at most three extents. blocks prior
  	 * to requested block, requested block, and blocks after requested
  	 * block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
831
  	udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);
  
  #ifdef UDF_PREALLOCATE
81056dd04   Jan Kara   udf: Perform prea...
832
833
834
835
836
837
  	/* We preallocate blocks only for regular files. It also makes sense
  	 * for directories but there's a problem when to drop the
  	 * preallocation. We might use some delayed work for that but I feel
  	 * it's overengineering for a filesystem like UDF. */
  	if (S_ISREG(inode->i_mode))
  		udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
  #endif
  
  	/* merge any continuous blocks in laarr */
  	udf_merge_extents(inode, laarr, &endnum);
  
  	/* write back the new extents, inserting new extents if the new number
28de7948a   Cyrill Gorcunov   UDF: coding style...
844
845
  	 * of extents is greater than the old number, and deleting extents if
  	 * the new number of extents is less than the old number */
ff116fc8d   Jan Kara   UDF: introduce st...
846
  	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847

3bf25cb40   Jan Kara   udf: use get_bh()
848
  	brelse(prev_epos.bh);
2fb7d99d0   Namjae Jeon   udf: fix memory l...
849
850
  	brelse(cur_epos.bh);
  	brelse(next_epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851

4b11111ab   Marcin Slusarz   udf: fix coding s...
852
  	newblock = udf_get_pblock(inode->i_sb, newblocknum,
48d6d8ff7   Marcin Slusarz   udf: cache struct...
853
  				iinfo->i_location.partitionReferenceNum, 0);
7b0b0933a   Jan Kara   udf: Cleanup call...
854
855
856
857
  	if (!newblock) {
  		*err = -EIO;
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  	*new = 1;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
859
860
  	iinfo->i_next_alloc_block = block;
  	iinfo->i_next_alloc_goal = newblocknum;
c2050a454   Deepa Dinamani   fs: Replace curre...
861
  	inode->i_ctime = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
  
  	if (IS_SYNC(inode))
  		udf_sync_inode(inode);
  	else
  		mark_inode_dirty(inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
867

7b0b0933a   Jan Kara   udf: Cleanup call...
868
  	return newblock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
870
871
  static void udf_split_extents(struct inode *inode, int *c, int offset,
  			      int newblocknum,
5ca4e4be8   Pekka Enberg   Remove struct typ...
872
  			      struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
cb00ea352   Cyrill Gorcunov   UDF: coding style...
873
  			      int *endnum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
  {
4b11111ab   Marcin Slusarz   udf: fix coding s...
875
876
  	unsigned long blocksize = inode->i_sb->s_blocksize;
  	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
4b11111ab   Marcin Slusarz   udf: fix coding s...
878
879
  	    (laarr[*c].extLength >> 30) ==
  				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  		int curr = *c;
  		int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
4b11111ab   Marcin Slusarz   udf: fix coding s...
882
  			    blocksize - 1) >> blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  		int8_t etype = (laarr[curr].extLength >> 30);
4b11111ab   Marcin Slusarz   udf: fix coding s...
884
  		if (blen == 1)
28de7948a   Cyrill Gorcunov   UDF: coding style...
885
  			;
4b11111ab   Marcin Slusarz   udf: fix coding s...
886
  		else if (!offset || blen == offset + 1) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
887
888
889
890
891
892
893
894
895
  			laarr[curr + 2] = laarr[curr + 1];
  			laarr[curr + 1] = laarr[curr];
  		} else {
  			laarr[curr + 3] = laarr[curr + 1];
  			laarr[curr + 2] = laarr[curr + 1] = laarr[curr];
  		}
  
  		if (offset) {
  			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
896
  				udf_free_blocks(inode->i_sb, inode,
97e961fdb   Pekka Enberg   Fix the udf code ...
897
  						&laarr[curr].extLocation,
4b11111ab   Marcin Slusarz   udf: fix coding s...
898
899
900
901
  						0, offset);
  				laarr[curr].extLength =
  					EXT_NOT_RECORDED_NOT_ALLOCATED |
  					(offset << blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  				laarr[curr].extLocation.logicalBlockNum = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
903
904
905
  				laarr[curr].extLocation.
  						partitionReferenceNum = 0;
  			} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
  				laarr[curr].extLength = (etype << 30) |
4b11111ab   Marcin Slusarz   udf: fix coding s...
907
  					(offset << blocksize_bits);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
908
909
910
  			curr++;
  			(*c)++;
  			(*endnum)++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
  		}
647bd61a5   Cyrill Gorcunov   UDF: check for al...
912

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
  		laarr[curr].extLocation.logicalBlockNum = newblocknum;
  		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
  			laarr[curr].extLocation.partitionReferenceNum =
c0b344385   Marcin Slusarz   udf: remove UDF_I...
916
  				UDF_I(inode)->i_location.partitionReferenceNum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  		laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
4b11111ab   Marcin Slusarz   udf: fix coding s...
918
  			blocksize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
919
  		curr++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920

cb00ea352   Cyrill Gorcunov   UDF: coding style...
921
  		if (blen != offset + 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
  			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
4b11111ab   Marcin Slusarz   udf: fix coding s...
923
924
  				laarr[curr].extLocation.logicalBlockNum +=
  								offset + 1;
28de7948a   Cyrill Gorcunov   UDF: coding style...
925
  			laarr[curr].extLength = (etype << 30) |
4b11111ab   Marcin Slusarz   udf: fix coding s...
926
  				((blen - (offset + 1)) << blocksize_bits);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
927
928
  			curr++;
  			(*endnum)++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
932
933
  		}
  	}
  }
  
  static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
5ca4e4be8   Pekka Enberg   Remove struct typ...
934
  				 struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
cb00ea352   Cyrill Gorcunov   UDF: coding style...
935
  				 int *endnum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
  {
  	int start, length = 0, currlength = 0, i;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
938
  	if (*endnum >= (c + 1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
941
942
  		if (!lastblock)
  			return;
  		else
  			start = c;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
943
  	} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
944
945
  		if ((laarr[c + 1].extLength >> 30) ==
  					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
946
  			start = c + 1;
4b11111ab   Marcin Slusarz   udf: fix coding s...
947
948
949
950
951
952
  			length = currlength =
  				(((laarr[c + 1].extLength &
  					UDF_EXTENT_LENGTH_MASK) +
  				inode->i_sb->s_blocksize - 1) >>
  				inode->i_sb->s_blocksize_bits);
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
  			start = c;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
955
956
  	for (i = start + 1; i <= *endnum; i++) {
  		if (i == *endnum) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
  			if (lastblock)
  				length += UDF_DEFAULT_PREALLOC_BLOCKS;
4b11111ab   Marcin Slusarz   udf: fix coding s...
959
960
961
962
963
964
965
  		} else if ((laarr[i].extLength >> 30) ==
  				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) {
  			length += (((laarr[i].extLength &
  						UDF_EXTENT_LENGTH_MASK) +
  				    inode->i_sb->s_blocksize - 1) >>
  				    inode->i_sb->s_blocksize_bits);
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
  			break;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
968
  	if (length) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  		int next = laarr[start].extLocation.logicalBlockNum +
28de7948a   Cyrill Gorcunov   UDF: coding style...
970
  			(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
4b11111ab   Marcin Slusarz   udf: fix coding s...
971
972
  			  inode->i_sb->s_blocksize - 1) >>
  			  inode->i_sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
  		int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
4b11111ab   Marcin Slusarz   udf: fix coding s...
974
975
976
977
  				laarr[start].extLocation.partitionReferenceNum,
  				next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ?
  				length : UDF_DEFAULT_PREALLOC_BLOCKS) -
  				currlength);
28de7948a   Cyrill Gorcunov   UDF: coding style...
978
  		if (numalloc) 	{
4b11111ab   Marcin Slusarz   udf: fix coding s...
979
  			if (start == (c + 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
  				laarr[start].extLength +=
4b11111ab   Marcin Slusarz   udf: fix coding s...
981
982
983
  					(numalloc <<
  					 inode->i_sb->s_blocksize_bits);
  			else {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
984
  				memmove(&laarr[c + 2], &laarr[c + 1],
5ca4e4be8   Pekka Enberg   Remove struct typ...
985
  					sizeof(struct long_ad) * (*endnum - (c + 1)));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
986
987
988
  				(*endnum)++;
  				laarr[c + 1].extLocation.logicalBlockNum = next;
  				laarr[c + 1].extLocation.partitionReferenceNum =
4b11111ab   Marcin Slusarz   udf: fix coding s...
989
990
991
992
993
994
  					laarr[c].extLocation.
  							partitionReferenceNum;
  				laarr[c + 1].extLength =
  					EXT_NOT_RECORDED_ALLOCATED |
  					(numalloc <<
  					 inode->i_sb->s_blocksize_bits);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
995
  				start = c + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  			}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
997
  			for (i = start + 1; numalloc && i < *endnum; i++) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
998
999
1000
1001
  				int elen = ((laarr[i].extLength &
  						UDF_EXTENT_LENGTH_MASK) +
  					    inode->i_sb->s_blocksize - 1) >>
  					    inode->i_sb->s_blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1003
  				if (elen > numalloc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
  					laarr[i].extLength -=
4b11111ab   Marcin Slusarz   udf: fix coding s...
1005
1006
  						(numalloc <<
  						 inode->i_sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
  					numalloc = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1008
  				} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
  					numalloc -= elen;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1010
  					if (*endnum > (i + 1))
4b11111ab   Marcin Slusarz   udf: fix coding s...
1011
1012
  						memmove(&laarr[i],
  							&laarr[i + 1],
5ca4e4be8   Pekka Enberg   Remove struct typ...
1013
  							sizeof(struct long_ad) *
4b11111ab   Marcin Slusarz   udf: fix coding s...
1014
  							(*endnum - (i + 1)));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1015
1016
  					i--;
  					(*endnum)--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
1018
  				}
  			}
c0b344385   Marcin Slusarz   udf: remove UDF_I...
1019
  			UDF_I(inode)->i_lenExtents +=
4b11111ab   Marcin Slusarz   udf: fix coding s...
1020
  				numalloc << inode->i_sb->s_blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
1023
1024
1025
  		}
  	}
  }
  
  static void udf_merge_extents(struct inode *inode,
5ca4e4be8   Pekka Enberg   Remove struct typ...
1026
  			      struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1027
  			      int *endnum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
  {
  	int i;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1030
1031
  	unsigned long blocksize = inode->i_sb->s_blocksize;
  	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1033
  	for (i = 0; i < (*endnum - 1); i++) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
1034
1035
  		struct kernel_long_ad *li /*l[i]*/ = &laarr[i];
  		struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1];
4b11111ab   Marcin Slusarz   udf: fix coding s...
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
  
  		if (((li->extLength >> 30) == (lip1->extLength >> 30)) &&
  			(((li->extLength >> 30) ==
  				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) ||
  			((lip1->extLocation.logicalBlockNum -
  			  li->extLocation.logicalBlockNum) ==
  			(((li->extLength & UDF_EXTENT_LENGTH_MASK) +
  			blocksize - 1) >> blocksize_bits)))) {
  
  			if (((li->extLength & UDF_EXTENT_LENGTH_MASK) +
  				(lip1->extLength & UDF_EXTENT_LENGTH_MASK) +
  				blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) {
  				lip1->extLength = (lip1->extLength -
  						  (li->extLength &
  						   UDF_EXTENT_LENGTH_MASK) +
  						   UDF_EXTENT_LENGTH_MASK) &
  							~(blocksize - 1);
  				li->extLength = (li->extLength &
  						 UDF_EXTENT_FLAG_MASK) +
  						(UDF_EXTENT_LENGTH_MASK + 1) -
  						blocksize;
  				lip1->extLocation.logicalBlockNum =
  					li->extLocation.logicalBlockNum +
  					((li->extLength &
  						UDF_EXTENT_LENGTH_MASK) >>
  						blocksize_bits);
  			} else {
  				li->extLength = lip1->extLength +
  					(((li->extLength &
  						UDF_EXTENT_LENGTH_MASK) +
  					 blocksize - 1) & ~(blocksize - 1));
  				if (*endnum > (i + 2))
  					memmove(&laarr[i + 1], &laarr[i + 2],
5ca4e4be8   Pekka Enberg   Remove struct typ...
1069
  						sizeof(struct long_ad) *
4b11111ab   Marcin Slusarz   udf: fix coding s...
1070
1071
1072
  						(*endnum - (i + 2)));
  				i--;
  				(*endnum)--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  			}
4b11111ab   Marcin Slusarz   udf: fix coding s...
1074
1075
1076
1077
  		} else if (((li->extLength >> 30) ==
  				(EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
  			   ((lip1->extLength >> 30) ==
  				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) {
97e961fdb   Pekka Enberg   Fix the udf code ...
1078
  			udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  					((li->extLength &
  					  UDF_EXTENT_LENGTH_MASK) +
  					 blocksize - 1) >> blocksize_bits);
  			li->extLocation.logicalBlockNum = 0;
  			li->extLocation.partitionReferenceNum = 0;
  
  			if (((li->extLength & UDF_EXTENT_LENGTH_MASK) +
  			     (lip1->extLength & UDF_EXTENT_LENGTH_MASK) +
  			     blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) {
  				lip1->extLength = (lip1->extLength -
  						   (li->extLength &
  						   UDF_EXTENT_LENGTH_MASK) +
  						   UDF_EXTENT_LENGTH_MASK) &
  						   ~(blocksize - 1);
  				li->extLength = (li->extLength &
  						 UDF_EXTENT_FLAG_MASK) +
  						(UDF_EXTENT_LENGTH_MASK + 1) -
  						blocksize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1097
  			} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1098
1099
1100
1101
  				li->extLength = lip1->extLength +
  					(((li->extLength &
  						UDF_EXTENT_LENGTH_MASK) +
  					  blocksize - 1) & ~(blocksize - 1));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1102
1103
  				if (*endnum > (i + 2))
  					memmove(&laarr[i + 1], &laarr[i + 2],
5ca4e4be8   Pekka Enberg   Remove struct typ...
1104
  						sizeof(struct long_ad) *
4b11111ab   Marcin Slusarz   udf: fix coding s...
1105
  						(*endnum - (i + 2)));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1106
1107
  				i--;
  				(*endnum)--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  			}
4b11111ab   Marcin Slusarz   udf: fix coding s...
1109
1110
1111
  		} else if ((li->extLength >> 30) ==
  					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
  			udf_free_blocks(inode->i_sb, inode,
97e961fdb   Pekka Enberg   Fix the udf code ...
1112
  					&li->extLocation, 0,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1113
1114
1115
1116
1117
1118
1119
1120
  					((li->extLength &
  						UDF_EXTENT_LENGTH_MASK) +
  					 blocksize - 1) >> blocksize_bits);
  			li->extLocation.logicalBlockNum = 0;
  			li->extLocation.partitionReferenceNum = 0;
  			li->extLength = (li->extLength &
  						UDF_EXTENT_LENGTH_MASK) |
  						EXT_NOT_RECORDED_NOT_ALLOCATED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
1122
1123
1124
1125
  		}
  	}
  }
  
  static void udf_update_extents(struct inode *inode,
5ca4e4be8   Pekka Enberg   Remove struct typ...
1126
  			       struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1127
1128
  			       int startnum, int endnum,
  			       struct extent_position *epos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
1130
  {
  	int start = 0, i;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1131
  	struct kernel_lb_addr tmploc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	uint32_t tmplen;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1133
1134
  	if (startnum > endnum) {
  		for (i = 0; i < (startnum - endnum); i++)
ff116fc8d   Jan Kara   UDF: introduce st...
1135
  			udf_delete_aext(inode, *epos, laarr[i].extLocation,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1136
1137
1138
  					laarr[i].extLength);
  	} else if (startnum < endnum) {
  		for (i = 0; i < (endnum - startnum); i++) {
ff116fc8d   Jan Kara   UDF: introduce st...
1139
  			udf_insert_aext(inode, *epos, laarr[i].extLocation,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1140
  					laarr[i].extLength);
ff116fc8d   Jan Kara   UDF: introduce st...
1141
  			udf_next_aext(inode, epos, &laarr[i].extLocation,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1142
1143
  				      &laarr[i].extLength, 1);
  			start++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
  		}
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1146
  	for (i = start; i < endnum; i++) {
ff116fc8d   Jan Kara   UDF: introduce st...
1147
  		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
97e961fdb   Pekka Enberg   Fix the udf code ...
1148
  		udf_write_aext(inode, epos, &laarr[i].extLocation,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1149
  			       laarr[i].extLength, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
1151
  	}
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1152
1153
  struct buffer_head *udf_bread(struct inode *inode, int block,
  			      int create, int *err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1155
  	struct buffer_head *bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
1157
1158
1159
1160
1161
1162
  
  	bh = udf_getblk(inode, block, create, err);
  	if (!bh)
  		return NULL;
  
  	if (buffer_uptodate(bh))
  		return bh;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1163

dfec8a14f   Mike Christie   fs: have ll_rw_bl...
1164
  	ll_rw_block(REQ_OP_READ, 0, 1, &bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
1165

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
1168
  	wait_on_buffer(bh);
  	if (buffer_uptodate(bh))
  		return bh;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1169

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
1171
1172
1173
  	brelse(bh);
  	*err = -EIO;
  	return NULL;
  }
7e49b6f24   Jan Kara   udf: Convert UDF ...
1174
  int udf_setsize(struct inode *inode, loff_t newsize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  	int err;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1177
  	struct udf_inode_info *iinfo;
7e49b6f24   Jan Kara   udf: Convert UDF ...
1178
  	int bsize = 1 << inode->i_blkbits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
  
  	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1181
  	      S_ISLNK(inode->i_mode)))
7e49b6f24   Jan Kara   udf: Convert UDF ...
1182
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
7e49b6f24   Jan Kara   udf: Convert UDF ...
1184
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1186
  	iinfo = UDF_I(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
1187
  	if (newsize > inode->i_size) {
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
1188
  		down_write(&iinfo->i_data_sem);
7e49b6f24   Jan Kara   udf: Convert UDF ...
1189
1190
1191
1192
  		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  			if (bsize <
  			    (udf_file_entry_alloc_offset(inode) + newsize)) {
  				err = udf_expand_file_adinicb(inode);
d2eb8c359   Jan Kara   udf: Fix deadlock...
1193
  				if (err)
7e49b6f24   Jan Kara   udf: Convert UDF ...
1194
  					return err;
d2eb8c359   Jan Kara   udf: Fix deadlock...
1195
  				down_write(&iinfo->i_data_sem);
bb2b6d19e   Ian Abbott   udf: fix udf_sets...
1196
  			} else {
7e49b6f24   Jan Kara   udf: Convert UDF ...
1197
  				iinfo->i_lenAlloc = newsize;
bb2b6d19e   Ian Abbott   udf: fix udf_sets...
1198
1199
  				goto set_size;
  			}
7e49b6f24   Jan Kara   udf: Convert UDF ...
1200
1201
1202
1203
1204
  		}
  		err = udf_extend_file(inode, newsize);
  		if (err) {
  			up_write(&iinfo->i_data_sem);
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
  		}
bb2b6d19e   Ian Abbott   udf: fix udf_sets...
1206
  set_size:
7e49b6f24   Jan Kara   udf: Convert UDF ...
1207
  		truncate_setsize(inode, newsize);
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
1208
  		up_write(&iinfo->i_data_sem);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1209
  	} else {
7e49b6f24   Jan Kara   udf: Convert UDF ...
1210
1211
  		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  			down_write(&iinfo->i_data_sem);
99600051b   Namjae Jeon   udf: add extent c...
1212
  			udf_clear_extent_cache(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize,
  			       0x00, bsize - newsize -
  			       udf_file_entry_alloc_offset(inode));
  			iinfo->i_lenAlloc = newsize;
  			truncate_setsize(inode, newsize);
  			up_write(&iinfo->i_data_sem);
  			goto update_time;
  		}
  		err = block_truncate_page(inode->i_mapping, newsize,
  					  udf_get_block);
  		if (err)
  			return err;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
1225
  		down_write(&iinfo->i_data_sem);
99600051b   Namjae Jeon   udf: add extent c...
1226
  		udf_clear_extent_cache(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
1227
  		truncate_setsize(inode, newsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  		udf_truncate_extents(inode);
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
1229
  		up_write(&iinfo->i_data_sem);
647bd61a5   Cyrill Gorcunov   UDF: check for al...
1230
  	}
7e49b6f24   Jan Kara   udf: Convert UDF ...
1231
  update_time:
c2050a454   Deepa Dinamani   fs: Replace curre...
1232
  	inode->i_mtime = inode->i_ctime = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
  	if (IS_SYNC(inode))
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1234
  		udf_sync_inode(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
1236
  	else
  		mark_inode_dirty(inode);
7e49b6f24   Jan Kara   udf: Convert UDF ...
1237
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
  }
c03aa9f6e   Jan Kara   udf: Avoid infini...
1239
1240
1241
1242
1243
1244
  /*
   * Maximum length of linked list formed by ICB hierarchy. The chosen number is
   * arbitrary - just that we hopefully don't limit any real use of rewritten
   * inode on write-once media but avoid looping for too long on corrupted media.
   */
  #define UDF_MAX_ICB_NESTING 1024
6174c2eb8   Jan Kara   udf: Fix loading ...
1245
  static int udf_read_inode(struct inode *inode, bool hidden_inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
1247
1248
  {
  	struct buffer_head *bh = NULL;
  	struct fileEntry *fe;
bb7720a0b   Jan Kara   udf: Fold udf_fil...
1249
  	struct extendedFileEntry *efe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
  	uint16_t ident;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1251
  	struct udf_inode_info *iinfo = UDF_I(inode);
bb7720a0b   Jan Kara   udf: Fold udf_fil...
1252
  	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1253
  	struct kernel_lb_addr *iloc = &iinfo->i_location;
bb7720a0b   Jan Kara   udf: Fold udf_fil...
1254
  	unsigned int link_count;
c03aa9f6e   Jan Kara   udf: Avoid infini...
1255
  	unsigned int indirections = 0;
791449542   Jan Kara   udf: Remove repea...
1256
  	int bs = inode->i_sb->s_blocksize;
6d3d5e860   Jan Kara   udf: Make udf_rea...
1257
  	int ret = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258

c03aa9f6e   Jan Kara   udf: Avoid infini...
1259
  reread:
6d3d5e860   Jan Kara   udf: Make udf_rea...
1260
1261
1262
1263
1264
1265
1266
  	if (iloc->logicalBlockNum >=
  	    sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
  		udf_debug("block=%d, partition=%d out of range
  ",
  			  iloc->logicalBlockNum, iloc->partitionReferenceNum);
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
  	/*
  	 * Set defaults, but the inode is still incomplete!
  	 * Note: get_new_inode() sets the following on a new inode:
  	 *      i_sb = sb
  	 *      i_no = ino
  	 *      i_flags = sb->s_flags
  	 *      i_state = 0
  	 * clean_inode(): zero fills and sets
  	 *      i_count = 1
  	 *      i_nlink = 1
  	 *      i_op = NULL;
  	 */
6d3d5e860   Jan Kara   udf: Make udf_rea...
1279
  	bh = udf_read_ptagged(inode->i_sb, iloc, 0, &ident);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1280
  	if (!bh) {
78ace70c4   Joe Perches   udf: Convert prin...
1281
1282
  		udf_err(inode->i_sb, "(ino %ld) failed !bh
  ", inode->i_ino);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1283
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
1286
  	}
  
  	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1287
  	    ident != TAG_IDENT_USE) {
78ace70c4   Joe Perches   udf: Convert prin...
1288
1289
1290
  		udf_err(inode->i_sb, "(ino %ld) failed ident=%d
  ",
  			inode->i_ino, ident);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1291
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
1293
1294
  	}
  
  	fe = (struct fileEntry *)bh->b_data;
bb7720a0b   Jan Kara   udf: Fold udf_fil...
1295
  	efe = (struct extendedFileEntry *)bh->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296

5e0f00173   Marcin Slusarz   udf: convert byte...
1297
  	if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
1ab927857   marcin.slusarz@gmail.com   udf: simplify __u...
1298
  		struct buffer_head *ibh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299

6d3d5e860   Jan Kara   udf: Make udf_rea...
1300
  		ibh = udf_read_ptagged(inode->i_sb, iloc, 1, &ident);
1ab927857   marcin.slusarz@gmail.com   udf: simplify __u...
1301
  		if (ident == TAG_IDENT_IE && ibh) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
1302
  			struct kernel_lb_addr loc;
1ab927857   marcin.slusarz@gmail.com   udf: simplify __u...
1303
1304
1305
1306
  			struct indirectEntry *ie;
  
  			ie = (struct indirectEntry *)ibh->b_data;
  			loc = lelb_to_cpu(ie->indirectICB.extLocation);
c03aa9f6e   Jan Kara   udf: Avoid infini...
1307
  			if (ie->indirectICB.extLength) {
c03aa9f6e   Jan Kara   udf: Avoid infini...
1308
1309
1310
1311
1312
1313
1314
1315
1316
  				brelse(ibh);
  				memcpy(&iinfo->i_location, &loc,
  				       sizeof(struct kernel_lb_addr));
  				if (++indirections > UDF_MAX_ICB_NESTING) {
  					udf_err(inode->i_sb,
  						"too many ICBs in ICB hierarchy"
  						" (max %d supported)
  ",
  						UDF_MAX_ICB_NESTING);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1317
  					goto out;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1318
  				}
6d3d5e860   Jan Kara   udf: Make udf_rea...
1319
  				brelse(bh);
c03aa9f6e   Jan Kara   udf: Avoid infini...
1320
  				goto reread;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
  			}
28de7948a   Cyrill Gorcunov   UDF: coding style...
1322
  		}
1ab927857   marcin.slusarz@gmail.com   udf: simplify __u...
1323
  		brelse(ibh);
5e0f00173   Marcin Slusarz   udf: convert byte...
1324
  	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
78ace70c4   Joe Perches   udf: Convert prin...
1325
1326
1327
  		udf_err(inode->i_sb, "unsupported strategy type: %d
  ",
  			le16_to_cpu(fe->icbTag.strategyType));
6d3d5e860   Jan Kara   udf: Make udf_rea...
1328
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
  	}
5e0f00173   Marcin Slusarz   udf: convert byte...
1330
  	if (fe->icbTag.strategyType == cpu_to_le16(4))
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1331
  		iinfo->i_strat4096 = 0;
5e0f00173   Marcin Slusarz   udf: convert byte...
1332
  	else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1333
  		iinfo->i_strat4096 = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1335
  	iinfo->i_alloc_type = le16_to_cpu(fe->icbTag.flags) &
4b11111ab   Marcin Slusarz   udf: fix coding s...
1336
  							ICBTAG_FLAG_AD_MASK;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1337
1338
1339
1340
1341
1342
  	iinfo->i_unique = 0;
  	iinfo->i_lenEAttr = 0;
  	iinfo->i_lenExtents = 0;
  	iinfo->i_lenAlloc = 0;
  	iinfo->i_next_alloc_block = 0;
  	iinfo->i_next_alloc_goal = 0;
5e0f00173   Marcin Slusarz   udf: convert byte...
1343
  	if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1344
1345
  		iinfo->i_efe = 1;
  		iinfo->i_use = 0;
791449542   Jan Kara   udf: Remove repea...
1346
  		ret = udf_alloc_i_data(inode, bs -
6d3d5e860   Jan Kara   udf: Make udf_rea...
1347
1348
1349
  					sizeof(struct extendedFileEntry));
  		if (ret)
  			goto out;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1350
  		memcpy(iinfo->i_ext.i_data,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1351
  		       bh->b_data + sizeof(struct extendedFileEntry),
791449542   Jan Kara   udf: Remove repea...
1352
  		       bs - sizeof(struct extendedFileEntry));
5e0f00173   Marcin Slusarz   udf: convert byte...
1353
  	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1354
1355
  		iinfo->i_efe = 0;
  		iinfo->i_use = 0;
791449542   Jan Kara   udf: Remove repea...
1356
  		ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry));
6d3d5e860   Jan Kara   udf: Make udf_rea...
1357
1358
  		if (ret)
  			goto out;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1359
  		memcpy(iinfo->i_ext.i_data,
c0b344385   Marcin Slusarz   udf: remove UDF_I...
1360
  		       bh->b_data + sizeof(struct fileEntry),
791449542   Jan Kara   udf: Remove repea...
1361
  		       bs - sizeof(struct fileEntry));
5e0f00173   Marcin Slusarz   udf: convert byte...
1362
  	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1363
1364
1365
  		iinfo->i_efe = 0;
  		iinfo->i_use = 1;
  		iinfo->i_lenAlloc = le32_to_cpu(
4b11111ab   Marcin Slusarz   udf: fix coding s...
1366
1367
  				((struct unallocSpaceEntry *)bh->b_data)->
  				 lengthAllocDescs);
791449542   Jan Kara   udf: Remove repea...
1368
  		ret = udf_alloc_i_data(inode, bs -
6d3d5e860   Jan Kara   udf: Make udf_rea...
1369
1370
1371
  					sizeof(struct unallocSpaceEntry));
  		if (ret)
  			goto out;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1372
  		memcpy(iinfo->i_ext.i_data,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1373
  		       bh->b_data + sizeof(struct unallocSpaceEntry),
791449542   Jan Kara   udf: Remove repea...
1374
  		       bs - sizeof(struct unallocSpaceEntry));
6d3d5e860   Jan Kara   udf: Make udf_rea...
1375
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
  	}
6d3d5e860   Jan Kara   udf: Make udf_rea...
1377
  	ret = -EIO;
c03cad241   Jan Kara   udf: Protect defa...
1378
  	read_lock(&sbi->s_cred_lock);
c2ba138a2   Eric W. Biederman   userns: Convert t...
1379
1380
  	i_uid_write(inode, le32_to_cpu(fe->uid));
  	if (!uid_valid(inode->i_uid) ||
ca76d2d80   Cyrill Gorcunov   UDF: fix UID and ...
1381
1382
  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||
  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))
4d6660eb3   Phillip Susi   [PATCH] udf: fix ...
1383
  		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384

c2ba138a2   Eric W. Biederman   userns: Convert t...
1385
1386
  	i_gid_write(inode, le32_to_cpu(fe->gid));
  	if (!gid_valid(inode->i_gid) ||
ca76d2d80   Cyrill Gorcunov   UDF: fix UID and ...
1387
1388
  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) ||
  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
4d6660eb3   Phillip Susi   [PATCH] udf: fix ...
1389
  		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390

7ac9bcd5d   Marcin Slusarz   udf: implement mo...
1391
  	if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&
87bc730c0   Marcin Slusarz   udf: fix default ...
1392
  			sbi->s_fmode != UDF_INVALID_MODE)
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
1393
1394
  		inode->i_mode = sbi->s_fmode;
  	else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY &&
87bc730c0   Marcin Slusarz   udf: fix default ...
1395
  			sbi->s_dmode != UDF_INVALID_MODE)
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
1396
1397
1398
1399
  		inode->i_mode = sbi->s_dmode;
  	else
  		inode->i_mode = udf_convert_permissions(fe);
  	inode->i_mode &= ~sbi->s_umask;
c03cad241   Jan Kara   udf: Protect defa...
1400
  	read_unlock(&sbi->s_cred_lock);
bfe868486   Miklos Szeredi   filesystems: add ...
1401
  	link_count = le16_to_cpu(fe->fileLinkCount);
4071b9136   Jan Kara   udf: Properly det...
1402
  	if (!link_count) {
6174c2eb8   Jan Kara   udf: Fix loading ...
1403
1404
1405
1406
1407
  		if (!hidden_inode) {
  			ret = -ESTALE;
  			goto out;
  		}
  		link_count = 1;
4071b9136   Jan Kara   udf: Properly det...
1408
  	}
bfe868486   Miklos Szeredi   filesystems: add ...
1409
  	set_nlink(inode, link_count);
c03cad241   Jan Kara   udf: Protect defa...
1410
1411
1412
  
  	inode->i_size = le64_to_cpu(fe->informationLength);
  	iinfo->i_lenExtents = inode->i_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1414
  	if (iinfo->i_efe == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
  		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
28de7948a   Cyrill Gorcunov   UDF: coding style...
1416
  			(inode->i_sb->s_blocksize_bits - 9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

56774805d   Marcin Slusarz   udf: convert udf_...
1418
  		if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1419
  			inode->i_atime = sbi->s_record_time;
56774805d   Marcin Slusarz   udf: convert udf_...
1420
1421
  		if (!udf_disk_stamp_to_time(&inode->i_mtime,
  					    fe->modificationTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1422
  			inode->i_mtime = sbi->s_record_time;
56774805d   Marcin Slusarz   udf: convert udf_...
1423
  		if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1424
  			inode->i_ctime = sbi->s_record_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1426
1427
1428
  		iinfo->i_unique = le64_to_cpu(fe->uniqueID);
  		iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
  		iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs);
d5e2cf07c   Steve Nickel   udf: Init/maintai...
1429
  		iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1430
  	} else {
647bd61a5   Cyrill Gorcunov   UDF: check for al...
1431
  		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1432
  		    (inode->i_sb->s_blocksize_bits - 9);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433

56774805d   Marcin Slusarz   udf: convert udf_...
1434
  		if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1435
  			inode->i_atime = sbi->s_record_time;
56774805d   Marcin Slusarz   udf: convert udf_...
1436
1437
  		if (!udf_disk_stamp_to_time(&inode->i_mtime,
  					    efe->modificationTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1438
  			inode->i_mtime = sbi->s_record_time;
56774805d   Marcin Slusarz   udf: convert udf_...
1439
  		if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1440
  			iinfo->i_crtime = sbi->s_record_time;
56774805d   Marcin Slusarz   udf: convert udf_...
1441
  		if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
cbf5676a0   marcin.slusarz@gmail.com   udf: convert udf_...
1442
  			inode->i_ctime = sbi->s_record_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1444
1445
1446
  		iinfo->i_unique = le64_to_cpu(efe->uniqueID);
  		iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
  		iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
d5e2cf07c   Steve Nickel   udf: Init/maintai...
1447
  		iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  	}
470cca56c   Jan Kara   udf: Set i_genera...
1449
  	inode->i_generation = iinfo->i_unique;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450

23b133bdc   Jan Kara   udf: Check length...
1451
1452
1453
1454
1455
1456
1457
1458
1459
  	/*
  	 * Sanity check length of allocation descriptors and extended attrs to
  	 * avoid integer overflows
  	 */
  	if (iinfo->i_lenEAttr > bs || iinfo->i_lenAlloc > bs)
  		goto out;
  	/* Now do exact checks */
  	if (udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc > bs)
  		goto out;
e159332b9   Jan Kara   udf: Verify i_siz...
1460
1461
1462
1463
1464
1465
1466
1467
1468
  	/* Sanity checks for files in ICB so that we don't get confused later */
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  		/*
  		 * For file in ICB data is stored in allocation descriptor
  		 * so sizes should match
  		 */
  		if (iinfo->i_lenAlloc != inode->i_size)
  			goto out;
  		/* File in ICB has to fit in there... */
791449542   Jan Kara   udf: Remove repea...
1469
  		if (inode->i_size > bs - udf_file_entry_alloc_offset(inode))
e159332b9   Jan Kara   udf: Verify i_siz...
1470
1471
  			goto out;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1472
1473
  	switch (fe->icbTag.fileType) {
  	case ICBTAG_FILE_TYPE_DIRECTORY:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1474
1475
1476
1477
1478
  		inode->i_op = &udf_dir_inode_operations;
  		inode->i_fop = &udf_dir_operations;
  		inode->i_mode |= S_IFDIR;
  		inc_nlink(inode);
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1479
1480
1481
  	case ICBTAG_FILE_TYPE_REALTIME:
  	case ICBTAG_FILE_TYPE_REGULAR:
  	case ICBTAG_FILE_TYPE_UNDEF:
742e1795e   Jan Kara   udf: Allow loadin...
1482
  	case ICBTAG_FILE_TYPE_VAT20:
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1483
  		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
28de7948a   Cyrill Gorcunov   UDF: coding style...
1484
1485
1486
1487
1488
1489
1490
  			inode->i_data.a_ops = &udf_adinicb_aops;
  		else
  			inode->i_data.a_ops = &udf_aops;
  		inode->i_op = &udf_file_inode_operations;
  		inode->i_fop = &udf_file_operations;
  		inode->i_mode |= S_IFREG;
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1491
  	case ICBTAG_FILE_TYPE_BLOCK:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1492
1493
  		inode->i_mode |= S_IFBLK;
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1494
  	case ICBTAG_FILE_TYPE_CHAR:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1495
1496
  		inode->i_mode |= S_IFCHR;
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1497
  	case ICBTAG_FILE_TYPE_FIFO:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1498
1499
  		init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1500
  	case ICBTAG_FILE_TYPE_SOCKET:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1501
1502
  		init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1503
  	case ICBTAG_FILE_TYPE_SYMLINK:
28de7948a   Cyrill Gorcunov   UDF: coding style...
1504
  		inode->i_data.a_ops = &udf_symlink_aops;
c73119c58   Al Viro   udf: don't duplic...
1505
  		inode->i_op = &page_symlink_inode_operations;
21fc61c73   Al Viro   don't put symlink...
1506
  		inode_nohighmem(inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
1507
1508
  		inode->i_mode = S_IFLNK | S_IRWXUGO;
  		break;
bfb257a59   Jan Kara   udf: Add read-onl...
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
  	case ICBTAG_FILE_TYPE_MAIN:
  		udf_debug("METADATA FILE-----
  ");
  		break;
  	case ICBTAG_FILE_TYPE_MIRROR:
  		udf_debug("METADATA MIRROR FILE-----
  ");
  		break;
  	case ICBTAG_FILE_TYPE_BITMAP:
  		udf_debug("METADATA BITMAP FILE-----
  ");
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1521
  	default:
78ace70c4   Joe Perches   udf: Convert prin...
1522
1523
1524
  		udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d
  ",
  			inode->i_ino, fe->icbTag.fileType);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1525
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1527
  	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1528
1529
  		struct deviceSpec *dsea =
  			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1530
1531
  		if (dsea) {
  			init_special_inode(inode, inode->i_mode,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1532
1533
  				MKDEV(le32_to_cpu(dsea->majorDeviceIdent),
  				      le32_to_cpu(dsea->minorDeviceIdent)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
  			/* Developer ID ??? */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1535
  		} else
6d3d5e860   Jan Kara   udf: Make udf_rea...
1536
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  	}
6d3d5e860   Jan Kara   udf: Make udf_rea...
1538
1539
  	ret = 0;
  out:
bb7720a0b   Jan Kara   udf: Fold udf_fil...
1540
  	brelse(bh);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1541
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
  }
647bd61a5   Cyrill Gorcunov   UDF: check for al...
1543
1544
  static int udf_alloc_i_data(struct inode *inode, size_t size)
  {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1545
1546
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL);
647bd61a5   Cyrill Gorcunov   UDF: check for al...
1547

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1548
  	if (!iinfo->i_ext.i_data) {
78ace70c4   Joe Perches   udf: Convert prin...
1549
1550
1551
  		udf_err(inode->i_sb, "(ino %ld) no free memory
  ",
  			inode->i_ino);
647bd61a5   Cyrill Gorcunov   UDF: check for al...
1552
1553
1554
1555
1556
  		return -ENOMEM;
  	}
  
  	return 0;
  }
faa17292f   Al Viro   udf: propagate um...
1557
  static umode_t udf_convert_permissions(struct fileEntry *fe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  {
faa17292f   Al Viro   udf: propagate um...
1559
  	umode_t mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
1561
1562
1563
1564
  	uint32_t permissions;
  	uint32_t flags;
  
  	permissions = le32_to_cpu(fe->permissions);
  	flags = le16_to_cpu(fe->icbTag.flags);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1565
1566
1567
1568
1569
1570
  	mode =	((permissions) & S_IRWXO) |
  		((permissions >> 2) & S_IRWXG) |
  		((permissions >> 4) & S_IRWXU) |
  		((flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) |
  		((flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) |
  		((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
1573
  
  	return mode;
  }
a9185b41a   Christoph Hellwig   pass writeback_co...
1574
  int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
  {
49521de11   Jan Kara   udf: Remove BKL f...
1576
  	return udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  }
49521de11   Jan Kara   udf: Remove BKL f...
1578
  static int udf_sync_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
1580
1581
  {
  	return udf_update_inode(inode, 1);
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1582
  static int udf_update_inode(struct inode *inode, int do_sync)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
1585
1586
  {
  	struct buffer_head *bh = NULL;
  	struct fileEntry *fe;
  	struct extendedFileEntry *efe;
b2527bfa5   Steve Nickel   udf: Fix file ent...
1587
  	uint64_t lb_recorded;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1588
1589
1590
  	uint32_t udfperms;
  	uint16_t icbflags;
  	uint16_t crclen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
  	int err = 0;
6c79e987d   Marcin Slusarz   udf: remove some ...
1592
  	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1593
  	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1594
  	struct udf_inode_info *iinfo = UDF_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595

5833ded9b   Jan Kara   udf: Do not read ...
1596
1597
  	bh = udf_tgetblk(inode->i_sb,
  			udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1598
  	if (!bh) {
aae917cd1   Jan Kara   udf: Fix unalloc ...
1599
1600
  		udf_debug("getblk failure
  ");
0fd2ba36b   Changwoo Min   udf: return corre...
1601
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
  	}
aae917cd1   Jan Kara   udf: Fix unalloc ...
1603
1604
  	lock_buffer(bh);
  	memset(bh->b_data, 0, inode->i_sb->s_blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
1606
  	fe = (struct fileEntry *)bh->b_data;
  	efe = (struct extendedFileEntry *)bh->b_data;
aae917cd1   Jan Kara   udf: Fix unalloc ...
1607
  	if (iinfo->i_use) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  		struct unallocSpaceEntry *use =
28de7948a   Cyrill Gorcunov   UDF: coding style...
1609
  			(struct unallocSpaceEntry *)bh->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1611
  		use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1612
  		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1613
  		       iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
4b11111ab   Marcin Slusarz   udf: fix coding s...
1614
  					sizeof(struct unallocSpaceEntry));
aae917cd1   Jan Kara   udf: Fix unalloc ...
1615
  		use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
70f19f586   Steven J. Magnani   udf: Don't corrup...
1616
  		crclen = sizeof(struct unallocSpaceEntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617

70f19f586   Steven J. Magnani   udf: Don't corrup...
1618
  		goto finish;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
  	}
4d6660eb3   Phillip Susi   [PATCH] udf: fix ...
1620
1621
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
  		fe->uid = cpu_to_le32(-1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1622
  	else
c2ba138a2   Eric W. Biederman   userns: Convert t...
1623
  		fe->uid = cpu_to_le32(i_uid_read(inode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624

4d6660eb3   Phillip Susi   [PATCH] udf: fix ...
1625
1626
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
  		fe->gid = cpu_to_le32(-1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1627
  	else
c2ba138a2   Eric W. Biederman   userns: Convert t...
1628
  		fe->gid = cpu_to_le32(i_gid_read(inode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629

4b11111ab   Marcin Slusarz   udf: fix coding s...
1630
1631
1632
  	udfperms = ((inode->i_mode & S_IRWXO)) |
  		   ((inode->i_mode & S_IRWXG) << 2) |
  		   ((inode->i_mode & S_IRWXU) << 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633

4b11111ab   Marcin Slusarz   udf: fix coding s...
1634
1635
1636
1637
  	udfperms |= (le32_to_cpu(fe->permissions) &
  		    (FE_PERM_O_DELETE | FE_PERM_O_CHATTR |
  		     FE_PERM_G_DELETE | FE_PERM_G_CHATTR |
  		     FE_PERM_U_DELETE | FE_PERM_U_CHATTR));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
  	fe->permissions = cpu_to_le32(udfperms);
8a70ee330   Jan Kara   udf: Avoid dir li...
1639
  	if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
1641
1642
1643
1644
  		fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
  	else
  		fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
  
  	fe->informationLength = cpu_to_le64(inode->i_size);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1645
  	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
1646
  		struct regid *eid;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1647
1648
  		struct deviceSpec *dsea =
  			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1649
  		if (!dsea) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  			dsea = (struct deviceSpec *)
28de7948a   Cyrill Gorcunov   UDF: coding style...
1651
1652
  				udf_add_extendedattr(inode,
  						     sizeof(struct deviceSpec) +
5ca4e4be8   Pekka Enberg   Remove struct typ...
1653
  						     sizeof(struct regid), 12, 0x3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
1655
  			dsea->attrType = cpu_to_le32(12);
  			dsea->attrSubtype = 1;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1656
1657
  			dsea->attrLength = cpu_to_le32(
  						sizeof(struct deviceSpec) +
5ca4e4be8   Pekka Enberg   Remove struct typ...
1658
1659
  						sizeof(struct regid));
  			dsea->impUseLength = cpu_to_le32(sizeof(struct regid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660
  		}
5ca4e4be8   Pekka Enberg   Remove struct typ...
1661
1662
  		eid = (struct regid *)dsea->impUse;
  		memset(eid, 0, sizeof(struct regid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
1664
1665
1666
1667
1668
  		strcpy(eid->ident, UDF_ID_DEVELOPER);
  		eid->identSuffix[0] = UDF_OS_CLASS_UNIX;
  		eid->identSuffix[1] = UDF_OS_ID_LINUX;
  		dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));
  		dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));
  	}
b2527bfa5   Steve Nickel   udf: Fix file ent...
1669
1670
1671
1672
1673
1674
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
  		lb_recorded = 0; /* No extents => no blocks! */
  	else
  		lb_recorded =
  			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
  			(blocksize_bits - 9);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1675
  	if (iinfo->i_efe == 0) {
c0b344385   Marcin Slusarz   udf: remove UDF_I...
1676
  		memcpy(bh->b_data + sizeof(struct fileEntry),
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1677
  		       iinfo->i_ext.i_data,
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1678
  		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
b2527bfa5   Steve Nickel   udf: Fix file ent...
1679
  		fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680

56774805d   Marcin Slusarz   udf: convert udf_...
1681
1682
1683
  		udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
  		udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
  		udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
5ca4e4be8   Pekka Enberg   Remove struct typ...
1684
  		memset(&(fe->impIdent), 0, sizeof(struct regid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
1686
1687
  		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
  		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
  		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1688
1689
1690
  		fe->uniqueID = cpu_to_le64(iinfo->i_unique);
  		fe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
  		fe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
d5e2cf07c   Steve Nickel   udf: Init/maintai...
1691
  		fe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
1693
  		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
  		crclen = sizeof(struct fileEntry);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1694
  	} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1695
  		memcpy(bh->b_data + sizeof(struct extendedFileEntry),
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1696
  		       iinfo->i_ext.i_data,
4b11111ab   Marcin Slusarz   udf: fix coding s...
1697
1698
  		       inode->i_sb->s_blocksize -
  					sizeof(struct extendedFileEntry));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1699
  		efe->objectSize = cpu_to_le64(inode->i_size);
b2527bfa5   Steve Nickel   udf: Fix file ent...
1700
  		efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1702
1703
1704
1705
  		if (iinfo->i_crtime.tv_sec > inode->i_atime.tv_sec ||
  		    (iinfo->i_crtime.tv_sec == inode->i_atime.tv_sec &&
  		     iinfo->i_crtime.tv_nsec > inode->i_atime.tv_nsec))
  			iinfo->i_crtime = inode->i_atime;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1706

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1707
1708
1709
1710
  		if (iinfo->i_crtime.tv_sec > inode->i_mtime.tv_sec ||
  		    (iinfo->i_crtime.tv_sec == inode->i_mtime.tv_sec &&
  		     iinfo->i_crtime.tv_nsec > inode->i_mtime.tv_nsec))
  			iinfo->i_crtime = inode->i_mtime;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1711

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1712
1713
1714
1715
  		if (iinfo->i_crtime.tv_sec > inode->i_ctime.tv_sec ||
  		    (iinfo->i_crtime.tv_sec == inode->i_ctime.tv_sec &&
  		     iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
  			iinfo->i_crtime = inode->i_ctime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716

56774805d   Marcin Slusarz   udf: convert udf_...
1717
1718
1719
1720
  		udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
  		udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
  		udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
  		udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721

5ca4e4be8   Pekka Enberg   Remove struct typ...
1722
  		memset(&(efe->impIdent), 0, sizeof(struct regid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
1725
  		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
  		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
  		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1726
1727
1728
  		efe->uniqueID = cpu_to_le64(iinfo->i_unique);
  		efe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
  		efe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
d5e2cf07c   Steve Nickel   udf: Init/maintai...
1729
  		efe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
1731
1732
  		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
  		crclen = sizeof(struct extendedFileEntry);
  	}
70f19f586   Steven J. Magnani   udf: Don't corrup...
1733
1734
  
  finish:
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1735
  	if (iinfo->i_strat4096) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
1738
  		fe->icbTag.strategyType = cpu_to_le16(4096);
  		fe->icbTag.strategyParameter = cpu_to_le16(1);
  		fe->icbTag.numEntries = cpu_to_le16(2);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1739
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740
1741
1742
  		fe->icbTag.strategyType = cpu_to_le16(4);
  		fe->icbTag.numEntries = cpu_to_le16(1);
  	}
70f19f586   Steven J. Magnani   udf: Don't corrup...
1743
1744
1745
  	if (iinfo->i_use)
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_USE;
  	else if (S_ISDIR(inode->i_mode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY;
  	else if (S_ISREG(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;
  	else if (S_ISLNK(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK;
  	else if (S_ISBLK(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK;
  	else if (S_ISCHR(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
  	else if (S_ISFIFO(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;
  	else if (S_ISSOCK(inode->i_mode))
  		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1759
  	icbflags =	iinfo->i_alloc_type |
28de7948a   Cyrill Gorcunov   UDF: coding style...
1760
1761
1762
1763
1764
1765
  			((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |
  			((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) |
  			((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) |
  			(le16_to_cpu(fe->icbTag.flags) &
  				~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID |
  				ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
  
  	fe->icbTag.flags = cpu_to_le16(icbflags);
6c79e987d   Marcin Slusarz   udf: remove some ...
1768
  	if (sbi->s_udfrev >= 0x0200)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
1771
  		fe->descTag.descVersion = cpu_to_le16(3);
  	else
  		fe->descTag.descVersion = cpu_to_le16(2);
6c79e987d   Marcin Slusarz   udf: remove some ...
1772
  	fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1773
  	fe->descTag.tagLocation = cpu_to_le32(
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1774
  					iinfo->i_location.logicalBlockNum);
aae917cd1   Jan Kara   udf: Fix unalloc ...
1775
  	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776
  	fe->descTag.descCRCLength = cpu_to_le16(crclen);
5ca4e4be8   Pekka Enberg   Remove struct typ...
1777
  	fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
f845fced9   Bob Copeland   udf: use crc_itu_...
1778
  						  crclen));
3f2587bb2   Marcin Slusarz   udf: create commo...
1779
  	fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780

5833ded9b   Jan Kara   udf: Do not read ...
1781
  	set_buffer_uptodate(bh);
aae917cd1   Jan Kara   udf: Fix unalloc ...
1782
  	unlock_buffer(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
1784
  	/* write the data blocks */
  	mark_buffer_dirty(bh);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1785
  	if (do_sync) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
  		sync_dirty_buffer(bh);
aae917cd1   Jan Kara   udf: Fix unalloc ...
1787
  		if (buffer_write_io_error(bh)) {
78ace70c4   Joe Perches   udf: Convert prin...
1788
1789
1790
  			udf_warn(inode->i_sb, "IO error syncing udf inode [%08lx]
  ",
  				 inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
1793
  			err = -EIO;
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
1794
  	brelse(bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
1795

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796
1797
  	return err;
  }
6174c2eb8   Jan Kara   udf: Fix loading ...
1798
1799
  struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
  			 bool hidden_inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
1801
1802
  {
  	unsigned long block = udf_get_lb_pblock(sb, ino, 0);
  	struct inode *inode = iget_locked(sb, block);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1803
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
1805
  
  	if (!inode)
6d3d5e860   Jan Kara   udf: Make udf_rea...
1806
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1807

6d3d5e860   Jan Kara   udf: Make udf_rea...
1808
1809
  	if (!(inode->i_state & I_NEW))
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810

6d3d5e860   Jan Kara   udf: Make udf_rea...
1811
  	memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
6174c2eb8   Jan Kara   udf: Fix loading ...
1812
  	err = udf_read_inode(inode, hidden_inode);
6d3d5e860   Jan Kara   udf: Make udf_rea...
1813
1814
1815
  	if (err < 0) {
  		iget_failed(inode);
  		return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
  	}
6d3d5e860   Jan Kara   udf: Make udf_rea...
1817
  	unlock_new_inode(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
  
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
  }
fcea62bab   Jan Kara   udf: Factor out c...
1821
1822
  int udf_setup_indirect_aext(struct inode *inode, int block,
  			    struct extent_position *epos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823
  {
fcea62bab   Jan Kara   udf: Factor out c...
1824
1825
  	struct super_block *sb = inode->i_sb;
  	struct buffer_head *bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
  	struct allocExtDesc *aed;
fcea62bab   Jan Kara   udf: Factor out c...
1827
1828
1829
  	struct extent_position nepos;
  	struct kernel_lb_addr neloc;
  	int ver, adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830

fcea62bab   Jan Kara   udf: Factor out c...
1831
1832
1833
1834
  	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  		adsize = sizeof(struct short_ad);
  	else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  		adsize = sizeof(struct long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1835
  	else
4f1b1519f   Arnd Bergmann   udf: avoid uninit...
1836
  		return -EIO;
fcea62bab   Jan Kara   udf: Factor out c...
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
  
  	neloc.logicalBlockNum = block;
  	neloc.partitionReferenceNum = epos->block.partitionReferenceNum;
  
  	bh = udf_tgetblk(sb, udf_get_lb_pblock(sb, &neloc, 0));
  	if (!bh)
  		return -EIO;
  	lock_buffer(bh);
  	memset(bh->b_data, 0x00, sb->s_blocksize);
  	set_buffer_uptodate(bh);
  	unlock_buffer(bh);
  	mark_buffer_dirty_inode(bh, inode);
  
  	aed = (struct allocExtDesc *)(bh->b_data);
  	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) {
  		aed->previousAllocExtLocation =
  				cpu_to_le32(epos->block.logicalBlockNum);
  	}
  	aed->lengthAllocDescs = cpu_to_le32(0);
  	if (UDF_SB(sb)->s_udfrev >= 0x0200)
  		ver = 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
  	else
fcea62bab   Jan Kara   udf: Factor out c...
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
  		ver = 2;
  	udf_new_tag(bh->b_data, TAG_IDENT_AED, ver, 1, block,
  		    sizeof(struct tag));
  
  	nepos.block = neloc;
  	nepos.offset = sizeof(struct allocExtDesc);
  	nepos.bh = bh;
  
  	/*
  	 * Do we have to copy current last extent to make space for indirect
  	 * one?
  	 */
  	if (epos->offset + adsize > sb->s_blocksize) {
  		struct kernel_lb_addr cp_loc;
  		uint32_t cp_len;
  		int cp_type;
  
  		epos->offset -= adsize;
  		cp_type = udf_current_aext(inode, epos, &cp_loc, &cp_len, 0);
  		cp_len |= ((uint32_t)cp_type) << 30;
  
  		__udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1);
  		udf_write_aext(inode, epos, &nepos.block,
  			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0);
  	} else {
  		__udf_add_aext(inode, epos, &nepos.block,
  			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0);
  	}
  
  	brelse(epos->bh);
  	*epos = nepos;
  
  	return 0;
  }
  
  /*
   * Append extent at the given position - should be the first free one in inode
   * / indirect extent. This function assumes there is enough space in the inode
   * or indirect extent. Use udf_add_aext() if you didn't check for this before.
   */
  int __udf_add_aext(struct inode *inode, struct extent_position *epos,
  		   struct kernel_lb_addr *eloc, uint32_t elen, int inc)
  {
  	struct udf_inode_info *iinfo = UDF_I(inode);
  	struct allocExtDesc *aed;
  	int adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1906
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
1907
  		adsize = sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1908
  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
1909
  		adsize = sizeof(struct long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
  	else
7e49b6f24   Jan Kara   udf: Convert UDF ...
1911
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912

fcea62bab   Jan Kara   udf: Factor out c...
1913
1914
1915
1916
1917
1918
1919
1920
  	if (!epos->bh) {
  		WARN_ON(iinfo->i_lenAlloc !=
  			epos->offset - udf_file_entry_alloc_offset(inode));
  	} else {
  		aed = (struct allocExtDesc *)epos->bh->b_data;
  		WARN_ON(le32_to_cpu(aed->lengthAllocDescs) !=
  			epos->offset - sizeof(struct allocExtDesc));
  		WARN_ON(epos->offset + adsize > inode->i_sb->s_blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  	}
7e49b6f24   Jan Kara   udf: Convert UDF ...
1922
  	udf_write_aext(inode, epos, eloc, elen, inc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1924
  	if (!epos->bh) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1925
  		iinfo->i_lenAlloc += adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  		mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1927
  	} else {
ff116fc8d   Jan Kara   UDF: introduce st...
1928
  		aed = (struct allocExtDesc *)epos->bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
1929
  		le32_add_cpu(&aed->lengthAllocDescs, adsize);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1930
1931
1932
1933
  		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
  				UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
  			udf_update_tag(epos->bh->b_data,
  					epos->offset + (inc ? 0 : adsize));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
  		else
4b11111ab   Marcin Slusarz   udf: fix coding s...
1935
1936
  			udf_update_tag(epos->bh->b_data,
  					sizeof(struct allocExtDesc));
ff116fc8d   Jan Kara   UDF: introduce st...
1937
  		mark_buffer_dirty_inode(epos->bh, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
  	}
7e49b6f24   Jan Kara   udf: Convert UDF ...
1939
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
  }
fcea62bab   Jan Kara   udf: Factor out c...
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
  /*
   * Append extent at given position - should be the first free one in inode
   * / indirect extent. Takes care of allocating and linking indirect blocks.
   */
  int udf_add_aext(struct inode *inode, struct extent_position *epos,
  		 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
  {
  	int adsize;
  	struct super_block *sb = inode->i_sb;
  
  	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  		adsize = sizeof(struct short_ad);
  	else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  		adsize = sizeof(struct long_ad);
  	else
  		return -EIO;
  
  	if (epos->offset + (2 * adsize) > sb->s_blocksize) {
  		int err;
  		int new_block;
  
  		new_block = udf_new_block(sb, NULL,
  					  epos->block.partitionReferenceNum,
  					  epos->block.logicalBlockNum, &err);
  		if (!new_block)
  			return -ENOSPC;
  
  		err = udf_setup_indirect_aext(inode, new_block, epos);
  		if (err)
  			return err;
  	}
  
  	return __udf_add_aext(inode, epos, eloc, elen, inc);
  }
7e49b6f24   Jan Kara   udf: Convert UDF ...
1975
1976
  void udf_write_aext(struct inode *inode, struct extent_position *epos,
  		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
1978
1979
  {
  	int adsize;
  	uint8_t *ptr;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1980
1981
  	struct short_ad *sad;
  	struct long_ad *lad;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1982
  	struct udf_inode_info *iinfo = UDF_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1983

ff116fc8d   Jan Kara   UDF: introduce st...
1984
  	if (!epos->bh)
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1985
  		ptr = iinfo->i_ext.i_data + epos->offset -
4b11111ab   Marcin Slusarz   udf: fix coding s...
1986
  			udf_file_entry_alloc_offset(inode) +
48d6d8ff7   Marcin Slusarz   udf: cache struct...
1987
  			iinfo->i_lenEAttr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988
  	else
ff116fc8d   Jan Kara   UDF: introduce st...
1989
  		ptr = epos->bh->b_data + epos->offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990

48d6d8ff7   Marcin Slusarz   udf: cache struct...
1991
  	switch (iinfo->i_alloc_type) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1992
  	case ICBTAG_FLAG_AD_SHORT:
5ca4e4be8   Pekka Enberg   Remove struct typ...
1993
  		sad = (struct short_ad *)ptr;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1994
  		sad->extLength = cpu_to_le32(elen);
97e961fdb   Pekka Enberg   Fix the udf code ...
1995
  		sad->extPosition = cpu_to_le32(eloc->logicalBlockNum);
5ca4e4be8   Pekka Enberg   Remove struct typ...
1996
  		adsize = sizeof(struct short_ad);
28de7948a   Cyrill Gorcunov   UDF: coding style...
1997
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1998
  	case ICBTAG_FLAG_AD_LONG:
5ca4e4be8   Pekka Enberg   Remove struct typ...
1999
  		lad = (struct long_ad *)ptr;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2000
  		lad->extLength = cpu_to_le32(elen);
97e961fdb   Pekka Enberg   Fix the udf code ...
2001
  		lad->extLocation = cpu_to_lelb(*eloc);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2002
  		memset(lad->impUse, 0x00, sizeof(lad->impUse));
5ca4e4be8   Pekka Enberg   Remove struct typ...
2003
  		adsize = sizeof(struct long_ad);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2004
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2005
  	default:
7e49b6f24   Jan Kara   udf: Convert UDF ...
2006
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2008
  	if (epos->bh) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
2009
  		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
6c79e987d   Marcin Slusarz   udf: remove some ...
2010
  		    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2011
2012
  			struct allocExtDesc *aed =
  				(struct allocExtDesc *)epos->bh->b_data;
ff116fc8d   Jan Kara   UDF: introduce st...
2013
  			udf_update_tag(epos->bh->b_data,
4b11111ab   Marcin Slusarz   udf: fix coding s...
2014
2015
  				       le32_to_cpu(aed->lengthAllocDescs) +
  				       sizeof(struct allocExtDesc));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
  		}
ff116fc8d   Jan Kara   UDF: introduce st...
2017
  		mark_buffer_dirty_inode(epos->bh, inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2018
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2019
  		mark_inode_dirty(inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2020
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
2022
  
  	if (inc)
ff116fc8d   Jan Kara   UDF: introduce st...
2023
  		epos->offset += adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2024
  }
b0918d9f4   Vegard Nossum   udf: limit the ma...
2025
2026
2027
2028
2029
  /*
   * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
   * someone does some weird stuff.
   */
  #define UDF_MAX_INDIR_EXTS 16
4b11111ab   Marcin Slusarz   udf: fix coding s...
2030
  int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
5ca4e4be8   Pekka Enberg   Remove struct typ...
2031
  		     struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2032
2033
  {
  	int8_t etype;
b0918d9f4   Vegard Nossum   udf: limit the ma...
2034
  	unsigned int indirections = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2035

ff116fc8d   Jan Kara   UDF: introduce st...
2036
  	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2037
  	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2038
  		int block;
b0918d9f4   Vegard Nossum   udf: limit the ma...
2039
2040
2041
2042
2043
2044
2045
2046
  
  		if (++indirections > UDF_MAX_INDIR_EXTS) {
  			udf_err(inode->i_sb,
  				"too many indirect extents in inode %lu
  ",
  				inode->i_ino);
  			return -1;
  		}
ff116fc8d   Jan Kara   UDF: introduce st...
2047
2048
  		epos->block = *eloc;
  		epos->offset = sizeof(struct allocExtDesc);
3bf25cb40   Jan Kara   udf: use get_bh()
2049
  		brelse(epos->bh);
97e961fdb   Pekka Enberg   Fix the udf code ...
2050
  		block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0);
4b11111ab   Marcin Slusarz   udf: fix coding s...
2051
2052
2053
2054
  		epos->bh = udf_tread(inode->i_sb, block);
  		if (!epos->bh) {
  			udf_debug("reading block %d failed!
  ", block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2055
2056
2057
2058
2059
2060
  			return -1;
  		}
  	}
  
  	return etype;
  }
4b11111ab   Marcin Slusarz   udf: fix coding s...
2061
  int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
5ca4e4be8   Pekka Enberg   Remove struct typ...
2062
  			struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2063
2064
2065
2066
  {
  	int alen;
  	int8_t etype;
  	uint8_t *ptr;
5ca4e4be8   Pekka Enberg   Remove struct typ...
2067
2068
  	struct short_ad *sad;
  	struct long_ad *lad;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2069
  	struct udf_inode_info *iinfo = UDF_I(inode);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2070

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2071
  	if (!epos->bh) {
ff116fc8d   Jan Kara   UDF: introduce st...
2072
2073
  		if (!epos->offset)
  			epos->offset = udf_file_entry_alloc_offset(inode);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2074
  		ptr = iinfo->i_ext.i_data + epos->offset -
4b11111ab   Marcin Slusarz   udf: fix coding s...
2075
  			udf_file_entry_alloc_offset(inode) +
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2076
  			iinfo->i_lenEAttr;
4b11111ab   Marcin Slusarz   udf: fix coding s...
2077
  		alen = udf_file_entry_alloc_offset(inode) +
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2078
  							iinfo->i_lenAlloc;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2079
  	} else {
ff116fc8d   Jan Kara   UDF: introduce st...
2080
2081
2082
  		if (!epos->offset)
  			epos->offset = sizeof(struct allocExtDesc);
  		ptr = epos->bh->b_data + epos->offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2083
  		alen = sizeof(struct allocExtDesc) +
4b11111ab   Marcin Slusarz   udf: fix coding s...
2084
2085
  			le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->
  							lengthAllocDescs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086
  	}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2087
  	switch (iinfo->i_alloc_type) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2088
  	case ICBTAG_FLAG_AD_SHORT:
4b11111ab   Marcin Slusarz   udf: fix coding s...
2089
2090
  		sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc);
  		if (!sad)
28de7948a   Cyrill Gorcunov   UDF: coding style...
2091
2092
2093
  			return -1;
  		etype = le32_to_cpu(sad->extLength) >> 30;
  		eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
4b11111ab   Marcin Slusarz   udf: fix coding s...
2094
  		eloc->partitionReferenceNum =
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2095
  				iinfo->i_location.partitionReferenceNum;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2096
2097
  		*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
  		break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2098
  	case ICBTAG_FLAG_AD_LONG:
4b11111ab   Marcin Slusarz   udf: fix coding s...
2099
2100
  		lad = udf_get_filelongad(ptr, alen, &epos->offset, inc);
  		if (!lad)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2101
  			return -1;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2102
2103
2104
2105
2106
  		etype = le32_to_cpu(lad->extLength) >> 30;
  		*eloc = lelb_to_cpu(lad->extLocation);
  		*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
  		break;
  	default:
a983f368f   Joe Perches   udf: Neaten udf_d...
2107
2108
  		udf_debug("alloc_type = %d unsupported
  ", iinfo->i_alloc_type);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2109
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2110
2111
2112
2113
  	}
  
  	return etype;
  }
28de7948a   Cyrill Gorcunov   UDF: coding style...
2114
  static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos,
5ca4e4be8   Pekka Enberg   Remove struct typ...
2115
  			      struct kernel_lb_addr neloc, uint32_t nelen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2116
  {
5ca4e4be8   Pekka Enberg   Remove struct typ...
2117
  	struct kernel_lb_addr oeloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2118
2119
  	uint32_t oelen;
  	int8_t etype;
ff116fc8d   Jan Kara   UDF: introduce st...
2120
  	if (epos.bh)
3bf25cb40   Jan Kara   udf: use get_bh()
2121
  		get_bh(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2123
  	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {
97e961fdb   Pekka Enberg   Fix the udf code ...
2124
  		udf_write_aext(inode, &epos, &neloc, nelen, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2125
2126
2127
  		neloc = oeloc;
  		nelen = (etype << 30) | oelen;
  	}
97e961fdb   Pekka Enberg   Fix the udf code ...
2128
  	udf_add_aext(inode, &epos, &neloc, nelen, 1);
3bf25cb40   Jan Kara   udf: use get_bh()
2129
  	brelse(epos.bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2130

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2131
2132
  	return (nelen >> 30);
  }
4b11111ab   Marcin Slusarz   udf: fix coding s...
2133
  int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
5ca4e4be8   Pekka Enberg   Remove struct typ...
2134
  		       struct kernel_lb_addr eloc, uint32_t elen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
  {
ff116fc8d   Jan Kara   UDF: introduce st...
2136
2137
  	struct extent_position oepos;
  	int adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
2139
  	int8_t etype;
  	struct allocExtDesc *aed;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2140
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2142
  	if (epos.bh) {
3bf25cb40   Jan Kara   udf: use get_bh()
2143
2144
  		get_bh(epos.bh);
  		get_bh(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2145
  	}
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2146
2147
  	iinfo = UDF_I(inode);
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
5ca4e4be8   Pekka Enberg   Remove struct typ...
2148
  		adsize = sizeof(struct short_ad);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2149
  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
5ca4e4be8   Pekka Enberg   Remove struct typ...
2150
  		adsize = sizeof(struct long_ad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2151
2152
  	else
  		adsize = 0;
ff116fc8d   Jan Kara   UDF: introduce st...
2153
2154
  	oepos = epos;
  	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2155
  		return -1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2156
  	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
97e961fdb   Pekka Enberg   Fix the udf code ...
2157
  		udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2158
  		if (oepos.bh != epos.bh) {
ff116fc8d   Jan Kara   UDF: introduce st...
2159
  			oepos.block = epos.block;
3bf25cb40   Jan Kara   udf: use get_bh()
2160
2161
  			brelse(oepos.bh);
  			get_bh(epos.bh);
ff116fc8d   Jan Kara   UDF: introduce st...
2162
2163
  			oepos.bh = epos.bh;
  			oepos.offset = epos.offset - adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
  		}
  	}
5ca4e4be8   Pekka Enberg   Remove struct typ...
2166
  	memset(&eloc, 0x00, sizeof(struct kernel_lb_addr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2167
  	elen = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2168
  	if (epos.bh != oepos.bh) {
97e961fdb   Pekka Enberg   Fix the udf code ...
2169
2170
2171
  		udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1);
  		udf_write_aext(inode, &oepos, &eloc, elen, 1);
  		udf_write_aext(inode, &oepos, &eloc, elen, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2172
  		if (!oepos.bh) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2173
  			iinfo->i_lenAlloc -= (adsize * 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174
  			mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2175
  		} else {
ff116fc8d   Jan Kara   UDF: introduce st...
2176
  			aed = (struct allocExtDesc *)oepos.bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
2177
  			le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
28de7948a   Cyrill Gorcunov   UDF: coding style...
2178
  			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
6c79e987d   Marcin Slusarz   udf: remove some ...
2179
  			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
4b11111ab   Marcin Slusarz   udf: fix coding s...
2180
2181
  				udf_update_tag(oepos.bh->b_data,
  						oepos.offset - (2 * adsize));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2182
  			else
4b11111ab   Marcin Slusarz   udf: fix coding s...
2183
2184
  				udf_update_tag(oepos.bh->b_data,
  						sizeof(struct allocExtDesc));
ff116fc8d   Jan Kara   UDF: introduce st...
2185
  			mark_buffer_dirty_inode(oepos.bh, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2186
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2187
  	} else {
97e961fdb   Pekka Enberg   Fix the udf code ...
2188
  		udf_write_aext(inode, &oepos, &eloc, elen, 1);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2189
  		if (!oepos.bh) {
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2190
  			iinfo->i_lenAlloc -= adsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
  			mark_inode_dirty(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2192
  		} else {
ff116fc8d   Jan Kara   UDF: introduce st...
2193
  			aed = (struct allocExtDesc *)oepos.bh->b_data;
c2104fda5   marcin.slusarz@gmail.com   udf: replace all ...
2194
  			le32_add_cpu(&aed->lengthAllocDescs, -adsize);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2195
  			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
6c79e987d   Marcin Slusarz   udf: remove some ...
2196
  			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
4b11111ab   Marcin Slusarz   udf: fix coding s...
2197
2198
  				udf_update_tag(oepos.bh->b_data,
  						epos.offset - adsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199
  			else
4b11111ab   Marcin Slusarz   udf: fix coding s...
2200
2201
  				udf_update_tag(oepos.bh->b_data,
  						sizeof(struct allocExtDesc));
ff116fc8d   Jan Kara   UDF: introduce st...
2202
  			mark_buffer_dirty_inode(oepos.bh, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203
2204
  		}
  	}
647bd61a5   Cyrill Gorcunov   UDF: check for al...
2205

3bf25cb40   Jan Kara   udf: use get_bh()
2206
2207
  	brelse(epos.bh);
  	brelse(oepos.bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2208

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2209
2210
  	return (elen >> 30);
  }
4b11111ab   Marcin Slusarz   udf: fix coding s...
2211
  int8_t inode_bmap(struct inode *inode, sector_t block,
5ca4e4be8   Pekka Enberg   Remove struct typ...
2212
  		  struct extent_position *pos, struct kernel_lb_addr *eloc,
4b11111ab   Marcin Slusarz   udf: fix coding s...
2213
  		  uint32_t *elen, sector_t *offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2214
  {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2215
  	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2216
  	loff_t lbcount = 0, bcount =
4b11111ab   Marcin Slusarz   udf: fix coding s...
2217
  	    (loff_t) block << blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2218
  	int8_t etype;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2219
  	struct udf_inode_info *iinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2220

48d6d8ff7   Marcin Slusarz   udf: cache struct...
2221
  	iinfo = UDF_I(inode);
99600051b   Namjae Jeon   udf: add extent c...
2222
2223
2224
2225
2226
  	if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) {
  		pos->offset = 0;
  		pos->block = iinfo->i_location;
  		pos->bh = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
  	*elen = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2228
  	do {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2229
2230
2231
  		etype = udf_next_aext(inode, pos, eloc, elen, 1);
  		if (etype == -1) {
  			*offset = (bcount - lbcount) >> blocksize_bits;
48d6d8ff7   Marcin Slusarz   udf: cache struct...
2232
  			iinfo->i_lenExtents = lbcount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233
2234
2235
2236
  			return -1;
  		}
  		lbcount += *elen;
  	} while (lbcount <= bcount);
99600051b   Namjae Jeon   udf: add extent c...
2237
2238
  	/* update extent cache */
  	udf_update_extent_cache(inode, lbcount - *elen, pos, 1);
4b11111ab   Marcin Slusarz   udf: fix coding s...
2239
  	*offset = (bcount + *elen - lbcount) >> blocksize_bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2240
2241
2242
  
  	return etype;
  }
60448b1d6   Jan Kara   udf: use sector_t...
2243
  long udf_block_map(struct inode *inode, sector_t block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2244
  {
5ca4e4be8   Pekka Enberg   Remove struct typ...
2245
  	struct kernel_lb_addr eloc;
ff116fc8d   Jan Kara   UDF: introduce st...
2246
  	uint32_t elen;
60448b1d6   Jan Kara   udf: use sector_t...
2247
  	sector_t offset;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2248
  	struct extent_position epos = {};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249
  	int ret;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
2250
  	down_read(&UDF_I(inode)->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2251

4b11111ab   Marcin Slusarz   udf: fix coding s...
2252
2253
  	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==
  						(EXT_RECORDED_ALLOCATED >> 30))
97e961fdb   Pekka Enberg   Fix the udf code ...
2254
  		ret = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2255
2256
  	else
  		ret = 0;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
2257
  	up_read(&UDF_I(inode)->i_data_sem);
3bf25cb40   Jan Kara   udf: use get_bh()
2258
  	brelse(epos.bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2259
2260
2261
2262
2263
2264
  
  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
  		return udf_fixed_to_variable(ret);
  	else
  		return ret;
  }