inode.c 58.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * inode.c
 *
 * PURPOSE
 *  Inode handling routines for the OSTA-UDF(tm) filesystem.
 *
 * 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
M
Marcin Slusarz 已提交
22 23
 *  12/06/98 blf  partition support in udf_iget, udf_block_map
 *                and udf_read_inode
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 *  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>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/slab.h>
40
#include <linux/crc-itu-t.h>
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53

#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

static mode_t udf_convert_permissions(struct fileEntry *);
static int udf_update_inode(struct inode *, int);
static void udf_fill_inode(struct inode *, struct buffer_head *);
54
static int udf_alloc_i_data(struct inode *inode, size_t size);
55
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
56
					sector_t *, int *);
J
Jan Kara 已提交
57
static int8_t udf_insert_aext(struct inode *, struct extent_position,
58
			      struct kernel_lb_addr, uint32_t);
L
Linus Torvalds 已提交
59
static void udf_split_extents(struct inode *, int *, int, int,
60
			      struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
L
Linus Torvalds 已提交
61
static void udf_prealloc_extents(struct inode *, int, int,
62
				 struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
L
Linus Torvalds 已提交
63
static void udf_merge_extents(struct inode *,
64
			      struct kernel_long_ad[EXTENT_MERGE_SIZE], int *);
L
Linus Torvalds 已提交
65
static void udf_update_extents(struct inode *,
66
			       struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int,
67
			       struct extent_position *);
L
Linus Torvalds 已提交
68 69
static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);

70

71
void udf_delete_inode(struct inode *inode)
L
Linus Torvalds 已提交
72
{
73 74
	truncate_inode_pages(&inode->i_data, 0);

L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85 86
	if (is_bad_inode(inode))
		goto no_delete;

	inode->i_size = 0;
	udf_truncate(inode);
	lock_kernel();

	udf_update_inode(inode, IS_SYNC(inode));
	udf_free_inode(inode);

	unlock_kernel();
	return;
87 88

no_delete:
L
Linus Torvalds 已提交
89 90 91
	clear_inode(inode);
}

J
Jan Kara 已提交
92
/*
93 94 95 96
 * If we are going to release inode from memory, we truncate last inode extent
 * to proper length. We could use drop_inode() but it's called under inode_lock
 * and thus we cannot mark inode dirty there.  We use clear_inode() but we have
 * to make sure to write inode as it's not written automatically.
J
Jan Kara 已提交
97
 */
L
Linus Torvalds 已提交
98 99
void udf_clear_inode(struct inode *inode)
{
J
Jan Kara 已提交
100 101 102 103 104
	struct udf_inode_info *iinfo = UDF_I(inode);

	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
	    inode->i_size != iinfo->i_lenExtents) {
		printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has "
105
			"inode size %llu different from extent length %llu. "
J
Jan Kara 已提交
106 107 108 109
			"Filesystem need not be standards compliant.\n",
			inode->i_sb->s_id, inode->i_ino, inode->i_mode,
			(unsigned long long)inode->i_size,
			(unsigned long long)iinfo->i_lenExtents);
L
Linus Torvalds 已提交
110
	}
111

112 113
	kfree(iinfo->i_ext.i_data);
	iinfo->i_ext.i_data = NULL;
L
Linus Torvalds 已提交
114 115 116 117 118 119 120 121 122 123 124 125
}

static int udf_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page, udf_get_block, wbc);
}

static int udf_readpage(struct file *file, struct page *page)
{
	return block_read_full_page(page, udf_get_block);
}

N
Nick Piggin 已提交
126 127 128
static int udf_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
L
Linus Torvalds 已提交
129
{
N
Nick Piggin 已提交
130 131 132
	*pagep = NULL;
	return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
				udf_get_block);
L
Linus Torvalds 已提交
133 134 135 136
}

static sector_t udf_bmap(struct address_space *mapping, sector_t block)
{
137
	return generic_block_bmap(mapping, block, udf_get_block);
L
Linus Torvalds 已提交
138 139
}

140
const struct address_space_operations udf_aops = {
141 142 143
	.readpage	= udf_readpage,
	.writepage	= udf_writepage,
	.sync_page	= block_sync_page,
N
Nick Piggin 已提交
144 145
	.write_begin		= udf_write_begin,
	.write_end		= generic_write_end,
146
	.bmap		= udf_bmap,
L
Linus Torvalds 已提交
147 148
};

149
void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
L
Linus Torvalds 已提交
150 151 152
{
	struct page *page;
	char *kaddr;
153
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161
	struct writeback_control udf_wbc = {
		.sync_mode = WB_SYNC_NONE,
		.nr_to_write = 1,
	};

	/* from now on we have normal address_space methods */
	inode->i_data.a_ops = &udf_aops;

162
	if (!iinfo->i_lenAlloc) {
L
Linus Torvalds 已提交
163
		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
164
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
L
Linus Torvalds 已提交
165
		else
166
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
L
Linus Torvalds 已提交
167 168 169 170 171
		mark_inode_dirty(inode);
		return;
	}

	page = grab_cache_page(inode->i_mapping, 0);
M
Matt Mackall 已提交
172 173
	BUG_ON(!PageLocked(page));

174
	if (!PageUptodate(page)) {
L
Linus Torvalds 已提交
175
		kaddr = kmap(page);
176 177 178 179
		memset(kaddr + iinfo->i_lenAlloc, 0x00,
		       PAGE_CACHE_SIZE - iinfo->i_lenAlloc);
		memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr,
			iinfo->i_lenAlloc);
L
Linus Torvalds 已提交
180 181 182 183
		flush_dcache_page(page);
		SetPageUptodate(page);
		kunmap(page);
	}
184 185 186
	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00,
	       iinfo->i_lenAlloc);
	iinfo->i_lenAlloc = 0;
L
Linus Torvalds 已提交
187
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
188
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
L
Linus Torvalds 已提交
189
	else
190
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
L
Linus Torvalds 已提交
191 192 193 194 195 196 197

	inode->i_data.a_ops->writepage(page, &udf_wbc);
	page_cache_release(page);

	mark_inode_dirty(inode);
}

198 199
struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
					   int *err)
L
Linus Torvalds 已提交
200 201
{
	int newblock;
J
Jan Kara 已提交
202
	struct buffer_head *dbh = NULL;
203
	struct kernel_lb_addr eloc;
L
Linus Torvalds 已提交
204
	uint8_t alloctype;
J
Jan Kara 已提交
205
	struct extent_position epos;
L
Linus Torvalds 已提交
206 207

	struct udf_fileident_bh sfibh, dfibh;
208 209
	loff_t f_pos = udf_ext0_offset(inode);
	int size = udf_ext0_offset(inode) + inode->i_size;
L
Linus Torvalds 已提交
210
	struct fileIdentDesc cfi, *sfi, *dfi;
211
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
212 213 214 215 216 217

	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
		alloctype = ICBTAG_FLAG_AD_SHORT;
	else
		alloctype = ICBTAG_FLAG_AD_LONG;

218
	if (!inode->i_size) {
219
		iinfo->i_alloc_type = alloctype;
L
Linus Torvalds 已提交
220 221 222 223 224 225
		mark_inode_dirty(inode);
		return NULL;
	}

	/* alloc block, and copy data to it */
	*block = udf_new_block(inode->i_sb, inode,
226 227
			       iinfo->i_location.partitionReferenceNum,
			       iinfo->i_location.logicalBlockNum, err);
L
Linus Torvalds 已提交
228 229 230
	if (!(*block))
		return NULL;
	newblock = udf_get_pblock(inode->i_sb, *block,
231
				  iinfo->i_location.partitionReferenceNum,
232
				0);
L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240 241 242 243
	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);

M
Marcin Slusarz 已提交
244
	sfibh.soffset = sfibh.eoffset =
245
			f_pos & (inode->i_sb->s_blocksize - 1);
J
Jan Kara 已提交
246
	sfibh.sbh = sfibh.ebh = NULL;
L
Linus Torvalds 已提交
247 248
	dfibh.soffset = dfibh.eoffset = 0;
	dfibh.sbh = dfibh.ebh = dbh;
249
	while (f_pos < size) {
250
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
M
Marcin Slusarz 已提交
251 252
		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL,
					 NULL, NULL, NULL);
253
		if (!sfi) {
J
Jan Kara 已提交
254
			brelse(dbh);
L
Linus Torvalds 已提交
255 256
			return NULL;
		}
257
		iinfo->i_alloc_type = alloctype;
L
Linus Torvalds 已提交
258 259 260 261 262
		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,
M
Marcin Slusarz 已提交
263 264
				 sfi->fileIdent +
					le16_to_cpu(sfi->lengthOfImpUse))) {
265
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
J
Jan Kara 已提交
266
			brelse(dbh);
L
Linus Torvalds 已提交
267 268 269 270 271
			return NULL;
		}
	}
	mark_buffer_dirty_inode(dbh, inode);

272 273 274
	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0,
		iinfo->i_lenAlloc);
	iinfo->i_lenAlloc = 0;
L
Linus Torvalds 已提交
275
	eloc.logicalBlockNum = *block;
M
Marcin Slusarz 已提交
276
	eloc.partitionReferenceNum =
277
				iinfo->i_location.partitionReferenceNum;
J
Jan Kara 已提交
278
	iinfo->i_lenExtents = inode->i_size;
J
Jan Kara 已提交
279
	epos.bh = NULL;
280
	epos.block = iinfo->i_location;
J
Jan Kara 已提交
281
	epos.offset = udf_file_entry_alloc_offset(inode);
J
Jan Kara 已提交
282
	udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
L
Linus Torvalds 已提交
283 284
	/* UniqueID stuff */

J
Jan Kara 已提交
285
	brelse(epos.bh);
L
Linus Torvalds 已提交
286 287 288 289
	mark_inode_dirty(inode);
	return dbh;
}

290 291
static int udf_get_block(struct inode *inode, sector_t block,
			 struct buffer_head *bh_result, int create)
