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 105 106 107 108 109
	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 "
			"inode size %llu different from extent lenght %llu. "
			"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
	kfree(iinfo->i_ext.i_data);
	iinfo->i_ext.i_data = NULL;
L
Linus Torvalds 已提交
113 114 115 116 117 118 119 120 121 122 123 124
}

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 已提交
125 126 127
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 已提交
128
{
N
Nick Piggin 已提交
129 130 131
	*pagep = NULL;
	return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
				udf_get_block);
L
Linus Torvalds 已提交
132 133 134 135
}

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

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

148
void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
L
Linus Torvalds 已提交
149 150 151
{
	struct page *page;
	char *kaddr;
152
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
153 154 155 156 157 158 159 160
	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;

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

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

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

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

	mark_inode_dirty(inode);
}

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

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

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

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

	/* alloc block, and copy data to it */
	*block = udf_new_block(inode->i_sb, inode,
225 226
			       iinfo->i_location.partitionReferenceNum,
			       iinfo->i_location.logicalBlockNum, err);
L
Linus Torvalds 已提交
227 228 229
	if (!(*block))
		return NULL;
	newblock = udf_get_pblock(inode->i_sb, *block,
230
				  iinfo->i_location.partitionReferenceNum,
231
				0);
L
Linus Torvalds 已提交
232 233 234 235 236 237 238 239 240 241 242
	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 已提交
243
	sfibh.soffset = sfibh.eoffset =
244
			f_pos & (inode->i_sb->s_blocksize - 1);
J
Jan Kara 已提交
245
	sfibh.sbh = sfibh.ebh = NULL;
L
Linus Torvalds 已提交
246 247
	dfibh.soffset = dfibh.eoffset = 0;
	dfibh.sbh = dfibh.ebh = dbh;
248
	while (f_pos < size) {
249
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
M
Marcin Slusarz 已提交
250 251
		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL,
					 NULL, NULL, NULL);
252
		if (!sfi) {
J
Jan Kara 已提交
253
			brelse(dbh);
L
Linus Torvalds 已提交
254 255
			return NULL;
		}
256
		iinfo->i_alloc_type = alloctype;
L
Linus Torvalds 已提交
257 258 259 260 261
		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 已提交
262 263
				 sfi->fileIdent +
					le16_to_cpu(sfi->lengthOfImpUse))) {
264
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
J
Jan Kara 已提交
265
			brelse(dbh);
L
Linus Torvalds 已提交
266 267 268 269 270
			return NULL;
		}
	}
	mark_buffer_dirty_inode(dbh, inode);

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

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

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

297
	if (!create) {
L
Linus Torvalds 已提交
298 299 300 301 302 303 304 305 306 307 308 309
		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();

310 311 312 313
	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 已提交
314 315 316 317 318
	}

	err = 0;

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

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

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

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

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

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

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

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

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

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

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

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

J
Jan Kara 已提交
418 419 420 421 422 423
	/* 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 已提交
424
	last_ext->extLocation.partitionReferenceNum = 0;
425
	add = (1 << (30-sb->s_blocksize_bits)) - 1;
M
Marcin Slusarz 已提交
426 427
	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
				(add << sb->s_blocksize_bits);
428

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

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

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

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

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

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

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

		lbcount += elen;

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

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

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

		c = !c;

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

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

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

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

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

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

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

		if (count) {
			if (c)
				laarr[0] = laarr[1];
			startnum = 1;
569
		} else {
J
Jan Kara 已提交
570
			/* Create a fake extent when there's not one */
M
Marcin Slusarz 已提交
571
			memset(&laarr[0].extLocation, 0x00,
572
				sizeof(struct kernel_lb_addr));
J
Jan Kara 已提交
573
			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
M
Marcin Slusarz 已提交
574 575
			/* Will udf_extend_file() create real extent from
			   a fake one? */
J
Jan Kara 已提交
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
			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 已提交
593 594
		if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) !=
						EXT_NOT_RECORDED_ALLOCATED) {
J
Jan Kara 已提交
595 596 597 598 599
			/* Is there any real extent? - otherwise we overwrite
			 * the fake one... */
			if (count)
				c = !c;
			laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
600
				inode->i_sb->s_blocksize;
M
Marcin Slusarz 已提交
601
			memset(&laarr[c].extLocation, 0x00,
602
				sizeof(struct kernel_lb_addr));
603 604
			count++;
			endnum++;
J
Jan Kara 已提交
605
		}
606
		endnum = c + 1;
L
Linus Torvalds 已提交
607
		lastblock = 1;
608
	} else {
L
Linus Torvalds 已提交
609 610
		endnum = startnum = ((count > 2) ? 2 : count);

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

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

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

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

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

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

#ifdef UDF_PREALLOCATE
664 665 666 667 668 669
	/* 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 已提交
670 671 672 673 674 675
#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
676 677
	 * 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 已提交
678
	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
L
Linus Torvalds 已提交
679

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

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

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

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

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

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

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

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

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

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

772
	if (*endnum >= (c + 1)) {
L
Linus Torvalds 已提交
773 774 775 776
		if (!lastblock)
			return;
		else
			start = c;
777
	} else {
M
Marcin Slusarz 已提交
778 779
		if ((laarr[c + 1].extLength >> 30) ==
					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
780
			start = c + 1;
M
Marcin Slusarz 已提交
781 782 783 784 785 786
			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 已提交
787 788 789
			start = c;
	}

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

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

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

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

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

870
	for (i = 0; i < (*endnum - 1); i++) {
871 872
		struct kernel_long_ad *li /*l[i]*/ = &laarr[i];
		struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1];