L
Linus Torvalds 已提交
292 293 294
{
	int err, new;
	struct buffer_head *bh;
295
	sector_t phys = 0;
296
	struct udf_inode_info *iinfo;
L
Linus Torvalds 已提交
297

298
	if (!create) {
L
Linus Torvalds 已提交
299 300 301 302 303 304 305 306 307 308 309 310
		phys = udf_block_map(inode, block);
		if (phys)
			map_bh(bh_result, inode->i_sb, phys);
		return 0;
	}

	err = -EIO;
	new = 0;
	bh = NULL;

	lock_kernel();

311 312 313 314
	iinfo = UDF_I(inode);
	if (block == iinfo->i_next_alloc_block + 1) {
		iinfo->i_next_alloc_block++;
		iinfo->i_next_alloc_goal++;
L
Linus Torvalds 已提交
315 316 317 318 319
	}

	err = 0;

	bh = inode_getblk(inode, block, &err, &phys, &new);
E
Eric Sesterhenn 已提交
320
	BUG_ON(bh);
L
Linus Torvalds 已提交
321 322
	if (err)
		goto abort;
E
Eric Sesterhenn 已提交
323
	BUG_ON(!phys);
L
Linus Torvalds 已提交
324 325 326 327

	if (new)
		set_buffer_new(bh_result);
	map_bh(bh_result, inode->i_sb, phys);
328 329

abort:
L
Linus Torvalds 已提交
330 331 332 333
	unlock_kernel();
	return err;
}

334 335
static struct buffer_head *udf_getblk(struct inode *inode, long block,
				      int create, int *err)
L
Linus Torvalds 已提交
336
{
337
	struct buffer_head *bh;
L
Linus Torvalds 已提交
338 339 340 341 342
	struct buffer_head dummy;

	dummy.b_state = 0;
	dummy.b_blocknr = -1000;
	*err = udf_get_block(inode, block, &dummy, create);
343
	if (!*err && buffer_mapped(&dummy)) {
L
Linus Torvalds 已提交
344
		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
345
		if (buffer_new(&dummy)) {
L
Linus Torvalds 已提交
346 347 348 349 350 351 352 353
			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;
	}
354

L
Linus Torvalds 已提交
355 356 357
	return NULL;
}

J
Jan Kara 已提交
358 359
/* Extend the file by 'blocks' blocks, return the number of extents added */
int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
360
		    struct kernel_long_ad *last_ext, sector_t blocks)
J
Jan Kara 已提交
361 362 363 364
{
	sector_t add;
	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
	struct super_block *sb = inode->i_sb;
365
	struct kernel_lb_addr prealloc_loc = {};
J
Jan Kara 已提交
366
	int prealloc_len = 0;
367
	struct udf_inode_info *iinfo;
J
Jan Kara 已提交
368 369 370 371 372

	/* The previous extent is fake and we should not extend by anything
	 * - there's nothing to do... */
	if (!blocks && fake)
		return 0;
373

374
	iinfo = UDF_I(inode);
J
Jan Kara 已提交
375 376 377
	/* Round the last extent up to a multiple of block size */
	if (last_ext->extLength & (sb->s_blocksize - 1)) {
		last_ext->extLength =
378 379 380
			(last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
			(((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
			  sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
381 382
		iinfo->i_lenExtents =
			(iinfo->i_lenExtents + sb->s_blocksize - 1) &
383
			~(sb->s_blocksize - 1);
J
Jan Kara 已提交
384
	}
385

J
Jan Kara 已提交
386
	/* Last extent are just preallocated blocks? */
M
Marcin Slusarz 已提交
387 388
	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
						EXT_NOT_RECORDED_ALLOCATED) {
J
Jan Kara 已提交
389 390 391 392 393
		/* 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 |
394
			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
J
Jan Kara 已提交
395
		last_ext->extLocation.logicalBlockNum = 0;
M
Marcin Slusarz 已提交
396
		last_ext->extLocation.partitionReferenceNum = 0;
J
Jan Kara 已提交
397
	}
398

J
Jan Kara 已提交
399
	/* Can we merge with the previous extent? */
M
Marcin Slusarz 已提交
400 401 402 403 404
	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;
J
Jan Kara 已提交
405 406 407 408 409 410 411
		if (add > blocks)
			add = blocks;
		blocks -= add;
		last_ext->extLength += add << sb->s_blocksize_bits;
	}

	if (fake) {
412
		udf_add_aext(inode, last_pos, &last_ext->extLocation,
413
			     last_ext->extLength, 1);
J
Jan Kara 已提交
414
		count++;
M
Marcin Slusarz 已提交
415
	} else
416
		udf_write_aext(inode, last_pos, &last_ext->extLocation,
M
Marcin Slusarz 已提交
417
				last_ext->extLength, 1);
418

J
Jan Kara 已提交
419 420 421 422 423 424
	/* Managed to do everything necessary? */
	if (!blocks)
		goto out;

	/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
	last_ext->extLocation.logicalBlockNum = 0;
M
Marcin Slusarz 已提交
425
	last_ext->extLocation.partitionReferenceNum = 0;
426
	add = (1 << (30-sb->s_blocksize_bits)) - 1;
M
Marcin Slusarz 已提交
427 428
	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
				(add << sb->s_blocksize_bits);
429

J
Jan Kara 已提交
430 431 432
	/* Create enough extents to cover the whole hole */
	while (blocks > add) {
		blocks -= add;
433
		if (udf_add_aext(inode, last_pos, &last_ext->extLocation,
434
				 last_ext->extLength, 1) == -1)
J
Jan Kara 已提交
435 436 437 438 439
			return -1;
		count++;
	}
	if (blocks) {
		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
440
			(blocks << sb->s_blocksize_bits);
441
		if (udf_add_aext(inode, last_pos, &last_ext->extLocation,
442
				 last_ext->extLength, 1) == -1)
J
Jan Kara 已提交
443 444 445
			return -1;
		count++;
	}
446 447

out:
J
Jan Kara 已提交
448 449
	/* Do we have some preallocated blocks saved? */
	if (prealloc_len) {
450
		if (udf_add_aext(inode, last_pos, &prealloc_loc,
M
Marcin Slusarz 已提交
451
				 prealloc_len, 1) == -1)
J
Jan Kara 已提交
452 453 454 455 456
			return -1;
		last_ext->extLocation = prealloc_loc;
		last_ext->extLength = prealloc_len;
		count++;
	}
457

J
Jan Kara 已提交
458
	/* last_pos should point to the last written extent... */
459
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
460
		last_pos->offset -= sizeof(struct short_ad);
461
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
462
		last_pos->offset -= sizeof(struct long_ad);
J
Jan Kara 已提交
463 464
	else
		return -1;
465

J
Jan Kara 已提交
466 467 468
	return count;
}

469
static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
470
					int *err, sector_t *phys, int *new)
L
Linus Torvalds 已提交
471
{
J
Jan Kara 已提交
472
	static sector_t last_block;
J
Jan Kara 已提交
473
	struct buffer_head *result = NULL;
474
	struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];
J
Jan Kara 已提交
475
	struct extent_position prev_epos, cur_epos, next_epos;
L
Linus Torvalds 已提交
476
	int count = 0, startnum = 0, endnum = 0;
J
Jan Kara 已提交
477
	uint32_t elen = 0, tmpelen;
478
	struct kernel_lb_addr eloc, tmpeloc;
L
Linus Torvalds 已提交
479
	int c = 1;
480 481 482
	loff_t lbcount = 0, b_off = 0;
	uint32_t newblocknum, newblock;
	sector_t offset = 0;
L
Linus Torvalds 已提交
483
	int8_t etype;
484 485
	struct udf_inode_info *iinfo = UDF_I(inode);
	int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
J
Jan Kara 已提交
486
	int lastblock = 0;
L
Linus Torvalds 已提交
487

J
Jan Kara 已提交
488
	prev_epos.offset = udf_file_entry_alloc_offset(inode);
489
	prev_epos.block = iinfo->i_location;
J
Jan Kara 已提交
490 491
	prev_epos.bh = NULL;
	cur_epos = next_epos = prev_epos;
492
	b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
L
Linus Torvalds 已提交
493 494

	/* find the extent which contains the block we are looking for.
495 496 497 498
	   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) {
J
Jan Kara 已提交
499 500
			brelse(prev_epos.bh);
			get_bh(cur_epos.bh);
J
Jan Kara 已提交
501
			prev_epos.bh = cur_epos.bh;
L
Linus Torvalds 已提交
502
		}
503
		if (cur_epos.bh != next_epos.bh) {
J
Jan Kara 已提交
504 505
			brelse(cur_epos.bh);
			get_bh(next_epos.bh);
J
Jan Kara 已提交
506
			cur_epos.bh = next_epos.bh;
L
Linus Torvalds 已提交
507 508 509 510
		}

		lbcount += elen;

J
Jan Kara 已提交
511 512
		prev_epos.block = cur_epos.block;
		cur_epos.block = next_epos.block;
L
Linus Torvalds 已提交
513

J
Jan Kara 已提交
514 515
		prev_epos.offset = cur_epos.offset;
		cur_epos.offset = next_epos.offset;
L
Linus Torvalds 已提交
516

M
Marcin Slusarz 已提交
517 518
		etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1);
		if (etype == -1)
L
Linus Torvalds 已提交
519 520 521 522 523 524 525 526 527
			break;

		c = !c;

		laarr[c].extLength = (etype << 30) | elen;
		laarr[c].extLocation = eloc;

		if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
			pgoal = eloc.logicalBlockNum +
528 529
				((elen + inode->i_sb->s_blocksize - 1) >>
				 inode->i_sb->s_blocksize_bits);
L
Linus Torvalds 已提交
530

531
		count++;
L
Linus Torvalds 已提交
532 533 534 535
	} while (lbcount + elen <= b_off);

	b_off -= lbcount;
	offset = b_off >> inode->i_sb->s_blocksize_bits;
J
Jan Kara 已提交
536 537 538 539 540 541
	/*
	 * 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);
L
Linus Torvalds 已提交
542 543

	/* if the extent is allocated and recorded, return the block
544
	   if the extent is not a multiple of the blocksize, round up */
L
Linus Torvalds 已提交
545

546 547
	if (etype == (EXT_RECORDED_ALLOCATED >> 30)) {
		if (elen & (inode->i_sb->s_blocksize - 1)) {
L
Linus Torvalds 已提交
548
			elen = EXT_RECORDED_ALLOCATED |
549 550
				((elen + inode->i_sb->s_blocksize - 1) &
				 ~(inode->i_sb->s_blocksize - 1));
551
			etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
L
Linus Torvalds 已提交
552
		}
J
Jan Kara 已提交
553 554 555
		brelse(prev_epos.bh);
		brelse(cur_epos.bh);
		brelse(next_epos.bh);
556
		newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
L
Linus Torvalds 已提交
557 558 559 560
		*phys = newblock;
		return NULL;
	}

J
Jan Kara 已提交
561 562
	last_block = block;
	/* Are we beyond EOF? */
563
	if (etype == -1) {
J
Jan Kara 已提交
564 565 566 567 568 569
		int ret;

		if (count) {
			if (c)
				laarr[0] = laarr[1];
			startnum = 1;
570
		} else {
J
Jan Kara 已提交
571
			/* Create a fake extent when there's not one */
M
Marcin Slusarz 已提交
572
			memset(&laarr[0].extLocation, 0x00,
573
				sizeof(struct kernel_lb_addr));
J
Jan Kara 已提交
574
			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
M
Marcin Slusarz 已提交
575 576
			/* Will udf_extend_file() create real extent from
			   a fake one? */
J
Jan Kara 已提交
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
			startnum = (offset > 0);
		}
		/* Create extents for the hole between EOF and offset */
		ret = udf_extend_file(inode, &prev_epos, laarr, offset);
		if (ret == -1) {
			brelse(prev_epos.bh);
			brelse(cur_epos.bh);
			brelse(next_epos.bh);
			/* We don't really know the error here so we just make
			 * something up */
			*err = -ENOSPC;
			return NULL;
		}
		c = 0;
		offset = 0;
		count += ret;
		/* We are not covered by a preallocated extent? */
M
Marcin Slusarz 已提交
594 595
		if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) !=
						EXT_NOT_RECORDED_ALLOCATED) {
J
Jan Kara 已提交
596 597 598 599 600
			/* Is there any real extent? - otherwise we overwrite
			 * the fake one... */
			if (count)
				c = !c;
			laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
601
				inode->i_sb->s_blocksize;
M
Marcin Slusarz 已提交
602
			memset(&laarr[c].extLocation, 0x00,
603
				sizeof(struct kernel_lb_addr));
604 605
			count++;
			endnum++;
J
Jan Kara 已提交
606
		}
607
		endnum = c + 1;
L
Linus Torvalds 已提交
608
		lastblock = 1;
609
	} else {
L
Linus Torvalds 已提交
610 611
		endnum = startnum = ((count > 2) ? 2 : count);

M
Marcin Slusarz 已提交
612 613
		/* if the current extent is in position 0,
		   swap it with the previous */
614
		if (!c && count != 1) {
J
Jan Kara 已提交
615 616 617 618 619
			laarr[2] = laarr[0];
			laarr[0] = laarr[1];
			laarr[1] = laarr[2];
			c = 1;
		}
L
Linus Torvalds 已提交
620

M
Marcin Slusarz 已提交
621 622 623 624
		/* 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) {
625 626 627 628 629
			laarr[c + 1].extLength = (etype << 30) | elen;
			laarr[c + 1].extLocation = eloc;
			count++;
			startnum++;
			endnum++;
M
Marcin Slusarz 已提交
630
		} else
L
Linus Torvalds 已提交
631 632 633 634
			lastblock = 1;
	}

	/* if the current extent is not recorded but allocated, get the
635
	 * block in the extent corresponding to the requested block */
M
Marcin Slusarz 已提交
636
	if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
L
Linus Torvalds 已提交
637
		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
M
Marcin Slusarz 已提交
638
	else { /* otherwise, allocate a new block */
639 640
		if (iinfo->i_next_alloc_block == block)
			goal = iinfo->i_next_alloc_goal;
L
Linus Torvalds 已提交
641

642
		if (!goal) {
M
Marcin Slusarz 已提交
643
			if (!(goal = pgoal)) /* XXX: what was intended here? */
644
				goal = iinfo->i_location.logicalBlockNum + 1;
L
Linus Torvalds 已提交
645 646
		}

M
Marcin Slusarz 已提交
647
		newblocknum = udf_new_block(inode->i_sb, inode,
648
				iinfo->i_location.partitionReferenceNum,
M
Marcin Slusarz 已提交
649 650
				goal, err);
		if (!newblocknum) {
J
Jan Kara 已提交
651
			brelse(prev_epos.bh);
L
Linus Torvalds 已提交
652 653 654
			*err = -ENOSPC;
			return NULL;
		}
655
		iinfo->i_lenExtents += inode->i_sb->s_blocksize;
L
Linus Torvalds 已提交
656 657
	}

M
Marcin Slusarz 已提交
658 659 660 661
	/* 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 */
L
Linus Torvalds 已提交
662 663 664
	udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);

#ifdef UDF_PREALLOCATE
665 666 667 668 669 670
	/* 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);
L
Linus Torvalds 已提交
671 672 673 674 675 676
#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
677 678
	 * of extents is greater than the old number, and deleting extents if
	 * the new number of extents is less than the old number */
J
Jan Kara 已提交
679
	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
L
Linus Torvalds 已提交
680

J
Jan Kara 已提交
681
	brelse(prev_epos.bh);
L
Linus Torvalds 已提交
682

M
Marcin Slusarz 已提交
683
	newblock = udf_get_pblock(inode->i_sb, newblocknum,
684
				iinfo->i_location.partitionReferenceNum, 0);
M
Marcin Slusarz 已提交
685
	if (!newblock)
L
Linus Torvalds 已提交
686 687 688 689
		return NULL;
	*phys = newblock;
	*err = 0;
	*new = 1;
690 691
	iinfo->i_next_alloc_block = block;
	iinfo->i_next_alloc_goal = newblocknum;
L
Linus Torvalds 已提交
692 693 694 695 696 697
	inode->i_ctime = current_fs_time(inode->i_sb);

	if (IS_SYNC(inode))
		udf_sync_inode(inode);
	else
		mark_inode_dirty(inode);
698

L
Linus Torvalds 已提交
699 700 701
	return result;
}

702 703
static void udf_split_extents(struct inode *inode, int *c, int offset,
			      int newblocknum,
704
			      struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
705
			      int *endnum)
L
Linus Torvalds 已提交
706
{
M
Marcin Slusarz 已提交
707 708 709
	unsigned long blocksize = inode->i_sb->s_blocksize;
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;

L
Linus Torvalds 已提交
710
	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
M
Marcin Slusarz 已提交
711 712
	    (laarr[*c].extLength >> 30) ==
				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) {
L
Linus Torvalds 已提交
713 714
		int curr = *c;
		int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
M
Marcin Slusarz 已提交
715
			    blocksize - 1) >> blocksize_bits;
L
Linus Torvalds 已提交
716 717
		int8_t etype = (laarr[curr].extLength >> 30);

M
Marcin Slusarz 已提交
718
		if (blen == 1)
719
			;
M
Marcin Slusarz 已提交
720
		else if (!offset || blen == offset + 1) {
721 722 723 724 725 726 727 728 729
			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)) {
M
Marcin Slusarz 已提交
730
				udf_free_blocks(inode->i_sb, inode,
731
						&laarr[curr].extLocation,
M
Marcin Slusarz 已提交
732 733 734 735
						0, offset);
				laarr[curr].extLength =
					EXT_NOT_RECORDED_NOT_ALLOCATED |
					(offset << blocksize_bits);
L
Linus Torvalds 已提交
736
				laarr[curr].extLocation.logicalBlockNum = 0;
M
Marcin Slusarz 已提交
737 738 739
				laarr[curr].extLocation.
						partitionReferenceNum = 0;
			} else
L
Linus Torvalds 已提交
740
				laarr[curr].extLength = (etype << 30) |
M
Marcin Slusarz 已提交
741
					(offset << blocksize_bits);
742 743 744
			curr++;
			(*c)++;
			(*endnum)++;
L
Linus Torvalds 已提交
745
		}
746

L
Linus Torvalds 已提交
747 748 749
		laarr[curr].extLocation.logicalBlockNum = newblocknum;
		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
			laarr[curr].extLocation.partitionReferenceNum =
750
				UDF_I(inode)->i_location.partitionReferenceNum;
L
Linus Torvalds 已提交
751
		laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
M
Marcin Slusarz 已提交
752
			blocksize;
753
		curr++;
L
Linus Torvalds 已提交
754

755
		if (blen != offset + 1) {
L
Linus Torvalds 已提交
756
			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
M
Marcin Slusarz 已提交
757 758
				laarr[curr].extLocation.logicalBlockNum +=
								offset + 1;
759
			laarr[curr].extLength = (etype << 30) |
M
Marcin Slusarz 已提交
760
				((blen - (offset + 1)) << blocksize_bits);
761 762
			curr++;
			(*endnum)++;
L
Linus Torvalds 已提交
763 764 765 766 767
		}
	}
}

static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
768
				 struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
769
				 int *endnum)
L
Linus Torvalds 已提交
770 771 772
{
	int start, length = 0, currlength = 0, i;

773
	if (*endnum >= (c + 1)) {
L
Linus Torvalds 已提交
774 775 776 777
		if (!lastblock)
			return;
		else
			start = c;
778
	} else {
M
Marcin Slusarz 已提交
779 780
		if ((laarr[c + 1].extLength >> 30) ==
					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
781
			start = c + 1;
M
Marcin Slusarz 已提交
782 783 784 785 786 787
			length = currlength =
				(((laarr[c + 1].extLength &
					UDF_EXTENT_LENGTH_MASK) +
				inode->i_sb->s_blocksize - 1) >>
				inode->i_sb->s_blocksize_bits);
		} else
L
Linus Torvalds 已提交
788 789 790
			start = c;
	}

791 792
	for (i = start + 1; i <= *endnum; i++) {
		if (i == *endnum) {
L
Linus Torvalds 已提交
793 794
			if (lastblock)
				length += UDF_DEFAULT_PREALLOC_BLOCKS;
M
Marcin Slusarz 已提交
795 796 797 798 799 800 801
		} 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
L
Linus Torvalds 已提交
802 803 804
			break;
	}

805
	if (length) {
L
Linus Torvalds 已提交
806
		int next = laarr[start].extLocation.logicalBlockNum +
807
			(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
M
Marcin Slusarz 已提交
808 809
			  inode->i_sb->s_blocksize - 1) >>
			  inode->i_sb->s_blocksize_bits);
L
Linus Torvalds 已提交
810
		int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
M
Marcin Slusarz 已提交
811 812 813 814
				laarr[start].extLocation.partitionReferenceNum,
				next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ?
				length : UDF_DEFAULT_PREALLOC_BLOCKS) -
				currlength);