M
Marcin Slusarz 已提交
873 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

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

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

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

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

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

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

	if (buffer_uptodate(bh))
		return bh;
1003

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	inode->i_uid = le32_to_cpu(fe->uid);
1208 1209 1210
	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))
1211
		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
L
Linus Torvalds 已提交
1212 1213

	inode->i_gid = le32_to_cpu(fe->gid);
1214 1215 1216
	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))
1217
		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
L
Linus Torvalds 已提交
1218 1219 1220 1221

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

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

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

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

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

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

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

1250 1251 1252 1253
		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;
1254
	} else {
1255
		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
1256
		    (inode->i_sb->s_blocksize_bits - 9);
L
Linus Torvalds 已提交
1257

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

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

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

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

1271 1272 1273
		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 已提交
1274
		offset = sizeof(struct extendedFileEntry) +
1275
							iinfo->i_lenEAttr;
L
Linus Torvalds 已提交
1276 1277
	}

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

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

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

	return 0;
}

1357
static mode_t udf_convert_permissions(struct fileEntry *fe)
L
Linus Torvalds 已提交
1358 1359 1360 1361 1362 1363 1364 1365
{
	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 已提交
1366 1367 1368 1369 1370 1371
	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 已提交
1372 1373 1374 1375

	return mode;
}

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

L
Linus Torvalds 已提交
1380 1381 1382
	lock_kernel();
	ret = udf_update_inode(inode, sync);
	unlock_kernel();
1383

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

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

1392
static int udf_update_inode(struct inode *inode, int do_sync)
L
Linus Torvalds 已提交
1393 1394 1395 1396 1397 1398 1399 1400
{
	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 已提交
1401
	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
M
Marcin Slusarz 已提交
1402
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
1403
	struct udf_inode_info *iinfo = UDF_I(inode);
L
Linus Torvalds 已提交
1404

M
Marcin Slusarz 已提交
1405 1406
	bh = udf_tread(inode->i_sb,
			udf_get_lb_pblock(inode->i_sb,
1407
					  &iinfo->i_location, 0));
1408
	if (!bh) {
L
Linus Torvalds 已提交
1409 1410 1411 1412 1413 1414 1415 1416 1417
		udf_debug("bread failure\n");
		return -EIO;
	}

	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);

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

1418
	if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_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 1426
					sizeof(struct unallocSpaceEntry));
		crclen = sizeof(struct unallocSpaceEntry) +
1427
				iinfo->i_lenAlloc - sizeof(struct tag);
M
Marcin Slusarz 已提交
1428
		use->descTag.tagLocation = cpu_to_le32(
1429
						iinfo->i_location.
M
Marcin Slusarz 已提交
1430
							logicalBlockNum);
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

		mark_buffer_dirty(bh);
J
Jan Kara 已提交
1438
		brelse(bh);
L
Linus Torvalds 已提交
1439 1440 1441
		return err;
	}

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

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

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

M
Marcin Slusarz 已提交
1456 1457 1458 1459
	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 已提交
1460 1461 1462 1463 1464 1465 1466 1467 1468
	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);

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

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

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

1524 1525 1526 1527
		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 已提交
1528

1529 1530 1531 1532
		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 已提交
1533

1534 1535 1536 1537
		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 已提交
1538

1539 1540 1541 1542
		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 已提交
1543

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

1578
	icbflags =	iinfo->i_alloc_type |
1579 1580 1581 1582 1583 1584
			((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 已提交
1585 1586

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

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

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

1617
struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
L
Linus Torvalds 已提交
1618 1619 1620 1621 1622 1623 1624 1625
{
	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) {
1626
		memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
L
Linus Torvalds 已提交
1627 1628 1629 1630 1631 1632 1633
		__udf_read_inode(inode);
		unlock_new_inode(inode);
	}

	if (is_bad_inode(inode))
		goto out_iput;

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

	return inode;

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

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

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

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

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

M
Marcin Slusarz 已提交
1680 1681 1682 1683
		epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
						obloc.partitionReferenceNum,
						obloc.logicalBlockNum, &err);
		if (!epos->block.logicalBlockNum)
L
Linus Torvalds 已提交
1684
			return -1;
M
Marcin Slusarz 已提交
1685
		nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
1686
								 &epos->block,
M
Marcin Slusarz 已提交
1687 1688
								 0));
		if (!nbh)
L
Linus Torvalds 已提交
1689 1690 1691 1692 1693 1694 1695 1696 1697
			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 已提交
1698 1699
			aed->previousAllocExtLocation =
					cpu_to_le32(obloc.logicalBlockNum);
1700
		if (epos->offset + adsize > inode->i_sb->s_blocksize) {
J
Jan Kara 已提交
1701
			loffset = epos->offset;
L
Linus Torvalds 已提交
1702 1703 1704 1705
			aed->lengthAllocDescs = cpu_to_le32(adsize);
			sptr = ptr - adsize;
			dptr = nbh->b_data + sizeof(struct allocExtDesc);
			memcpy(dptr, sptr, adsize);
J
Jan Kara 已提交
1706
			epos->offset = sizeof(struct allocExtDesc) + adsize;
1707
		} else {
J
Jan Kara 已提交
1708
			loffset = epos->offset + adsize;
L
Linus Torvalds 已提交
1709 1710
			aed->lengthAllocDescs = cpu_to_le32(0);
			sptr = ptr;
J
Jan Kara 已提交
1711
			epos->offset = sizeof(struct allocExtDesc);
L
Linus Torvalds 已提交
1712

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

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

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

	return etype;
}

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

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

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

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

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

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

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

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

	return etype;
}

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

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

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

	return etype;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return etype;
}

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

	lock_kernel();

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

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

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