815
		if (numalloc) 	{
M
Marcin Slusarz 已提交
816
			if (start == (c + 1))
L
Linus Torvalds 已提交
817
				laarr[start].extLength +=
M
Marcin Slusarz 已提交
818 819 820
					(numalloc <<
					 inode->i_sb->s_blocksize_bits);
			else {
821
				memmove(&laarr[c + 2], &laarr[c + 1],
822
					sizeof(struct long_ad) * (*endnum - (c + 1)));
823 824 825
				(*endnum)++;
				laarr[c + 1].extLocation.logicalBlockNum = next;
				laarr[c + 1].extLocation.partitionReferenceNum =
M
Marcin Slusarz 已提交
826 827 828 829 830 831
					laarr[c].extLocation.
							partitionReferenceNum;
				laarr[c + 1].extLength =
					EXT_NOT_RECORDED_ALLOCATED |
					(numalloc <<
					 inode->i_sb->s_blocksize_bits);
832
				start = c + 1;
L
Linus Torvalds 已提交
833 834
			}

835
			for (i = start + 1; numalloc && i < *endnum; i++) {
M
Marcin Slusarz 已提交
836 837 838 839
				int elen = ((laarr[i].extLength &
						UDF_EXTENT_LENGTH_MASK) +
					    inode->i_sb->s_blocksize - 1) >>
					    inode->i_sb->s_blocksize_bits;
L
Linus Torvalds 已提交
840

841
				if (elen > numalloc) {
L
Linus Torvalds 已提交
842
					laarr[i].extLength -=
M
Marcin Slusarz 已提交
843 844
						(numalloc <<
						 inode->i_sb->s_blocksize_bits);
L
Linus Torvalds 已提交
845
					numalloc = 0;
846
				} else {
L
Linus Torvalds 已提交
847
					numalloc -= elen;
848
					if (*endnum > (i + 1))
M
Marcin Slusarz 已提交
849 850
						memmove(&laarr[i],
							&laarr[i + 1],
851
							sizeof(struct long_ad) *
M
Marcin Slusarz 已提交
852
							(*endnum - (i + 1)));
853 854
					i--;
					(*endnum)--;
L
Linus Torvalds 已提交
855 856
				}
			}
857
			UDF_I(inode)->i_lenExtents +=
M
Marcin Slusarz 已提交
858
				numalloc << inode->i_sb->s_blocksize_bits;
L
Linus Torvalds 已提交
859 860 861 862 863
		}
	}
}

static void udf_merge_extents(struct inode *inode,
864
			      struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
865
			      int *endnum)
L
Linus Torvalds 已提交
866 867
{
	int i;
M
Marcin Slusarz 已提交
868 869
	unsigned long blocksize = inode->i_sb->s_blocksize;
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
L
Linus Torvalds 已提交
870

871
	for (i = 0; i < (*endnum - 1); i++) {
872 873
		struct kernel_long_ad *li /*l[i]*/ = &laarr[i];
		struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1];
M
Marcin Slusarz 已提交
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906

		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],
907
						sizeof(struct long_ad) *
M
Marcin Slusarz 已提交
908 909 910
						(*endnum - (i + 2)));
				i--;
				(*endnum)--;
L
Linus Torvalds 已提交
911
			}
M
Marcin Slusarz 已提交
912 913 914 915
		} else if (((li->extLength >> 30) ==
				(EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
			   ((lip1->extLength >> 30) ==
				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) {
916
			udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0,
M
Marcin Slusarz 已提交
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
					((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;
935
			} else {
M
Marcin Slusarz 已提交
936 937 938 939
				li->extLength = lip1->extLength +
					(((li->extLength &
						UDF_EXTENT_LENGTH_MASK) +
					  blocksize - 1) & ~(blocksize - 1));
940 941
				if (*endnum > (i + 2))
					memmove(&laarr[i + 1], &laarr[i + 2],
942
						sizeof(struct long_ad) *
M
Marcin Slusarz 已提交
943
						(*endnum - (i + 2)));
944 945
				i--;
				(*endnum)--;
L
Linus Torvalds 已提交
946
			}
M
Marcin Slusarz 已提交
947 948 949
		} else if ((li->extLength >> 30) ==
					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
			udf_free_blocks(inode->i_sb, inode,
950
					&li->extLocation, 0,
M
Marcin Slusarz 已提交
951 952 953 954 955 956 957 958
					((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;
L
Linus Torvalds 已提交
959 960 961 962 963
		}
	}
}

static void udf_update_extents(struct inode *inode,
964
			       struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
965 966
			       int startnum, int endnum,
			       struct extent_position *epos)
L
Linus Torvalds 已提交
967 968
{
	int start = 0, i;
969
	struct kernel_lb_addr tmploc;
L
Linus Torvalds 已提交
970 971
	uint32_t tmplen;

972 973
	if (startnum > endnum) {
		for (i = 0; i < (startnum - endnum); i++)
J
Jan Kara 已提交
974
			udf_delete_aext(inode, *epos, laarr[i].extLocation,
975 976 977
					laarr[i].extLength);
	} else if (startnum < endnum) {
		for (i = 0; i < (endnum - startnum); i++) {
J
Jan Kara 已提交
978
			udf_insert_aext(inode, *epos, laarr[i].extLocation,
979
					laarr[i].extLength);
J
Jan Kara 已提交
980
			udf_next_aext(inode, epos, &laarr[i].extLocation,
981 982
				      &laarr[i].extLength, 1);
			start++;
L
Linus Torvalds 已提交
983 984 985
		}
	}

986
	for (i = start; i < endnum; i++) {
J
Jan Kara 已提交
987
		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
988
		udf_write_aext(inode, epos, &laarr[i].extLocation,
989
			       laarr[i].extLength, 1);
L
Linus Torvalds 已提交
990 991 992
	}
}

993 994
struct buffer_head *udf_bread(struct inode *inode, int block,
			      int create, int *err)
L
Linus Torvalds 已提交
995
{
996
	struct buffer_head *bh = NULL;
L
Linus Torvalds 已提交
997 998 999 1000 1001 1002 1003

	bh = udf_getblk(inode, block, create, err);
	if (!bh)
		return NULL;

	if (buffer_uptodate(bh))
		return bh;
1004

L
Linus Torvalds 已提交
1005
	ll_rw_block(READ, 1, &bh);
1006

L
Linus Torvalds 已提交
1007 1008 1009
	wait_on_buffer(bh);
	if (buffer_uptodate(bh))
		return bh;
1010

L
Linus Torvalds 已提交
1011 1012 1013 1014 1015
	brelse(bh);
	*err = -EIO;
	return NULL;
}

1016
void udf_truncate(struct inode *inode)
L
Linus Torvalds 已提交
1017 1018 1019
{
	int offset;
	int err;
1020
	struct udf_inode_info *iinfo;
L
Linus Torvalds 已提交
1021 1022

	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1023
	      S_ISLNK(inode->i_mode)))
L
Linus Torvalds 已提交
1024 1025 1026 1027 1028
		return;
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
		return;

	lock_kernel();
1029 1030
	iinfo = UDF_I(inode);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
M
Marcin Slusarz 已提交
1031 1032 1033
		if (inode->i_sb->s_blocksize <
				(udf_file_entry_alloc_offset(inode) +
				 inode->i_size)) {
L
Linus Torvalds 已提交
1034
			udf_expand_file_adinicb(inode, inode->i_size, &err);
1035 1036
			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
				inode->i_size = iinfo->i_lenAlloc;
L
Linus Torvalds 已提交
1037 1038
				unlock_kernel();
				return;
M
Marcin Slusarz 已提交
1039
			} else
L
Linus Torvalds 已提交
1040
				udf_truncate_extents(inode);
1041
		} else {
L
Linus Torvalds 已提交
1042
			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
1043
			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset,
1044
				0x00, inode->i_sb->s_blocksize -
M
Marcin Slusarz 已提交
1045
				offset - udf_file_entry_alloc_offset(inode));
1046
			iinfo->i_lenAlloc = inode->i_size;
L
Linus Torvalds 已提交
1047
		}
1048
	} else {
M
Marcin Slusarz 已提交
1049 1050
		block_truncate_page(inode->i_mapping, inode->i_size,
				    udf_get_block);
L
Linus Torvalds 已提交
1051
		udf_truncate_extents(inode);
1052
	}
L
Linus Torvalds 已提交
1053 1054 1055

	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
	if (IS_SYNC(inode))
1056
		udf_sync_inode(inode);
L
Linus Torvalds 已提交
1057 1058 1059 1060 1061
	else
		mark_inode_dirty(inode);
	unlock_kernel();
}

1062
static void __udf_read_inode(struct inode *inode)
L
Linus Torvalds 已提交
1063 1064 1065 1066
{
	struct buffer_head *bh = NULL;
	struct fileEntry *fe;
	uint16_t ident;
1067
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080

	/*
	 * 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;
	 */
1081
	bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident);
1082
	if (!bh) {
L
Linus Torvalds 已提交
1083
		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
1084
		       inode->i_ino);
L
Linus Torvalds 已提交
1085 1086 1087 1088 1089
		make_bad_inode(inode);
		return;
	}

	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
1090
	    ident != TAG_IDENT_USE) {
M
Marcin Slusarz 已提交
1091 1092
		printk(KERN_ERR "udf: udf_read_inode(ino %ld) "
				"failed ident=%d\n", inode->i_ino, ident);
J
Jan Kara 已提交
1093
		brelse(bh);
L
Linus Torvalds 已提交
1094 1095 1096 1097 1098 1099
		make_bad_inode(inode);
		return;
	}

	fe = (struct fileEntry *)bh->b_data;

1100
	if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
1101
		struct buffer_head *ibh;
L
Linus Torvalds 已提交
1102

1103
		ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1,
M
Marcin Slusarz 已提交
1104
					&ident);
1105 1106
		if (ident == TAG_IDENT_IE && ibh) {
			struct buffer_head *nbh = NULL;
1107
			struct kernel_lb_addr loc;
1108 1109 1110 1111 1112 1113
			struct indirectEntry *ie;

			ie = (struct indirectEntry *)ibh->b_data;
			loc = lelb_to_cpu(ie->indirectICB.extLocation);

			if (ie->indirectICB.extLength &&
1114
				(nbh = udf_read_ptagged(inode->i_sb, &loc, 0,
1115 1116 1117 1118 1119
							&ident))) {
				if (ident == TAG_IDENT_FE ||
					ident == TAG_IDENT_EFE) {
					memcpy(&iinfo->i_location,
						&loc,
1120
						sizeof(struct kernel_lb_addr));
1121
					brelse(bh);
J
Jan Kara 已提交
1122
					brelse(ibh);
1123 1124 1125
					brelse(nbh);
					__udf_read_inode(inode);
					return;
1126
				}
1127
				brelse(nbh);
L
Linus Torvalds 已提交
1128
			}
1129
		}
1130
		brelse(ibh);
1131
	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
L
Linus Torvalds 已提交
1132
		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
1133
		       le16_to_cpu(fe->icbTag.strategyType));
J
Jan Kara 已提交
1134
		brelse(bh);
L
Linus Torvalds 已提交
1135 1136 1137 1138
		make_bad_inode(inode);
		return;
	}
	udf_fill_inode(inode, bh);
J
Jan Kara 已提交
1139

J
Jan Kara 已提交
1140
	brelse(bh);
L
Linus Torvalds 已提交
1141 1142 1143 1144 1145 1146 1147
}

static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
{
	struct fileEntry *fe;
	struct extendedFileEntry *efe;
	int offset;
M
Marcin Slusarz 已提交
1148
	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
1149
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1150 1151 1152 1153

	fe = (struct fileEntry *)bh->b_data;
	efe = (struct extendedFileEntry *)bh->b_data;

1154
	if (fe->icbTag.strategyType == cpu_to_le16(4))
1155
		iinfo->i_strat4096 = 0;
1156
	else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */
1157
		iinfo->i_strat4096 = 1;
L
Linus Torvalds 已提交
1158

1159
	iinfo->i_alloc_type = le16_to_cpu(fe->icbTag.flags) &
M
Marcin Slusarz 已提交
1160
							ICBTAG_FLAG_AD_MASK;
1161 1162 1163 1164 1165 1166
	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;
1167
	if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
1168 1169
		iinfo->i_efe = 1;
		iinfo->i_use = 0;
M
Marcin Slusarz 已提交
1170 1171
		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
					sizeof(struct extendedFileEntry))) {
1172 1173 1174
			make_bad_inode(inode);
			return;
		}
1175
		memcpy(iinfo->i_ext.i_data,
M
Marcin Slusarz 已提交
1176 1177 1178
		       bh->b_data + sizeof(struct extendedFileEntry),
		       inode->i_sb->s_blocksize -
					sizeof(struct extendedFileEntry));
1179
	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
1180 1181
		iinfo->i_efe = 0;
		iinfo->i_use = 0;
M
Marcin Slusarz 已提交
1182 1183
		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
						sizeof(struct fileEntry))) {
1184 1185 1186
			make_bad_inode(inode);
			return;
		}
1187
		memcpy(iinfo->i_ext.i_data,
1188
		       bh->b_data + sizeof(struct fileEntry),
1189
		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
1190
	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
1191 1192 1193
		iinfo->i_efe = 0;
		iinfo->i_use = 1;
		iinfo->i_lenAlloc = le32_to_cpu(
M
Marcin Slusarz 已提交
1194 1195 1196 1197
				((struct unallocSpaceEntry *)bh->b_data)->
				 lengthAllocDescs);
		if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
					sizeof(struct unallocSpaceEntry))) {
1198 1199 1200
			make_bad_inode(inode);
			return;
		}
1201
		memcpy(iinfo->i_ext.i_data,
M
Marcin Slusarz 已提交
1202 1203 1204
		       bh->b_data + sizeof(struct unallocSpaceEntry),
		       inode->i_sb->s_blocksize -
					sizeof(struct unallocSpaceEntry));
L
Linus Torvalds 已提交
1205 1206 1207 1208
		return;
	}

	inode->i_uid = le32_to_cpu(fe->uid);
1209 1210 1211
	if (inode->i_uid == -1 ||
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))
1212
		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
L
Linus Torvalds 已提交
1213 1214

	inode->i_gid = le32_to_cpu(fe->gid);
1215 1216 1217
	if (inode->i_gid == -1 ||
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) ||
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
1218
		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
L
Linus Torvalds 已提交
1219 1220 1221 1222

	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
	if (!inode->i_nlink)
		inode->i_nlink = 1;
1223

L
Linus Torvalds 已提交
1224
	inode->i_size = le64_to_cpu(fe->informationLength);
1225
	iinfo->i_lenExtents = inode->i_size;
L
Linus Torvalds 已提交
1226

1227
	if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&
1228
			sbi->s_fmode != UDF_INVALID_MODE)
1229 1230
		inode->i_mode = sbi->s_fmode;
	else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY &&
1231
			sbi->s_dmode != UDF_INVALID_MODE)
1232 1233 1234 1235
		inode->i_mode = sbi->s_dmode;
	else
		inode->i_mode = udf_convert_permissions(fe);
	inode->i_mode &= ~sbi->s_umask;
L
Linus Torvalds 已提交
1236

1237
	if (iinfo->i_efe == 0) {
L
Linus Torvalds 已提交
1238
		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
1239
			(inode->i_sb->s_blocksize_bits - 9);
L
Linus Torvalds 已提交
1240

1241
		if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
1242 1243
			inode->i_atime = sbi->s_record_time;

1244 1245
		if (!udf_disk_stamp_to_time(&inode->i_mtime,
					    fe->modificationTime))
1246 1247
			inode->i_mtime = sbi->s_record_time;

1248
		if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
1249
			inode->i_ctime = sbi->s_record_time;
L
Linus Torvalds 已提交
1250

1251 1252 1253 1254
		iinfo->i_unique = le64_to_cpu(fe->uniqueID);
		iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
		iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs);
		offset = sizeof(struct fileEntry) + iinfo->i_lenEAttr;
1255
	} else {
1256
		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
1257
		    (inode->i_sb->s_blocksize_bits - 9);
L
Linus Torvalds 已提交
1258

1259
		if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
1260 1261
			inode->i_atime = sbi->s_record_time;

1262 1263
		if (!udf_disk_stamp_to_time(&inode->i_mtime,
					    efe->modificationTime))
1264 1265
			inode->i_mtime = sbi->s_record_time;

1266
		if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
1267 1268
			iinfo->i_crtime = sbi->s_record_time;

1269
		if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
1270
			inode->i_ctime = sbi->s_record_time;
L
Linus Torvalds 已提交
1271

1272 1273 1274
		iinfo->i_unique = le64_to_cpu(efe->uniqueID);
		iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
		iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
M
Marcin Slusarz 已提交
1275
		offset = sizeof(struct extendedFileEntry) +
1276
							iinfo->i_lenEAttr;
L
Linus Torvalds 已提交
1277 1278
	}

1279 1280
	switch (fe->icbTag.fileType) {
	case ICBTAG_FILE_TYPE_DIRECTORY:
1281 1282 1283 1284 1285
		inode->i_op = &udf_dir_inode_operations;
		inode->i_fop = &udf_dir_operations;
		inode->i_mode |= S_IFDIR;
		inc_nlink(inode);
		break;
1286 1287 1288
	case ICBTAG_FILE_TYPE_REALTIME:
	case ICBTAG_FILE_TYPE_REGULAR:
	case ICBTAG_FILE_TYPE_UNDEF:
J
Jan Kara 已提交
1289
	case ICBTAG_FILE_TYPE_VAT20:
1290
		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1291 1292 1293 1294 1295 1296 1297
			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;
1298
	case ICBTAG_FILE_TYPE_BLOCK:
1299 1300
		inode->i_mode |= S_IFBLK;
		break;
1301
	case ICBTAG_FILE_TYPE_CHAR:
1302 1303
		inode->i_mode |= S_IFCHR;
		break;
1304
	case ICBTAG_FILE_TYPE_FIFO:
1305 1306
		init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
		break;
1307
	case ICBTAG_FILE_TYPE_SOCKET:
1308 1309
		init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
		break;
1310
	case ICBTAG_FILE_TYPE_SYMLINK:
1311
		inode->i_data.a_ops = &udf_symlink_aops;
1312
		inode->i_op = &udf_symlink_inode_operations;
1313 1314
		inode->i_mode = S_IFLNK | S_IRWXUGO;
		break;
1315 1316 1317 1318 1319 1320 1321 1322 1323
	case ICBTAG_FILE_TYPE_MAIN:
		udf_debug("METADATA FILE-----\n");
		break;
	case ICBTAG_FILE_TYPE_MIRROR:
		udf_debug("METADATA MIRROR FILE-----\n");
		break;
	case ICBTAG_FILE_TYPE_BITMAP:
		udf_debug("METADATA BITMAP FILE-----\n");
		break;
1324
	default:
M
Marcin Slusarz 已提交
1325 1326 1327
		printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
				"file type=%d\n", inode->i_ino,
				fe->icbTag.fileType);
1328 1329
		make_bad_inode(inode);
		return;
L
Linus Torvalds 已提交
1330
	}
1331
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
M
Marcin Slusarz 已提交
1332 1333
		struct deviceSpec *dsea =
			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
1334 1335
		if (dsea) {
			init_special_inode(inode, inode->i_mode,
M
Marcin Slusarz 已提交
1336 1337
				MKDEV(le32_to_cpu(dsea->majorDeviceIdent),
				      le32_to_cpu(dsea->minorDeviceIdent)));
L
Linus Torvalds 已提交
1338
			/* Developer ID ??? */
M
Marcin Slusarz 已提交
1339
		} else
L
Linus Torvalds 已提交
1340 1341 1342 1343
			make_bad_inode(inode);
	}
}

1344 1345
static int udf_alloc_i_data(struct inode *inode, size_t size)
{
1346 1347
	struct udf_inode_info *iinfo = UDF_I(inode);
	iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL);
1348

1349
	if (!iinfo->i_ext.i_data) {
M
Marcin Slusarz 已提交
1350 1351
		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) "
				"no free memory\n", inode->i_ino);
1352 1353 1354 1355 1356 1357
		return -ENOMEM;
	}

	return 0;
}

1358
static mode_t udf_convert_permissions(struct fileEntry *fe)
L
Linus Torvalds 已提交
1359 1360 1361 1362 1363 1364 1365 1366
{
	mode_t mode;
	uint32_t permissions;
	uint32_t flags;

	permissions = le32_to_cpu(fe->permissions);
	flags = le16_to_cpu(fe->icbTag.flags);

M
Marcin Slusarz 已提交
1367 1368 1369 1370 1371 1372
	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);
L
Linus Torvalds 已提交
1373 1374 1375 1376

	return mode;
}

1377
int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
L
Linus Torvalds 已提交
1378 1379
{
	int ret;
1380

L
Linus Torvalds 已提交
1381
	lock_kernel();
1382
	ret = udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
L
Linus Torvalds 已提交
1383
	unlock_kernel();
1384

L
Linus Torvalds 已提交
1385 1386 1387
	return ret;
}

1388
int udf_sync_inode(struct inode *inode)
L
Linus Torvalds 已提交
1389 1390 1391 1392
{
	return udf_update_inode(inode, 1);
}

1393
static int udf_update_inode(struct inode *inode, int do_sync)
L
Linus Torvalds 已提交
1394 1395 1396 1397 1398 1399 1400 1401
{
	struct buffer_head *bh = NULL;
	struct fileEntry *fe;
	struct extendedFileEntry *efe;
	uint32_t udfperms;
	uint16_t icbflags;
	uint16_t crclen;
	int err = 0;
M
Marcin Slusarz 已提交
1402
	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
M
Marcin Slusarz 已提交
1403
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
1404
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1405

1406 1407
	bh = udf_tgetblk(inode->i_sb,
			udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
1408
	if (!bh) {
1409 1410
		udf_debug("getblk failure\n");
		return -ENOMEM;
L
Linus Torvalds 已提交
1411 1412
	}

1413 1414
	lock_buffer(bh);
	memset(bh->b_data, 0, inode->i_sb->s_blocksize);
L
Linus Torvalds 已提交
1415 1416 1417
	fe = (struct fileEntry *)bh->b_data;
	efe = (struct extendedFileEntry *)bh->b_data;

1418
	if (iinfo->i_use) {
L
Linus Torvalds 已提交
1419
		struct unallocSpaceEntry *use =
1420
			(struct unallocSpaceEntry *)bh->b_data;
L
Linus Torvalds 已提交
1421

1422
		use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
M
Marcin Slusarz 已提交
1423
		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
1424
		       iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
M
Marcin Slusarz 已提交
1425
					sizeof(struct unallocSpaceEntry));
1426 1427 1428
		use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
		use->descTag.tagLocation =
				cpu_to_le32(iinfo->i_location.logicalBlockNum);
M
Marcin Slusarz 已提交
1429
		crclen = sizeof(struct unallocSpaceEntry) +
1430
				iinfo->i_lenAlloc - sizeof(struct tag);
L
Linus Torvalds 已提交
1431
		use->descTag.descCRCLength = cpu_to_le16(crclen);
1432
		use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
1433
							   sizeof(struct tag),
1434
							   crclen));
1435
		use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
L
Linus Torvalds 已提交
1436

1437
		goto out;
L
Linus Torvalds 已提交
1438 1439
	}

1440 1441
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
		fe->uid = cpu_to_le32(-1);
1442 1443
	else
		fe->uid = cpu_to_le32(inode->i_uid);
L
Linus Torvalds 已提交
1444

1445 1446
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
		fe->gid = cpu_to_le32(-1);
1447 1448
	else
		fe->gid = cpu_to_le32(inode->i_gid);
L
Linus Torvalds 已提交
1449

M
Marcin Slusarz 已提交
1450 1451 1452
	udfperms = ((inode->i_mode & S_IRWXO)) |
		   ((inode->i_mode & S_IRWXG) << 2) |
		   ((inode->i_mode & S_IRWXU) << 4);
L
Linus Torvalds 已提交
1453

M
Marcin Slusarz 已提交
1454 1455 1456 1457
	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));
L
Linus Torvalds 已提交
1458 1459 1460 1461 1462 1463 1464 1465 1466
	fe->permissions = cpu_to_le32(udfperms);

	if (S_ISDIR(inode->i_mode))
		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);

1467
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
1468
		struct regid *eid;
1469 1470
		struct deviceSpec *dsea =
			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
1471
		if (!dsea) {
L
Linus Torvalds 已提交
1472
			dsea = (struct deviceSpec *)
1473 1474
				udf_add_extendedattr(inode,
						     sizeof(struct deviceSpec) +
1475
						     sizeof(struct regid), 12, 0x3);
L
Linus Torvalds 已提交
1476 1477
			dsea->attrType = cpu_to_le32(12);
			dsea->attrSubtype = 1;
M
Marcin Slusarz 已提交
1478 1479
			dsea->attrLength = cpu_to_le32(
						sizeof(struct deviceSpec) +
1480 1481
						sizeof(struct regid));
			dsea->impUseLength = cpu_to_le32(sizeof(struct regid));
L
Linus Torvalds 已提交
1482
		}
1483 1484
		eid = (struct regid *)dsea->impUse;
		memset(eid, 0, sizeof(struct regid));
L
Linus Torvalds 已提交
1485 1486 1487 1488 1489 1490 1491
		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));
	}

1492
	if (iinfo->i_efe == 0) {
1493
		memcpy(bh->b_data + sizeof(struct fileEntry),
1494
		       iinfo->i_ext.i_data,
1495
		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
1496
		fe->logicalBlocksRecorded = cpu_to_le64(
M
Marcin Slusarz 已提交
1497 1498
			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
			(blocksize_bits - 9));
L
Linus Torvalds 已提交
1499

1500 1501 1502
		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);
1503
		memset(&(fe->impIdent), 0, sizeof(struct regid));
L
Linus Torvalds 已提交
1504 1505 1506
		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1507 1508 1509
		fe->uniqueID = cpu_to_le64(iinfo->i_unique);
		fe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
		fe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
L
Linus Torvalds 已提交
1510 1511
		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
		crclen = sizeof(struct fileEntry);
1512
	} else {
M
Marcin Slusarz 已提交
1513
		memcpy(bh->b_data + sizeof(struct extendedFileEntry),
1514
		       iinfo->i_ext.i_data,
M
Marcin Slusarz 已提交
1515 1516
		       inode->i_sb->s_blocksize -
					sizeof(struct extendedFileEntry));
L
Linus Torvalds 已提交
1517
		efe->objectSize = cpu_to_le64(inode->i_size);
1518
		efe->logicalBlocksRecorded = cpu_to_le64(
M
Marcin Slusarz 已提交
1519 1520
			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
			(blocksize_bits - 9));
L
Linus Torvalds 已提交
1521

1522 1523 1524 1525
		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;
M
Marcin Slusarz 已提交
1526

1527 1528 1529 1530
		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;
M
Marcin Slusarz 已提交
1531

1532 1533 1534 1535
		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;
L
Linus Torvalds 已提交
1536

1537 1538 1539 1540
		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);
L
Linus Torvalds 已提交
1541

1542
		memset(&(efe->impIdent), 0, sizeof(struct regid));
L
Linus Torvalds 已提交
1543 1544 1545
		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1546 1547 1548
		efe->uniqueID = cpu_to_le64(iinfo->i_unique);
		efe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
		efe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
L
Linus Torvalds 已提交
1549 1550 1551
		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
		crclen = sizeof(struct extendedFileEntry);
	}
1552
	if (iinfo->i_strat4096) {
L
Linus Torvalds 已提交
1553 1554 1555
		fe->icbTag.strategyType = cpu_to_le16(4096);
		fe->icbTag.strategyParameter = cpu_to_le16(1);
		fe->icbTag.numEntries = cpu_to_le16(2);
1556
	} else {
L
Linus Torvalds 已提交
1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
		fe->icbTag.strategyType = cpu_to_le16(4);
		fe->icbTag.numEntries = cpu_to_le16(1);
	}

	if (S_ISDIR(inode->i_mode))
		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;

1576
	icbflags =	iinfo->i_alloc_type |
1577 1578 1579 1580 1581 1582
			((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));
L
Linus Torvalds 已提交
1583 1584

	fe->icbTag.flags = cpu_to_le16(icbflags);
M
Marcin Slusarz 已提交
1585
	if (sbi->s_udfrev >= 0x0200)
L
Linus Torvalds 已提交
1586 1587 1588
		fe->descTag.descVersion = cpu_to_le16(3);
	else
		fe->descTag.descVersion = cpu_to_le16(2);
M
Marcin Slusarz 已提交
1589
	fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
M
Marcin Slusarz 已提交
1590
	fe->descTag.tagLocation = cpu_to_le32(
1591
					iinfo->i_location.logicalBlockNum);
1592
	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
L
Linus Torvalds 已提交
1593
	fe->descTag.descCRCLength = cpu_to_le16(crclen);
1594
	fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
1595
						  crclen));
1596
	fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
L
Linus Torvalds 已提交
1597

1598
out:
1599
	set_buffer_uptodate(bh);
1600 1601
	unlock_buffer(bh);

L
Linus Torvalds 已提交
1602 1603
	/* write the data blocks */
	mark_buffer_dirty(bh);
1604
	if (do_sync) {
L
Linus Torvalds 已提交
1605
		sync_dirty_buffer(bh);
1606
		if (buffer_write_io_error(bh)) {
M
Marcin Slusarz 已提交
1607 1608 1609
			printk(KERN_WARNING "IO error syncing udf inode "
				"[%s:%08lx]\n", inode->i_sb->s_id,
				inode->i_ino);
L
Linus Torvalds 已提交
1610 1611 1612
			err = -EIO;
		}
	}
J
Jan Kara 已提交
1613
	brelse(bh);
1614

L
Linus Torvalds 已提交
1615 1616 1617
	return err;
}

1618
struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
L
Linus Torvalds 已提交
1619 1620 1621 1622 1623 1624 1625 1626
{
	unsigned long block = udf_get_lb_pblock(sb, ino, 0);
	struct inode *inode = iget_locked(sb, block);

	if (!inode)
		return NULL;

	if (inode->i_state & I_NEW) {
1627
		memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
L
Linus Torvalds 已提交
1628 1629 1630 1631 1632 1633 1634
		__udf_read_inode(inode);
		unlock_new_inode(inode);
	}

	if (is_bad_inode(inode))
		goto out_iput;

1635 1636
	if (ino->logicalBlockNum >= UDF_SB(sb)->
			s_partmaps[ino->partitionReferenceNum].s_partition_len) {
L
Linus Torvalds 已提交
1637
		udf_debug("block=%d, partition=%d out of range\n",
1638
			  ino->logicalBlockNum, ino->partitionReferenceNum);
L
Linus Torvalds 已提交
1639 1640 1641 1642 1643 1644
		make_bad_inode(inode);
		goto out_iput;
	}

	return inode;

1645
 out_iput:
L
Linus Torvalds 已提交
1646 1647 1648 1649
	iput(inode);
	return NULL;
}

M
Marcin Slusarz 已提交
1650
int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
1651
		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
L
Linus Torvalds 已提交
1652 1653
{
	int adsize;
1654 1655
	struct short_ad *sad = NULL;
	struct long_ad *lad = NULL;
L
Linus Torvalds 已提交
1656 1657 1658
	struct allocExtDesc *aed;
	int8_t etype;
	uint8_t *ptr;
1659
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1660

J
Jan Kara 已提交
1661
	if (!epos->bh)
1662
		ptr = iinfo->i_ext.i_data + epos->offset -
M
Marcin Slusarz 已提交
1663
			udf_file_entry_alloc_offset(inode) +
1664
			iinfo->i_lenEAttr;
L
Linus Torvalds 已提交
1665
	else
J
Jan Kara 已提交
1666
		ptr = epos->bh->b_data + epos->offset;
L
Linus Torvalds 已提交
1667

1668
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
1669
		adsize = sizeof(struct short_ad);
1670
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
1671
		adsize = sizeof(struct long_ad);
L
Linus Torvalds 已提交
1672 1673 1674
	else
		return -1;

1675
	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
A
Al Viro 已提交
1676
		unsigned char *sptr, *dptr;
L
Linus Torvalds 已提交
1677 1678
		struct buffer_head *nbh;
		int err, loffset;
1679
		struct kernel_lb_addr obloc = epos->block;
L
Linus Torvalds 已提交
1680

M
Marcin Slusarz 已提交
1681 1682 1683 1684
		epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
						obloc.partitionReferenceNum,
						obloc.logicalBlockNum, &err);
		if (!epos->block.logicalBlockNum)
L
Linus Torvalds 已提交
1685
			return -1;
M
Marcin Slusarz 已提交
1686
		nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
1687
								 &epos->block,
M
Marcin Slusarz 已提交
1688 1689
								 0));
		if (!nbh)
L
Linus Torvalds 已提交
1690 1691 1692 1693 1694 1695 1696 1697 1698
			return -1;
		lock_buffer(nbh);
		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
		set_buffer_uptodate(nbh);
		unlock_buffer(nbh);
		mark_buffer_dirty_inode(nbh, inode);

		aed = (struct allocExtDesc *)(nbh->b_data);
		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
M
Marcin Slusarz 已提交
1699 1700
			aed->previousAllocExtLocation =
					cpu_to_le32(obloc.logicalBlockNum);
1701
		if (epos->offset + adsize > inode->i_sb->s_blocksize) {
J
Jan Kara 已提交
1702
			loffset = epos->offset;
L
Linus Torvalds 已提交
1703 1704 1705 1706
			aed->lengthAllocDescs = cpu_to_le32(adsize);
			sptr = ptr - adsize;
			dptr = nbh->b_data + sizeof(struct allocExtDesc);
			memcpy(dptr, sptr, adsize);
J
Jan Kara 已提交
1707
			epos->offset = sizeof(struct allocExtDesc) + adsize;
1708
		} else {
J
Jan Kara 已提交
1709
			loffset = epos->offset + adsize;
L
Linus Torvalds 已提交
1710 1711
			aed->lengthAllocDescs = cpu_to_le32(0);
			sptr = ptr;
J
Jan Kara 已提交
1712
			epos->offset = sizeof(struct allocExtDesc);
L
Linus Torvalds 已提交
1713

1714
			if (epos->bh) {
J
Jan Kara 已提交
1715
				aed = (struct allocExtDesc *)epos->bh->b_data;
1716
				le32_add_cpu(&aed->lengthAllocDescs, adsize);
1717
			} else {
1718
				iinfo->i_lenAlloc += adsize;
L
Linus Torvalds 已提交
1719 1720 1721
				mark_inode_dirty(inode);
			}
		}
M
Marcin Slusarz 已提交
1722
		if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200)
L
Linus Torvalds 已提交
1723
			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
1724
				    epos->block.logicalBlockNum, sizeof(struct tag));
L
Linus Torvalds 已提交
1725 1726
		else
			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
1727
				    epos->block.logicalBlockNum, sizeof(struct tag));
1728
		switch (iinfo->i_alloc_type) {
1729
		case ICBTAG_FLAG_AD_SHORT:
1730
			sad = (struct short_ad *)sptr;
1731 1732
			sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
						     inode->i_sb->s_blocksize);
M
Marcin Slusarz 已提交
1733 1734
			sad->extPosition =
				cpu_to_le32(epos->block.logicalBlockNum);
1735
			break;
1736
		case ICBTAG_FLAG_AD_LONG:
1737
			lad = (struct long_ad *)sptr;
1738 1739 1740 1741 1742
			lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
						     inode->i_sb->s_blocksize);
			lad->extLocation = cpu_to_lelb(epos->block);
			memset(lad->impUse, 0x00, sizeof(lad->impUse));
			break;
L
Linus Torvalds 已提交
1743
		}
1744
		if (epos->bh) {
1745
			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
M
Marcin Slusarz 已提交
1746
			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
J
Jan Kara 已提交
1747
				udf_update_tag(epos->bh->b_data, loffset);
L
Linus Torvalds 已提交
1748
			else
M
Marcin Slusarz 已提交
1749 1750
				udf_update_tag(epos->bh->b_data,
						sizeof(struct allocExtDesc));
J
Jan Kara 已提交
1751
			mark_buffer_dirty_inode(epos->bh, inode);
J
Jan Kara 已提交
1752
			brelse(epos->bh);
1753
		} else {
L
Linus Torvalds 已提交
1754
			mark_inode_dirty(inode);
1755
		}
J
Jan Kara 已提交
1756
		epos->bh = nbh;
L
Linus Torvalds 已提交
1757 1758
	}

J
Jan Kara 已提交
1759
	etype = udf_write_aext(inode, epos, eloc, elen, inc);
L
Linus Torvalds 已提交
1760

1761
	if (!epos->bh) {
1762
		iinfo->i_lenAlloc += adsize;
L
Linus Torvalds 已提交
1763
		mark_inode_dirty(inode);
1764
	} else {
J
Jan Kara 已提交
1765
		aed = (struct allocExtDesc *)epos->bh->b_data;
1766
		le32_add_cpu(&aed->lengthAllocDescs, adsize);
M
Marcin Slusarz 已提交
1767 1768 1769 1770
		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));
L
Linus Torvalds 已提交
1771
		else
M
Marcin Slusarz 已提交
1772 1773
			udf_update_tag(epos->bh->b_data,
					sizeof(struct allocExtDesc));
J
Jan Kara 已提交
1774
		mark_buffer_dirty_inode(epos->bh, inode);
L
Linus Torvalds 已提交
1775 1776 1777 1778 1779
	}

	return etype;
}

M
Marcin Slusarz 已提交
1780
int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
1781
		      struct kernel_lb_addr *eloc, uint32_t elen, int inc)
L
Linus Torvalds 已提交
1782 1783 1784
{
	int adsize;
	uint8_t *ptr;
1785 1786
	struct short_ad *sad;
	struct long_ad *lad;
1787
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1788

J
Jan Kara 已提交
1789
	if (!epos->bh)
1790
		ptr = iinfo->i_ext.i_data + epos->offset -
M
Marcin Slusarz 已提交
1791
			udf_file_entry_alloc_offset(inode) +
1792
			iinfo->i_lenEAttr;
L
Linus Torvalds 已提交
1793
	else
J
Jan Kara 已提交
1794
		ptr = epos->bh->b_data + epos->offset;
L
Linus Torvalds 已提交
1795

1796
	switch (iinfo->i_alloc_type) {
1797
	case ICBTAG_FLAG_AD_SHORT:
1798
		sad = (struct short_ad *)ptr;
1799
		sad->extLength = cpu_to_le32(elen);
1800
		sad->extPosition = cpu_to_le32(eloc->logicalBlockNum);
1801
		adsize = sizeof(struct short_ad);
1802
		break;
1803
	case ICBTAG_FLAG_AD_LONG:
1804
		lad = (struct long_ad *)ptr;
1805
		lad->extLength = cpu_to_le32(elen);
1806
		lad->extLocation = cpu_to_lelb(*eloc);
1807
		memset(lad->impUse, 0x00, sizeof(lad->impUse));
1808
		adsize = sizeof(struct long_ad);
1809
		break;
1810 1811
	default:
		return -1;
L
Linus Torvalds 已提交
1812 1813
	}

1814
	if (epos->bh) {
1815
		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
M
Marcin Slusarz 已提交
1816
		    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) {
M
Marcin Slusarz 已提交
1817 1818
			struct allocExtDesc *aed =
				(struct allocExtDesc *)epos->bh->b_data;
J
Jan Kara 已提交
1819
			udf_update_tag(epos->bh->b_data,
M
Marcin Slusarz 已提交
1820 1821
				       le32_to_cpu(aed->lengthAllocDescs) +
				       sizeof(struct allocExtDesc));
L
Linus Torvalds 已提交
1822
		}
J
Jan Kara 已提交
1823
		mark_buffer_dirty_inode(epos->bh, inode);
1824
	} else {
L
Linus Torvalds 已提交
1825
		mark_inode_dirty(inode);
1826
	}
L
Linus Torvalds 已提交
1827 1828

	if (inc)
J
Jan Kara 已提交
1829
		epos->offset += adsize;
1830

L
Linus Torvalds 已提交
1831 1832 1833
	return (elen >> 30);
}

M
Marcin Slusarz 已提交
1834
int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
1835
		     struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
L
Linus Torvalds 已提交
1836 1837 1838
{
	int8_t etype;

J
Jan Kara 已提交
1839
	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
1840
	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
M
Marcin Slusarz 已提交
1841
		int block;
J
Jan Kara 已提交
1842 1843
		epos->block = *eloc;
		epos->offset = sizeof(struct allocExtDesc);
J
Jan Kara 已提交
1844
		brelse(epos->bh);
1845
		block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0);
M
Marcin Slusarz 已提交
1846 1847 1848
		epos->bh = udf_tread(inode->i_sb, block);
		if (!epos->bh) {
			udf_debug("reading block %d failed!\n", block);
L
Linus Torvalds 已提交
1849 1850 1851 1852 1853 1854 1855
			return -1;
		}
	}

	return etype;
}

M
Marcin Slusarz 已提交
1856
int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
1857
			struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
L
Linus Torvalds 已提交
1858 1859 1860 1861
{
	int alen;
	int8_t etype;
	uint8_t *ptr;
1862 1863
	struct short_ad *sad;
	struct long_ad *lad;
1864
	struct udf_inode_info *iinfo = UDF_I(inode);
1865

1866
	if (!epos->bh) {
J
Jan Kara 已提交
1867 1868
		if (!epos->offset)
			epos->offset = udf_file_entry_alloc_offset(inode);
1869
		ptr = iinfo->i_ext.i_data + epos->offset -
M
Marcin Slusarz 已提交
1870
			udf_file_entry_alloc_offset(inode) +
1871
			iinfo->i_lenEAttr;
M
Marcin Slusarz 已提交
1872
		alen = udf_file_entry_alloc_offset(inode) +
1873
							iinfo->i_lenAlloc;
1874
	} else {
J
Jan Kara 已提交
1875 1876 1877
		if (!epos->offset)
			epos->offset = sizeof(struct allocExtDesc);
		ptr = epos->bh->b_data + epos->offset;
1878
		alen = sizeof(struct allocExtDesc) +
M
Marcin Slusarz 已提交
1879 1880
			le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->
							lengthAllocDescs);
L
Linus Torvalds 已提交
1881 1882
	}

1883
	switch (iinfo->i_alloc_type) {
1884
	case ICBTAG_FLAG_AD_SHORT:
M
Marcin Slusarz 已提交
1885 1886
		sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc);
		if (!sad)
1887 1888 1889
			return -1;
		etype = le32_to_cpu(sad->extLength) >> 30;
		eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
M
Marcin Slusarz 已提交
1890
		eloc->partitionReferenceNum =
1891
				iinfo->i_location.partitionReferenceNum;
1892 1893
		*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
		break;
1894
	case ICBTAG_FLAG_AD_LONG:
M
Marcin Slusarz 已提交
1895 1896
		lad = udf_get_filelongad(ptr, alen, &epos->offset, inc);
		if (!lad)
L
Linus Torvalds 已提交
1897
			return -1;
1898 1899 1900 1901 1902
		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:
M
Marcin Slusarz 已提交
1903
		udf_debug("alloc_type = %d unsupported\n",
1904
				iinfo->i_alloc_type);
1905
		return -1;
L
Linus Torvalds 已提交
1906 1907 1908 1909 1910
	}

	return etype;
}

1911
static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos,
1912
			      struct kernel_lb_addr neloc, uint32_t nelen)
L
Linus Torvalds 已提交
1913
{
1914
	struct kernel_lb_addr oeloc;
L
Linus Torvalds 已提交
1915 1916 1917
	uint32_t oelen;
	int8_t etype;

J
Jan Kara 已提交
1918
	if (epos.bh)
J
Jan Kara 已提交
1919
		get_bh(epos.bh);
L
Linus Torvalds 已提交
1920

1921
	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {
1922
		udf_write_aext(inode, &epos, &neloc, nelen, 1);
L
Linus Torvalds 已提交
1923 1924 1925
		neloc = oeloc;
		nelen = (etype << 30) | oelen;
	}
1926
	udf_add_aext(inode, &epos, &neloc, nelen, 1);
J
Jan Kara 已提交
1927
	brelse(epos.bh);
1928

L
Linus Torvalds 已提交
1929 1930 1931
	return (nelen >> 30);
}

M
Marcin Slusarz 已提交
1932
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
1933
		       struct kernel_lb_addr eloc, uint32_t elen)
L
Linus Torvalds 已提交
1934
{
J
Jan Kara 已提交
1935 1936
	struct extent_position oepos;
	int adsize;
L
Linus Torvalds 已提交
1937 1938
	int8_t etype;
	struct allocExtDesc *aed;
1939
	struct udf_inode_info *iinfo;
L
Linus Torvalds 已提交
1940

1941
	if (epos.bh) {
J
Jan Kara 已提交
1942 1943
		get_bh(epos.bh);
		get_bh(epos.bh);
L
Linus Torvalds 已提交
1944 1945
	}

1946 1947
	iinfo = UDF_I(inode);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
1948
		adsize = sizeof(struct short_ad);
1949
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
1950
		adsize = sizeof(struct long_ad);
L
Linus Torvalds 已提交
1951 1952 1953
	else
		adsize = 0;

J
Jan Kara 已提交
1954 1955
	oepos = epos;
	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
L
Linus Torvalds 已提交
1956 1957
		return -1;

1958
	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
1959
		udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1);
1960
		if (oepos.bh != epos.bh) {
J
Jan Kara 已提交
1961
			oepos.block = epos.block;
J
Jan Kara 已提交
1962 1963
			brelse(oepos.bh);
			get_bh(epos.bh);
J
Jan Kara 已提交
1964 1965
			oepos.bh = epos.bh;
			oepos.offset = epos.offset - adsize;
L
Linus Torvalds 已提交
1966 1967
		}
	}
1968
	memset(&eloc, 0x00, sizeof(struct kernel_lb_addr));
L
Linus Torvalds 已提交
1969 1970
	elen = 0;

1971
	if (epos.bh != oepos.bh) {
1972 1973 1974
		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);
1975
		if (!oepos.bh) {
1976
			iinfo->i_lenAlloc -= (adsize * 2);
L
Linus Torvalds 已提交
1977
			mark_inode_dirty(inode);
1978
		} else {
J
Jan Kara 已提交
1979
			aed = (struct allocExtDesc *)oepos.bh->b_data;
1980
			le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
1981
			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
M
Marcin Slusarz 已提交
1982
			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
M
Marcin Slusarz 已提交
1983 1984
				udf_update_tag(oepos.bh->b_data,
						oepos.offset - (2 * adsize));
L
Linus Torvalds 已提交
1985
			else
M
Marcin Slusarz 已提交
1986 1987
				udf_update_tag(oepos.bh->b_data,
						sizeof(struct allocExtDesc));
J
Jan Kara 已提交
1988
			mark_buffer_dirty_inode(oepos.bh, inode);
L
Linus Torvalds 已提交
1989
		}
1990
	} else {
1991
		udf_write_aext(inode, &oepos, &eloc, elen, 1);
1992
		if (!oepos.bh) {
1993
			iinfo->i_lenAlloc -= adsize;
L
Linus Torvalds 已提交
1994
			mark_inode_dirty(inode);
1995
		} else {
J
Jan Kara 已提交
1996
			aed = (struct allocExtDesc *)oepos.bh->b_data;
1997
			le32_add_cpu(&aed->lengthAllocDescs, -adsize);
1998
			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
M
Marcin Slusarz 已提交
1999
			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
M
Marcin Slusarz 已提交
2000 2001
				udf_update_tag(oepos.bh->b_data,
						epos.offset - adsize);
L
Linus Torvalds 已提交
2002
			else
M
Marcin Slusarz 已提交
2003 2004
				udf_update_tag(oepos.bh->b_data,
						sizeof(struct allocExtDesc));
J
Jan Kara 已提交
2005
			mark_buffer_dirty_inode(oepos.bh, inode);
L
Linus Torvalds 已提交
2006 2007
		}
	}
2008

J
Jan Kara 已提交
2009 2010
	brelse(epos.bh);
	brelse(oepos.bh);
2011

L
Linus Torvalds 已提交
2012 2013 2014
	return (elen >> 30);
}

M
Marcin Slusarz 已提交
2015
int8_t inode_bmap(struct inode *inode, sector_t block,
2016
		  struct extent_position *pos, struct kernel_lb_addr *eloc,
M
Marcin Slusarz 已提交
2017
		  uint32_t *elen, sector_t *offset)
L
Linus Torvalds 已提交
2018
{
M
Marcin Slusarz 已提交
2019
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
2020
	loff_t lbcount = 0, bcount =
M
Marcin Slusarz 已提交
2021
	    (loff_t) block << blocksize_bits;
L
Linus Torvalds 已提交
2022
	int8_t etype;
2023
	struct udf_inode_info *iinfo;
L
Linus Torvalds 已提交
2024

2025
	iinfo = UDF_I(inode);
J
Jan Kara 已提交
2026
	pos->offset = 0;
2027
	pos->block = iinfo->i_location;
J
Jan Kara 已提交
2028
	pos->bh = NULL;
L
Linus Torvalds 已提交
2029 2030
	*elen = 0;

2031
	do {
M
Marcin Slusarz 已提交
2032 2033 2034
		etype = udf_next_aext(inode, pos, eloc, elen, 1);
		if (etype == -1) {
			*offset = (bcount - lbcount) >> blocksize_bits;
2035
			iinfo->i_lenExtents = lbcount;
L
Linus Torvalds 已提交
2036 2037 2038 2039 2040
			return -1;
		}
		lbcount += *elen;
	} while (lbcount <= bcount);

M
Marcin Slusarz 已提交
2041
	*offset = (bcount + *elen - lbcount) >> blocksize_bits;
L
Linus Torvalds 已提交
2042 2043 2044 2045

	return etype;
}

2046
long udf_block_map(struct inode *inode, sector_t block)
L
Linus Torvalds 已提交
2047
{
2048
	struct kernel_lb_addr eloc;
J
Jan Kara 已提交
2049
	uint32_t elen;
2050
	sector_t offset;
2051
	struct extent_position epos = {};
L
Linus Torvalds 已提交
2052 2053 2054 2055
	int ret;

	lock_kernel();

M
Marcin Slusarz 已提交
2056 2057
	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==
						(EXT_RECORDED_ALLOCATED >> 30))
2058
		ret = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
L
Linus Torvalds 已提交
2059 2060 2061 2062
	else
		ret = 0;

	unlock_kernel();
J
Jan Kara 已提交
2063
	brelse(epos.bh);
L
Linus Torvalds 已提交
2064 2065 2066 2067 2068 2069

	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
		return udf_fixed_to_variable(ret);
	else
		return ret;
}