inode.c 67.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
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
Marcin Slusarz's avatar
Marcin Slusarz committed
22 23
 *  12/06/98 blf  partition support in udf_iget, udf_block_map
 *                and udf_read_inode
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37
 *  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/module.h>
#include <linux/pagemap.h>
#include <linux/writeback.h>
#include <linux/slab.h>
38
#include <linux/crc-itu-t.h>
39
#include <linux/mpage.h>
40
#include <linux/uio.h>
41
#include <linux/bio.h>
Linus Torvalds's avatar
Linus Torvalds committed
42 43 44 45 46 47

#include "udf_i.h"
#include "udf_sb.h"

#define EXTENT_MERGE_SIZE 5

48 49 50 51 52 53 54
#define FE_MAPPED_PERMS	(FE_PERM_U_READ | FE_PERM_U_WRITE | FE_PERM_U_EXEC | \
			 FE_PERM_G_READ | FE_PERM_G_WRITE | FE_PERM_G_EXEC | \
			 FE_PERM_O_READ | FE_PERM_O_WRITE | FE_PERM_O_EXEC)

#define FE_DELETE_PERMS	(FE_PERM_U_DELETE | FE_PERM_G_DELETE | \
			 FE_PERM_O_DELETE)

55 56
struct udf_map_rq;

Al Viro's avatar
Al Viro committed
57
static umode_t udf_convert_permissions(struct fileEntry *);
Linus Torvalds's avatar
Linus Torvalds committed
58
static int udf_update_inode(struct inode *, int);
59
static int udf_sync_inode(struct inode *inode);
60
static int udf_alloc_i_data(struct inode *inode, size_t size);
61
static int inode_getblk(struct inode *inode, struct udf_map_rq *map);
62 63
static int udf_insert_aext(struct inode *, struct extent_position,
			   struct kernel_lb_addr, uint32_t);
64
static void udf_split_extents(struct inode *, int *, int, udf_pblk_t,
65
			      struct kernel_long_ad *, int *);
Linus Torvalds's avatar
Linus Torvalds committed
66
static void udf_prealloc_extents(struct inode *, int, int,
67 68
				 struct kernel_long_ad *, int *);
static void udf_merge_extents(struct inode *, struct kernel_long_ad *, int *);
69 70
static int udf_update_extents(struct inode *, struct kernel_long_ad *, int,
			      int, struct extent_position *);
71 72
static int udf_get_block_wb(struct inode *inode, sector_t block,
			    struct buffer_head *bh_result, int create);
Linus Torvalds's avatar
Linus Torvalds committed
73

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
static void __udf_clear_extent_cache(struct inode *inode)
{
	struct udf_inode_info *iinfo = UDF_I(inode);

	if (iinfo->cached_extent.lstart != -1) {
		brelse(iinfo->cached_extent.epos.bh);
		iinfo->cached_extent.lstart = -1;
	}
}

/* Invalidate extent cache */
static void udf_clear_extent_cache(struct inode *inode)
{
	struct udf_inode_info *iinfo = UDF_I(inode);

	spin_lock(&iinfo->i_extent_cache_lock);
	__udf_clear_extent_cache(inode);
	spin_unlock(&iinfo->i_extent_cache_lock);
}

/* Return contents of extent cache */
static int udf_read_extent_cache(struct inode *inode, loff_t bcount,
				 loff_t *lbcount, struct extent_position *pos)
{
	struct udf_inode_info *iinfo = UDF_I(inode);
	int ret = 0;

	spin_lock(&iinfo->i_extent_cache_lock);
	if ((iinfo->cached_extent.lstart <= bcount) &&
	    (iinfo->cached_extent.lstart != -1)) {
		/* Cache hit */
		*lbcount = iinfo->cached_extent.lstart;
		memcpy(pos, &iinfo->cached_extent.epos,
		       sizeof(struct extent_position));
		if (pos->bh)
			get_bh(pos->bh);
		ret = 1;
	}
	spin_unlock(&iinfo->i_extent_cache_lock);
	return ret;
}

/* Add extent to extent cache */
static void udf_update_extent_cache(struct inode *inode, loff_t estart,
118
				    struct extent_position *pos)
119 120 121 122 123 124 125 126
{
	struct udf_inode_info *iinfo = UDF_I(inode);

	spin_lock(&iinfo->i_extent_cache_lock);
	/* Invalidate previously cached extent */
	__udf_clear_extent_cache(inode);
	if (pos->bh)
		get_bh(pos->bh);
127
	memcpy(&iinfo->cached_extent.epos, pos, sizeof(*pos));
128
	iinfo->cached_extent.lstart = estart;
129 130 131 132 133 134 135 136
	switch (iinfo->i_alloc_type) {
	case ICBTAG_FLAG_AD_SHORT:
		iinfo->cached_extent.epos.offset -= sizeof(struct short_ad);
		break;
	case ICBTAG_FLAG_AD_LONG:
		iinfo->cached_extent.epos.offset -= sizeof(struct long_ad);
		break;
	}
137 138
	spin_unlock(&iinfo->i_extent_cache_lock);
}
139

Al Viro's avatar
Al Viro committed
140
void udf_evict_inode(struct inode *inode)
Linus Torvalds's avatar
Linus Torvalds committed
141
{
Jan Kara's avatar
Jan Kara committed
142
	struct udf_inode_info *iinfo = UDF_I(inode);
Al Viro's avatar
Al Viro committed
143 144
	int want_delete = 0;

145 146 147 148 149 150 151 152 153 154 155 156 157 158
	if (!is_bad_inode(inode)) {
		if (!inode->i_nlink) {
			want_delete = 1;
			udf_setsize(inode, 0);
			udf_update_inode(inode, IS_SYNC(inode));
		}
		if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
		    inode->i_size != iinfo->i_lenExtents) {
			udf_warn(inode->i_sb,
				 "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n",
				 inode->i_ino, inode->i_mode,
				 (unsigned long long)inode->i_size,
				 (unsigned long long)iinfo->i_lenExtents);
		}
159 160
	}
	truncate_inode_pages_final(&inode->i_data);
Al Viro's avatar
Al Viro committed
161
	invalidate_inode_buffers(inode);
162
	clear_inode(inode);
163 164
	kfree(iinfo->i_data);
	iinfo->i_data = NULL;
165
	udf_clear_extent_cache(inode);
Al Viro's avatar
Al Viro committed
166 167 168
	if (want_delete) {
		udf_free_inode(inode);
	}
Linus Torvalds's avatar
Linus Torvalds committed
169 170
}

Ian Abbott's avatar
Ian Abbott committed
171 172 173 174 175 176 177
static void udf_write_failed(struct address_space *mapping, loff_t to)
{
	struct inode *inode = mapping->host;
	struct udf_inode_info *iinfo = UDF_I(inode);
	loff_t isize = inode->i_size;

	if (to > isize) {
178
		truncate_pagecache(inode, isize);
Ian Abbott's avatar
Ian Abbott committed
179 180
		if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
			down_write(&iinfo->i_data_sem);
181
			udf_clear_extent_cache(inode);
Ian Abbott's avatar
Ian Abbott committed
182 183 184 185 186 187
			udf_truncate_extents(inode);
			up_write(&iinfo->i_data_sem);
		}
	}
}

188 189
static int udf_adinicb_writepage(struct page *page,
				 struct writeback_control *wbc, void *data)
190
{
191 192 193 194
	struct inode *inode = page->mapping->host;
	struct udf_inode_info *iinfo = UDF_I(inode);

	BUG_ON(!PageLocked(page));
195 196
	memcpy_to_page(page, 0, iinfo->i_data + iinfo->i_lenEAttr,
		       i_size_read(inode));
197 198 199 200 201 202
	unlock_page(page);
	mark_inode_dirty(inode);

	return 0;
}

203 204
static int udf_writepages(struct address_space *mapping,
			  struct writeback_control *wbc)
205 206 207 208 209 210 211
{
	struct inode *inode = mapping->host;
	struct udf_inode_info *iinfo = UDF_I(inode);

	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
		return mpage_writepages(mapping, wbc, udf_get_block_wb);
	return write_cache_pages(mapping, wbc, udf_adinicb_writepage, NULL);
212 213
}

214 215 216 217 218 219 220
static void udf_adinicb_readpage(struct page *page)
{
	struct inode *inode = page->mapping->host;
	char *kaddr;
	struct udf_inode_info *iinfo = UDF_I(inode);
	loff_t isize = i_size_read(inode);

221
	kaddr = kmap_local_page(page);
222 223 224 225
	memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, isize);
	memset(kaddr + isize, 0, PAGE_SIZE - isize);
	flush_dcache_page(page);
	SetPageUptodate(page);
226
	kunmap_local(kaddr);
227 228
}

229
static int udf_read_folio(struct file *file, struct folio *folio)
Linus Torvalds's avatar
Linus Torvalds committed
230
{
231 232 233 234 235 236 237
	struct udf_inode_info *iinfo = UDF_I(file_inode(file));

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		udf_adinicb_readpage(&folio->page);
		folio_unlock(folio);
		return 0;
	}
238
	return mpage_read_folio(folio, udf_get_block);
239 240
}

241
static void udf_readahead(struct readahead_control *rac)
242
{
243
	mpage_readahead(rac, udf_get_block);
Linus Torvalds's avatar
Linus Torvalds committed
244 245
}

246 247 248
static int udf_write_begin(struct file *file, struct address_space *mapping,
			   loff_t pos, unsigned len,
			   struct page **pagep, void **fsdata)
Linus Torvalds's avatar
Linus Torvalds committed
249
{
250 251
	struct udf_inode_info *iinfo = UDF_I(file_inode(file));
	struct page *page;
252 253
	int ret;

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
		ret = block_write_begin(mapping, pos, len, pagep,
					udf_get_block);
		if (unlikely(ret))
			udf_write_failed(mapping, pos + len);
		return ret;
	}
	if (WARN_ON_ONCE(pos >= PAGE_SIZE))
		return -EIO;
	page = grab_cache_page_write_begin(mapping, 0);
	if (!page)
		return -ENOMEM;
	*pagep = page;
	if (!PageUptodate(page))
		udf_adinicb_readpage(page);
	return 0;
Ian Abbott's avatar
Ian Abbott committed
270
}
271

272 273 274
static int udf_write_end(struct file *file, struct address_space *mapping,
			 loff_t pos, unsigned len, unsigned copied,
			 struct page *page, void *fsdata)
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
{
	struct inode *inode = file_inode(file);
	loff_t last_pos;

	if (UDF_I(inode)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
		return generic_write_end(file, mapping, pos, len, copied, page,
					 fsdata);
	last_pos = pos + copied;
	if (last_pos > inode->i_size)
		i_size_write(inode, last_pos);
	set_page_dirty(page);
	unlock_page(page);
	put_page(page);

	return copied;
}

292
static ssize_t udf_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
Ian Abbott's avatar
Ian Abbott committed
293 294 295 296
{
	struct file *file = iocb->ki_filp;
	struct address_space *mapping = file->f_mapping;
	struct inode *inode = mapping->host;
297
	size_t count = iov_iter_count(iter);
Ian Abbott's avatar
Ian Abbott committed
298 299
	ssize_t ret;

300 301 302
	/* Fallback to buffered IO for in-ICB files */
	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
		return 0;
303
	ret = blockdev_direct_IO(iocb, inode, iter, udf_get_block);
304
	if (unlikely(ret < 0 && iov_iter_rw(iter) == WRITE))
305
		udf_write_failed(mapping, iocb->ki_pos + count);
306
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
307 308 309 310
}

static sector_t udf_bmap(struct address_space *mapping, sector_t block)
{
311 312 313 314
	struct udf_inode_info *iinfo = UDF_I(mapping->host);

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
		return -EINVAL;
315
	return generic_block_bmap(mapping, block, udf_get_block);
Linus Torvalds's avatar
Linus Torvalds committed
316 317
}

318
const struct address_space_operations udf_aops = {
319
	.dirty_folio	= block_dirty_folio,
320
	.invalidate_folio = block_invalidate_folio,
321
	.read_folio	= udf_read_folio,
322
	.readahead	= udf_readahead,
323
	.writepages	= udf_writepages,
Ian Abbott's avatar
Ian Abbott committed
324
	.write_begin	= udf_write_begin,
325
	.write_end	= udf_write_end,
Ian Abbott's avatar
Ian Abbott committed
326
	.direct_IO	= udf_direct_IO,
327
	.bmap		= udf_bmap,
328
	.migrate_folio	= buffer_migrate_folio,
Linus Torvalds's avatar
Linus Torvalds committed
329 330
};

331 332 333 334 335
/*
 * Expand file stored in ICB to a normal one-block-file
 *
 * This function requires i_mutex held
 */
336
int udf_expand_file_adinicb(struct inode *inode)
Linus Torvalds's avatar
Linus Torvalds committed
337 338 339
{
	struct page *page;
	char *kaddr;
340
	struct udf_inode_info *iinfo = UDF_I(inode);
341
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
342

Al Viro's avatar
Al Viro committed
343
	WARN_ON_ONCE(!inode_is_locked(inode));
344
	if (!iinfo->i_lenAlloc) {
345
		down_write(&iinfo->i_data_sem);
Linus Torvalds's avatar
Linus Torvalds committed
346
		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
347
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
Linus Torvalds's avatar
Linus Torvalds committed
348
		else
349
			iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
350 351
		/* from now on we have normal address_space methods */
		inode->i_data.a_ops = &udf_aops;
352
		up_write(&iinfo->i_data_sem);
Linus Torvalds's avatar
Linus Torvalds committed
353
		mark_inode_dirty(inode);
354
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
355 356
	}

357 358 359
	page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
	if (!page)
		return -ENOMEM;
Matt Mackall's avatar
Matt Mackall committed
360

361
	if (!PageUptodate(page)) {
362
		kaddr = kmap_atomic(page);
363
		memset(kaddr + iinfo->i_lenAlloc, 0x00,
364
		       PAGE_SIZE - iinfo->i_lenAlloc);
365
		memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr,
366
			iinfo->i_lenAlloc);
Linus Torvalds's avatar
Linus Torvalds committed
367 368
		flush_dcache_page(page);
		SetPageUptodate(page);
369
		kunmap_atomic(kaddr);
Linus Torvalds's avatar
Linus Torvalds committed
370
	}
371
	down_write(&iinfo->i_data_sem);
372
	memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
373 374
	       iinfo->i_lenAlloc);
	iinfo->i_lenAlloc = 0;
Linus Torvalds's avatar
Linus Torvalds committed
375
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
376
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
Linus Torvalds's avatar
Linus Torvalds committed
377
	else
378
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
379 380
	set_page_dirty(page);
	unlock_page(page);
381
	up_write(&iinfo->i_data_sem);
382
	err = filemap_fdatawrite(inode->i_mapping);
383 384 385
	if (err) {
		/* Restore everything back so that we don't lose data... */
		lock_page(page);
386
		down_write(&iinfo->i_data_sem);
387
		kaddr = kmap_atomic(page);
388
		memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, inode->i_size);
389
		kunmap_atomic(kaddr);
390 391
		unlock_page(page);
		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
392
		iinfo->i_lenAlloc = inode->i_size;
393
		up_write(&iinfo->i_data_sem);
394
	}
395
	put_page(page);
Linus Torvalds's avatar
Linus Torvalds committed
396
	mark_inode_dirty(inode);
397 398

	return err;
Linus Torvalds's avatar
Linus Torvalds committed
399 400
}

401 402
#define UDF_MAP_CREATE		0x01	/* Mapping can allocate new blocks */
#define UDF_MAP_NOPREALLOC	0x02	/* Do not preallocate blocks */
403 404 405 406 407 408 409 410 411 412 413 414

#define UDF_BLK_MAPPED	0x01	/* Block was successfully mapped */
#define UDF_BLK_NEW	0x02	/* Block was freshly allocated */

struct udf_map_rq {
	sector_t lblk;
	udf_pblk_t pblk;
	int iflags;		/* UDF_MAP_ flags determining behavior */
	int oflags;		/* UDF_BLK_ flags reporting results */
};

static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
Linus Torvalds's avatar
Linus Torvalds committed
415
{
416
	int err;
417
	struct udf_inode_info *iinfo = UDF_I(inode);
Linus Torvalds's avatar
Linus Torvalds committed
418

419 420
	map->oflags = 0;
	if (!(map->iflags & UDF_MAP_CREATE)) {
421 422 423 424 425 426 427 428 429 430
		struct kernel_lb_addr eloc;
		uint32_t elen;
		sector_t offset;
		struct extent_position epos = {};

		down_read(&iinfo->i_data_sem);
		if (inode_bmap(inode, map->lblk, &epos, &eloc, &elen, &offset)
				== (EXT_RECORDED_ALLOCATED >> 30)) {
			map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc,
							offset);
431
			map->oflags |= UDF_BLK_MAPPED;
432 433 434 435
		}
		up_read(&iinfo->i_data_sem);
		brelse(epos.bh);

Linus Torvalds's avatar
Linus Torvalds committed
436 437 438
		return 0;
	}

439
	down_write(&iinfo->i_data_sem);
440 441 442 443
	/*
	 * Block beyond EOF and prealloc extents? Just discard preallocation
	 * as it is not useful and complicates things.
	 */
444
	if (((loff_t)map->lblk) << inode->i_blkbits >= iinfo->i_lenExtents)
445
		udf_discard_prealloc(inode);
446
	udf_clear_extent_cache(inode);
447
	err = inode_getblk(inode, map);
448
	up_write(&iinfo->i_data_sem);
449
	return err;
450
}
451

452 453
static int __udf_get_block(struct inode *inode, sector_t block,
			   struct buffer_head *bh_result, int flags)
454 455 456 457
{
	int err;
	struct udf_map_rq map = {
		.lblk = block,
458
		.iflags = flags,
459 460 461 462 463 464 465 466 467 468 469
	};

	err = udf_map_block(inode, &map);
	if (err < 0)
		return err;
	if (map.oflags & UDF_BLK_MAPPED) {
		map_bh(bh_result, inode->i_sb, map.pblk);
		if (map.oflags & UDF_BLK_NEW)
			set_buffer_new(bh_result);
	}
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
470 471
}

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
int udf_get_block(struct inode *inode, sector_t block,
		  struct buffer_head *bh_result, int create)
{
	int flags = create ? UDF_MAP_CREATE : 0;

	/*
	 * 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))
		flags |= UDF_MAP_NOPREALLOC;
	return __udf_get_block(inode, block, bh_result, flags);
}

/*
 * We shouldn't be allocating blocks on page writeback since we allocate them
 * on page fault. We can spot dirty buffers without allocated blocks though
 * when truncate expands file. These however don't have valid data so we can
 * safely ignore them. So never allocate blocks from page writeback.
 */
static int udf_get_block_wb(struct inode *inode, sector_t block,
			    struct buffer_head *bh_result, int create)
{
	return __udf_get_block(inode, block, bh_result, 0);
}

500 501 502
/* Extend the file with new blocks totaling 'new_block_bytes',
 * return the number of extents added
 */
503 504 505
static int udf_do_extend_file(struct inode *inode,
			      struct extent_position *last_pos,
			      struct kernel_long_ad *last_ext,
506
			      loff_t new_block_bytes)
Jan Kara's avatar
Jan Kara committed
507
{
508
	uint32_t add;
Jan Kara's avatar
Jan Kara committed
509 510
	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
	struct super_block *sb = inode->i_sb;
511
	struct udf_inode_info *iinfo;
512
	int err;
Jan Kara's avatar
Jan Kara committed
513 514 515

	/* The previous extent is fake and we should not extend by anything
	 * - there's nothing to do... */
516
	if (!new_block_bytes && fake)
Jan Kara's avatar
Jan Kara committed
517
		return 0;
518

519
	iinfo = UDF_I(inode);
Jan Kara's avatar
Jan Kara committed
520 521 522
	/* Round the last extent up to a multiple of block size */
	if (last_ext->extLength & (sb->s_blocksize - 1)) {
		last_ext->extLength =
523 524 525
			(last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
			(((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
			  sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
526 527
		iinfo->i_lenExtents =
			(iinfo->i_lenExtents + sb->s_blocksize - 1) &
528
			~(sb->s_blocksize - 1);
Jan Kara's avatar
Jan Kara committed
529
	}
530

531
	add = 0;
Jan Kara's avatar
Jan Kara committed
532
	/* Can we merge with the previous extent? */
Marcin Slusarz's avatar
Marcin Slusarz committed
533 534
	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
					EXT_NOT_RECORDED_NOT_ALLOCATED) {
535 536 537 538 539 540
		add = (1 << 30) - sb->s_blocksize -
			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
		if (add > new_block_bytes)
			add = new_block_bytes;
		new_block_bytes -= add;
		last_ext->extLength += add;
Jan Kara's avatar
Jan Kara committed
541 542 543
	}

	if (fake) {
544 545 546 547
		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
				   last_ext->extLength, 1);
		if (err < 0)
			goto out_err;
Jan Kara's avatar
Jan Kara committed
548
		count++;
549 550 551 552
	} else {
		struct kernel_lb_addr tmploc;
		uint32_t tmplen;

553
		udf_write_aext(inode, last_pos, &last_ext->extLocation,
Marcin Slusarz's avatar
Marcin Slusarz committed
554
				last_ext->extLength, 1);
555

556
		/*
557 558 559
		 * We've rewritten the last extent. If we are going to add
		 * more extents, we may need to enter possible following
		 * empty indirect extent.
560
		 */
561
		if (new_block_bytes)
562
			udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0);
563
	}
564
	iinfo->i_lenExtents += add;
565

Jan Kara's avatar
Jan Kara committed
566
	/* Managed to do everything necessary? */
567
	if (!new_block_bytes)
Jan Kara's avatar
Jan Kara committed
568 569 570 571
		goto out;

	/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
	last_ext->extLocation.logicalBlockNum = 0;
Marcin Slusarz's avatar
Marcin Slusarz committed
572
	last_ext->extLocation.partitionReferenceNum = 0;
573 574
	add = (1 << 30) - sb->s_blocksize;
	last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | add;
575

Jan Kara's avatar
Jan Kara committed
576
	/* Create enough extents to cover the whole hole */
577 578
	while (new_block_bytes > add) {
		new_block_bytes -= add;
579 580 581
		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
				   last_ext->extLength, 1);
		if (err)
582
			goto out_err;
583
		iinfo->i_lenExtents += add;
Jan Kara's avatar
Jan Kara committed
584 585
		count++;
	}
586
	if (new_block_bytes) {
Jan Kara's avatar
Jan Kara committed
587
		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
588
			new_block_bytes;
589 590 591
		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
				   last_ext->extLength, 1);
		if (err)
592
			goto out_err;
593
		iinfo->i_lenExtents += new_block_bytes;
Jan Kara's avatar
Jan Kara committed
594 595
		count++;
	}
596 597

out:
Jan Kara's avatar
Jan Kara committed
598
	/* last_pos should point to the last written extent... */
599
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
600
		last_pos->offset -= sizeof(struct short_ad);
601
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
602
		last_pos->offset -= sizeof(struct long_ad);
Jan Kara's avatar
Jan Kara committed
603
	else
604
		return -EIO;
605

Jan Kara's avatar
Jan Kara committed
606
	return count;
607 608 609 610 611
out_err:
	/* Remove extents we've created so far */
	udf_clear_extent_cache(inode);
	udf_truncate_extents(inode);
	return err;
Jan Kara's avatar
Jan Kara committed
612 613
}

614 615 616 617
/* Extend the final block of the file to final_block_len bytes */
static void udf_do_extend_final_block(struct inode *inode,
				      struct extent_position *last_pos,
				      struct kernel_long_ad *last_ext,
618
				      uint32_t new_elen)
619 620 621
{
	uint32_t added_bytes;

622 623 624 625 626 627
	/*
	 * Extent already large enough? It may be already rounded up to block
	 * size...
	 */
	if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK))
		return;
628
	added_bytes = new_elen - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
629 630 631 632 633 634 635
	last_ext->extLength += added_bytes;
	UDF_I(inode)->i_lenExtents += added_bytes;

	udf_write_aext(inode, last_pos, &last_ext->extLocation,
			last_ext->extLength, 1);
}

636 637 638 639 640 641 642 643 644
static int udf_extend_file(struct inode *inode, loff_t newsize)
{

	struct extent_position epos;
	struct kernel_lb_addr eloc;
	uint32_t elen;
	int8_t etype;
	struct super_block *sb = inode->i_sb;
	sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
645
	loff_t new_elen;
646 647 648
	int adsize;
	struct udf_inode_info *iinfo = UDF_I(inode);
	struct kernel_long_ad extent;
649
	int err = 0;
650
	bool within_last_ext;
651 652 653 654 655 656 657 658

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		adsize = sizeof(struct short_ad);
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
		adsize = sizeof(struct long_ad);
	else
		BUG();

659
	down_write(&iinfo->i_data_sem);
660 661 662 663 664 665
	/*
	 * When creating hole in file, just don't bother with preserving
	 * preallocation. It likely won't be very useful anyway.
	 */
	udf_discard_prealloc(inode);

666
	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
667
	within_last_ext = (etype != -1);
668
	/* We don't expect extents past EOF... */
669
	WARN_ON_ONCE(within_last_ext &&
670
		     elen > ((loff_t)offset + 1) << inode->i_blkbits);
671 672 673 674 675 676 677 678 679 680 681 682 683 684

	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
		/* File has no extents at all or has empty last
		 * indirect extent! Create a fake extent... */
		extent.extLocation.logicalBlockNum = 0;
		extent.extLocation.partitionReferenceNum = 0;
		extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
	} else {
		epos.offset -= adsize;
		etype = udf_next_aext(inode, &epos, &extent.extLocation,
				      &extent.extLength, 0);
		extent.extLength |= etype << 30;
	}
685

686 687
	new_elen = ((loff_t)offset << inode->i_blkbits) |
					(newsize & (sb->s_blocksize - 1));
688 689 690 691

	/* File has extent covering the new size (could happen when extending
	 * inside a block)?
	 */
692
	if (within_last_ext) {
693
		/* Extending file within the last file block */
694
		udf_do_extend_final_block(inode, &epos, &extent, new_elen);
695
	} else {
696
		err = udf_do_extend_file(inode, &epos, &extent, new_elen);
697 698
	}

699 700 701 702 703
	if (err < 0)
		goto out;
	err = 0;
out:
	brelse(epos.bh);
704
	up_write(&iinfo->i_data_sem);
705 706 707
	return err;
}

708
static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
Linus Torvalds's avatar
Linus Torvalds committed
709
{
710
	struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];
711
	struct extent_position prev_epos, cur_epos, next_epos;
Linus Torvalds's avatar
Linus Torvalds committed
712
	int count = 0, startnum = 0, endnum = 0;
Jan Kara's avatar
Jan Kara committed
713
	uint32_t elen = 0, tmpelen;
714
	struct kernel_lb_addr eloc, tmpeloc;
Linus Torvalds's avatar
Linus Torvalds committed
715
	int c = 1;
716
	loff_t lbcount = 0, b_off = 0;
717
	udf_pblk_t newblocknum;
718
	sector_t offset = 0;
Linus Torvalds's avatar
Linus Torvalds committed
719
	int8_t etype;
720
	struct udf_inode_info *iinfo = UDF_I(inode);
721
	udf_pblk_t goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
Jan Kara's avatar
Jan Kara committed
722
	int lastblock = 0;
723
	bool isBeyondEOF;
724
	int ret = 0;
Linus Torvalds's avatar
Linus Torvalds committed
725

726
	prev_epos.offset = udf_file_entry_alloc_offset(inode);
727
	prev_epos.block = iinfo->i_location;
728 729
	prev_epos.bh = NULL;
	cur_epos = next_epos = prev_epos;
730
	b_off = (loff_t)map->lblk << inode->i_sb->s_blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
731 732

	/* find the extent which contains the block we are looking for.
733 734 735 736
	   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) {
Jan Kara's avatar
Jan Kara committed
737 738
			brelse(prev_epos.bh);
			get_bh(cur_epos.bh);
739
			prev_epos.bh = cur_epos.bh;
Linus Torvalds's avatar
Linus Torvalds committed
740
		}
741
		if (cur_epos.bh != next_epos.bh) {
Jan Kara's avatar
Jan Kara committed
742 743
			brelse(cur_epos.bh);
			get_bh(next_epos.bh);
744
			cur_epos.bh = next_epos.bh;
Linus Torvalds's avatar
Linus Torvalds committed
745 746 747 748
		}

		lbcount += elen;

749 750
		prev_epos.block = cur_epos.block;
		cur_epos.block = next_epos.block;
Linus Torvalds's avatar
Linus Torvalds committed
751

752 753
		prev_epos.offset = cur_epos.offset;
		cur_epos.offset = next_epos.offset;
Linus Torvalds's avatar
Linus Torvalds committed
754

Marcin Slusarz's avatar
Marcin Slusarz committed
755 756
		etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1);
		if (etype == -1)
Linus Torvalds's avatar
Linus Torvalds committed
757 758 759 760 761 762 763 764 765
			break;

		c = !c;

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

		if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
			pgoal = eloc.logicalBlockNum +
766 767
				((elen + inode->i_sb->s_blocksize - 1) >>
				 inode->i_sb->s_blocksize_bits);
Linus Torvalds's avatar
Linus Torvalds committed
768

769
		count++;
Linus Torvalds's avatar
Linus Torvalds committed
770 771 772 773
	} while (lbcount + elen <= b_off);

	b_off -= lbcount;
	offset = b_off >> inode->i_sb->s_blocksize_bits;
Jan Kara's avatar
Jan Kara committed
774 775 776 777 778 779
	/*
	 * 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);
Linus Torvalds's avatar
Linus Torvalds committed
780 781

	/* if the extent is allocated and recorded, return the block
782
	   if the extent is not a multiple of the blocksize, round up */
Linus Torvalds's avatar
Linus Torvalds committed
783

784 785
	if (etype == (EXT_RECORDED_ALLOCATED >> 30)) {
		if (elen & (inode->i_sb->s_blocksize - 1)) {
Linus Torvalds's avatar
Linus Torvalds committed
786
			elen = EXT_RECORDED_ALLOCATED |
787 788
				((elen + inode->i_sb->s_blocksize - 1) &
				 ~(inode->i_sb->s_blocksize - 1));
789 790 791
			iinfo->i_lenExtents =
				ALIGN(iinfo->i_lenExtents,
				      inode->i_sb->s_blocksize);
792
			udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
Linus Torvalds's avatar
Linus Torvalds committed
793
		}
794 795
		map->oflags = UDF_BLK_MAPPED;
		map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
Fabian Frederick's avatar
Fabian Frederick committed
796
		goto out_free;
Linus Torvalds's avatar
Linus Torvalds committed
797 798
	}

799
	/* Are we beyond EOF and preallocated extent? */
800
	if (etype == -1) {
801
		loff_t hole_len;
802

803
		isBeyondEOF = true;
Jan Kara's avatar
Jan Kara committed
804 805 806 807
		if (count) {
			if (c)
				laarr[0] = laarr[1];
			startnum = 1;
808
		} else {
Jan Kara's avatar
Jan Kara committed
809
			/* Create a fake extent when there's not one */
Marcin Slusarz's avatar
Marcin Slusarz committed
810
			memset(&laarr[0].extLocation, 0x00,
811
				sizeof(struct kernel_lb_addr));
Jan Kara's avatar
Jan Kara committed
812
			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
813
			/* Will udf_do_extend_file() create real extent from
Marcin Slusarz's avatar
Marcin Slusarz committed
814
			   a fake one? */
Jan Kara's avatar
Jan Kara committed
815 816 817
			startnum = (offset > 0);
		}
		/* Create extents for the hole between EOF and offset */
818 819
		hole_len = (loff_t)offset << inode->i_blkbits;
		ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len);
820
		if (ret < 0)
Fabian Frederick's avatar
Fabian Frederick committed
821
			goto out_free;
Jan Kara's avatar
Jan Kara committed
822 823 824
		c = 0;
		offset = 0;
		count += ret;
825 826 827 828 829 830 831 832 833 834 835
		/*
		 * Is there any real extent? - otherwise we overwrite the fake
		 * one...
		 */
		if (count)
			c = !c;
		laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
			inode->i_sb->s_blocksize;
		memset(&laarr[c].extLocation, 0x00,
			sizeof(struct kernel_lb_addr));
		count++;
836
		endnum = c + 1;
Linus Torvalds's avatar
Linus Torvalds committed
837
		lastblock = 1;
838
	} else {
839
		isBeyondEOF = false;
Linus Torvalds's avatar
Linus Torvalds committed
840 841
		endnum = startnum = ((count > 2) ? 2 : count);

Marcin Slusarz's avatar
Marcin Slusarz committed
842 843
		/* if the current extent is in position 0,
		   swap it with the previous */
844
		if (!c && count != 1) {
Jan Kara's avatar
Jan Kara committed
845 846 847 848 849
			laarr[2] = laarr[0];
			laarr[0] = laarr[1];
			laarr[1] = laarr[2];
			c = 1;
		}
Linus Torvalds's avatar
Linus Torvalds committed
850

Marcin Slusarz's avatar
Marcin Slusarz committed
851 852 853 854
		/* 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) {
855 856 857 858 859
			laarr[c + 1].extLength = (etype << 30) | elen;
			laarr[c + 1].extLocation = eloc;
			count++;
			startnum++;
			endnum++;
Marcin Slusarz's avatar
Marcin Slusarz committed
860
		} else
Linus Torvalds's avatar
Linus Torvalds committed
861 862 863 864
			lastblock = 1;
	}

	/* if the current extent is not recorded but allocated, get the
865
	 * block in the extent corresponding to the requested block */
Marcin Slusarz's avatar
Marcin Slusarz committed
866
	if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
Linus Torvalds's avatar
Linus Torvalds committed
867
		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
Marcin Slusarz's avatar
Marcin Slusarz committed
868
	else { /* otherwise, allocate a new block */
869
		if (iinfo->i_next_alloc_block == map->lblk)
870
			goal = iinfo->i_next_alloc_goal;
Linus Torvalds's avatar
Linus Torvalds committed
871

872
		if (!goal) {
Marcin Slusarz's avatar
Marcin Slusarz committed
873
			if (!(goal = pgoal)) /* XXX: what was intended here? */
874
				goal = iinfo->i_location.logicalBlockNum + 1;
Linus Torvalds's avatar
Linus Torvalds committed
875 876
		}

Marcin Slusarz's avatar
Marcin Slusarz committed
877
		newblocknum = udf_new_block(inode->i_sb, inode,
878
				iinfo->i_location.partitionReferenceNum,
879 880
				goal, &ret);
		if (!newblocknum)
Fabian Frederick's avatar
Fabian Frederick committed
881
			goto out_free;
882 883
		if (isBeyondEOF)
			iinfo->i_lenExtents += inode->i_sb->s_blocksize;
Linus Torvalds's avatar
Linus Torvalds committed
884 885
	}

Marcin Slusarz's avatar
Marcin Slusarz committed
886 887 888 889
	/* 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 */
Linus Torvalds's avatar
Linus Torvalds committed
890 891
	udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);

892
	if (!(map->iflags & UDF_MAP_NOPREALLOC))
893
		udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
Linus Torvalds's avatar
Linus Torvalds committed
894 895 896 897 898

	/* merge any continuous blocks in laarr */
	udf_merge_extents(inode, laarr, &endnum);

	/* write back the new extents, inserting new extents if the new number
899 900
	 * of extents is greater than the old number, and deleting extents if
	 * the new number of extents is less than the old number */
901 902
	ret = udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
	if (ret < 0)
903
		goto out_free;
Linus Torvalds's avatar
Linus Torvalds committed
904

905
	map->pblk = udf_get_pblock(inode->i_sb, newblocknum,
906
				iinfo->i_location.partitionReferenceNum, 0);
907 908
	if (!map->pblk) {
		ret = -EFSCORRUPTED;
Fabian Frederick's avatar
Fabian Frederick committed
909
		goto out_free;
910
	}
911 912
	map->oflags = UDF_BLK_NEW | UDF_BLK_MAPPED;
	iinfo->i_next_alloc_block = map->lblk + 1;
913
	iinfo->i_next_alloc_goal = newblocknum + 1;
914
	inode->i_ctime = current_time(inode);
Linus Torvalds's avatar
Linus Torvalds committed
915 916 917 918 919

	if (IS_SYNC(inode))
		udf_sync_inode(inode);
	else
		mark_inode_dirty(inode);
920
	ret = 0;
Fabian Frederick's avatar
Fabian Frederick committed
921 922 923 924
out_free:
	brelse(prev_epos.bh);
	brelse(cur_epos.bh);
	brelse(next_epos.bh);
925
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
926 927
}

928
static void udf_split_extents(struct inode *inode, int *c, int offset,
929 930
			       udf_pblk_t newblocknum,
			       struct kernel_long_ad *laarr, int *endnum)
Linus Torvalds's avatar
Linus Torvalds committed
931
{
Marcin Slusarz's avatar
Marcin Slusarz committed
932 933 934
	unsigned long blocksize = inode->i_sb->s_blocksize;
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;

Linus Torvalds's avatar
Linus Torvalds committed
935
	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
Marcin Slusarz's avatar
Marcin Slusarz committed
936 937
	    (laarr[*c].extLength >> 30) ==
				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) {
Linus Torvalds's avatar
Linus Torvalds committed
938 939
		int curr = *c;
		int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
Marcin Slusarz's avatar
Marcin Slusarz committed
940
			    blocksize - 1) >> blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
941 942
		int8_t etype = (laarr[curr].extLength >> 30);

Marcin Slusarz's avatar
Marcin Slusarz committed
943
		if (blen == 1)
944
			;
Marcin Slusarz's avatar
Marcin Slusarz committed
945
		else if (!offset || blen == offset + 1) {
946 947 948 949 950 951 952 953 954
			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)) {
Marcin Slusarz's avatar
Marcin Slusarz committed
955
				udf_free_blocks(inode->i_sb, inode,
956
						&laarr[curr].extLocation,
Marcin Slusarz's avatar
Marcin Slusarz committed
957 958 959 960
						0, offset);
				laarr[curr].extLength =
					EXT_NOT_RECORDED_NOT_ALLOCATED |
					(offset << blocksize_bits);
Linus Torvalds's avatar
Linus Torvalds committed
961
				laarr[curr].extLocation.logicalBlockNum = 0;
Marcin Slusarz's avatar
Marcin Slusarz committed
962 963 964
				laarr[curr].extLocation.
						partitionReferenceNum = 0;
			} else
Linus Torvalds's avatar
Linus Torvalds committed
965
				laarr[curr].extLength = (etype << 30) |
Marcin Slusarz's avatar
Marcin Slusarz committed
966
					(offset << blocksize_bits);
967 968 969
			curr++;
			(*c)++;
			(*endnum)++;
Linus Torvalds's avatar
Linus Torvalds committed
970
		}
971

Linus Torvalds's avatar
Linus Torvalds committed
972 973 974
		laarr[curr].extLocation.logicalBlockNum = newblocknum;
		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
			laarr[curr].extLocation.partitionReferenceNum =
975
				UDF_I(inode)->i_location.partitionReferenceNum;
Linus Torvalds's avatar
Linus Torvalds committed
976
		laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
Marcin Slusarz's avatar
Marcin Slusarz committed
977
			blocksize;
978
		curr++;
Linus Torvalds's avatar
Linus Torvalds committed
979

980
		if (blen != offset + 1) {
Linus Torvalds's avatar
Linus Torvalds committed
981
			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
Marcin Slusarz's avatar
Marcin Slusarz committed
982 983
				laarr[curr].extLocation.logicalBlockNum +=
								offset + 1;
984
			laarr[curr].extLength = (etype << 30) |
Marcin Slusarz's avatar
Marcin Slusarz committed
985
				((blen - (offset + 1)) << blocksize_bits);
986 987
			curr++;
			(*endnum)++;
Linus Torvalds's avatar
Linus Torvalds committed
988 989 990 991 992
		}
	}
}

static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
993
				 struct kernel_long_ad *laarr,
994
				 int *endnum)
Linus Torvalds's avatar
Linus Torvalds committed
995 996 997
{
	int start, length = 0, currlength = 0, i;

998
	if (*endnum >= (c + 1)) {
Linus Torvalds's avatar
Linus Torvalds committed
999 1000 1001 1002
		if (!lastblock)
			return;
		else
			start = c;
1003
	} else {
Marcin Slusarz's avatar
Marcin Slusarz committed
1004 1005
		if ((laarr[c + 1].extLength >> 30) ==
					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
1006
			start = c + 1;
Marcin Slusarz's avatar
Marcin Slusarz committed
1007 1008 1009 1010 1011 1012
			length = currlength =
				(((laarr[c + 1].extLength &
					UDF_EXTENT_LENGTH_MASK) +
				inode->i_sb->s_blocksize - 1) >>
				inode->i_sb->s_blocksize_bits);
		} else
Linus Torvalds's avatar
Linus Torvalds committed
1013 1014 1015
			start = c;
	}

1016 1017
	for (i = start + 1; i <= *endnum; i++) {
		if (i == *endnum) {
Linus Torvalds's avatar
Linus Torvalds committed
1018 1019
			if (lastblock)
				length += UDF_DEFAULT_PREALLOC_BLOCKS;
Marcin Slusarz's avatar
Marcin Slusarz committed
1020 1021 1022 1023 1024 1025 1026
		} 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
Linus Torvalds's avatar
Linus Torvalds committed
1027 1028 1029
			break;
	}

1030
	if (length) {
Linus Torvalds's avatar
Linus Torvalds committed
1031
		int next = laarr[start].extLocation.logicalBlockNum +
1032
			(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
Marcin Slusarz's avatar
Marcin Slusarz committed
1033 1034
			  inode->i_sb->s_blocksize - 1) >>
			  inode->i_sb->s_blocksize_bits);
Linus Torvalds's avatar
Linus Torvalds committed
1035
		int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
Marcin Slusarz's avatar
Marcin Slusarz committed
1036 1037 1038 1039
				laarr[start].extLocation.partitionReferenceNum,
				next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ?
				length : UDF_DEFAULT_PREALLOC_BLOCKS) -
				currlength);
1040
		if (numalloc) 	{
Marcin Slusarz's avatar
Marcin Slusarz committed
1041
			if (start == (c + 1))
Linus Torvalds's avatar
Linus Torvalds committed
1042
				laarr[start].extLength +=
Marcin Slusarz's avatar
Marcin Slusarz committed
1043 1044 1045
					(numalloc <<
					 inode->i_sb->s_blocksize_bits);
			else {
1046
				memmove(&laarr[c + 2], &laarr[c + 1],
1047
					sizeof(struct long_ad) * (*endnum - (c + 1)));
1048 1049 1050
				(*endnum)++;
				laarr[c + 1].extLocation.logicalBlockNum = next;
				laarr[c + 1].extLocation.partitionReferenceNum =
Marcin Slusarz's avatar
Marcin Slusarz committed
1051 1052 1053 1054 1055 1056
					laarr[c].extLocation.
							partitionReferenceNum;
				laarr[c + 1].extLength =
					EXT_NOT_RECORDED_ALLOCATED |
					(numalloc <<
					 inode->i_sb->s_blocksize_bits);
1057
				start = c + 1;
Linus Torvalds's avatar
Linus Torvalds committed
1058 1059
			}

1060
			for (i = start + 1; numalloc && i < *endnum; i++) {
Marcin Slusarz's avatar
Marcin Slusarz committed
1061 1062 1063 1064
				int elen = ((laarr[i].extLength &
						UDF_EXTENT_LENGTH_MASK) +
					    inode->i_sb->s_blocksize - 1) >>
					    inode->i_sb->s_blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
1065

1066
				if (elen > numalloc) {
Linus Torvalds's avatar
Linus Torvalds committed
1067
					laarr[i].extLength -=
Marcin Slusarz's avatar
Marcin Slusarz committed
1068 1069
						(numalloc <<
						 inode->i_sb->s_blocksize_bits);
Linus Torvalds's avatar
Linus Torvalds committed
1070
					numalloc = 0;
1071
				} else {
Linus Torvalds's avatar
Linus Torvalds committed
1072
					numalloc -= elen;
1073
					if (*endnum > (i + 1))
Marcin Slusarz's avatar
Marcin Slusarz committed
1074 1075
						memmove(&laarr[i],
							&laarr[i + 1],
1076
							sizeof(struct long_ad) *
Marcin Slusarz's avatar
Marcin Slusarz committed
1077
							(*endnum - (i + 1)));
1078 1079
					i--;
					(*endnum)--;
Linus Torvalds's avatar
Linus Torvalds committed
1080 1081
				}
			}
1082
			UDF_I(inode)->i_lenExtents +=
Marcin Slusarz's avatar
Marcin Slusarz committed
1083
				numalloc << inode->i_sb->s_blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
1084 1085 1086 1087
		}
	}
}

1088
static void udf_merge_extents(struct inode *inode, struct kernel_long_ad *laarr,
1089
			      int *endnum)
Linus Torvalds's avatar
Linus Torvalds committed
1090 1091
{
	int i;
Marcin Slusarz's avatar
Marcin Slusarz committed
1092 1093
	unsigned long blocksize = inode->i_sb->s_blocksize;
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
1094

1095
	for (i = 0; i < (*endnum - 1); i++) {
1096 1097
		struct kernel_long_ad *li /*l[i]*/ = &laarr[i];
		struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1];
Marcin Slusarz's avatar
Marcin Slusarz committed
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107

		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) +
1108 1109
			     (lip1->extLength & UDF_EXTENT_LENGTH_MASK) +
			     blocksize - 1) <= UDF_EXTENT_LENGTH_MASK) {
Marcin Slusarz's avatar
Marcin Slusarz committed
1110 1111 1112 1113 1114 1115
				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],
1116
						sizeof(struct long_ad) *
Marcin Slusarz's avatar
Marcin Slusarz committed
1117 1118 1119
						(*endnum - (i + 2)));
				i--;
				(*endnum)--;
Linus Torvalds's avatar
Linus Torvalds committed
1120
			}
Marcin Slusarz's avatar
Marcin Slusarz committed
1121 1122 1123 1124
		} else if (((li->extLength >> 30) ==
				(EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
			   ((lip1->extLength >> 30) ==
				(EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) {
1125
			udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0,
Marcin Slusarz's avatar
Marcin Slusarz committed
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
					((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;
1144
			} else {
Marcin Slusarz's avatar
Marcin Slusarz committed
1145 1146 1147 1148
				li->extLength = lip1->extLength +
					(((li->extLength &
						UDF_EXTENT_LENGTH_MASK) +
					  blocksize - 1) & ~(blocksize - 1));
1149 1150
				if (*endnum > (i + 2))
					memmove(&laarr[i + 1], &laarr[i + 2],
1151
						sizeof(struct long_ad) *
Marcin Slusarz's avatar
Marcin Slusarz committed
1152
						(*endnum - (i + 2)));
1153 1154
				i--;
				(*endnum)--;
Linus Torvalds's avatar
Linus Torvalds committed
1155
			}
Marcin Slusarz's avatar
Marcin Slusarz committed
1156 1157 1158
		} else if ((li->extLength >> 30) ==
					(EXT_NOT_RECORDED_ALLOCATED >> 30)) {
			udf_free_blocks(inode->i_sb, inode,
1159
					&li->extLocation, 0,
Marcin Slusarz's avatar
Marcin Slusarz committed
1160 1161 1162 1163 1164 1165 1166 1167
					((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;
Linus Torvalds's avatar
Linus Torvalds committed
1168 1169 1170 1171
		}
	}
}

1172 1173 1174
static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr,
			      int startnum, int endnum,
			      struct extent_position *epos)
Linus Torvalds's avatar
Linus Torvalds committed
1175 1176
{
	int start = 0, i;
1177
	struct kernel_lb_addr tmploc;
Linus Torvalds's avatar
Linus Torvalds committed
1178
	uint32_t tmplen;
1179
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
1180

1181 1182
	if (startnum > endnum) {
		for (i = 0; i < (startnum - endnum); i++)
1183
			udf_delete_aext(inode, *epos);
1184 1185
	} else if (startnum < endnum) {
		for (i = 0; i < (endnum - startnum); i++) {
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
			err = udf_insert_aext(inode, *epos,
					      laarr[i].extLocation,
					      laarr[i].extLength);
			/*
			 * If we fail here, we are likely corrupting the extent
			 * list and leaking blocks. At least stop early to
			 * limit the damage.
			 */
			if (err < 0)
				return err;
1196
			udf_next_aext(inode, epos, &laarr[i].extLocation,
1197 1198
				      &laarr[i].extLength, 1);
			start++;
Linus Torvalds's avatar
Linus Torvalds committed
1199 1200 1201
		}
	}

1202
	for (i = start; i < endnum; i++) {
1203
		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
1204
		udf_write_aext(inode, epos, &laarr[i].extLocation,
1205
			       laarr[i].extLength, 1);
Linus Torvalds's avatar
Linus Torvalds committed
1206
	}
1207
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1208 1209
}

1210
struct buffer_head *udf_bread(struct inode *inode, udf_pblk_t block,
1211
			      int create, int *err)
Linus Torvalds's avatar
Linus Torvalds committed
1212
{
1213
	struct buffer_head *bh = NULL;
1214 1215 1216 1217
	struct udf_map_rq map = {
		.lblk = block,
		.iflags = UDF_MAP_NOPREALLOC | (create ? UDF_MAP_CREATE : 0),
	};
Linus Torvalds's avatar
Linus Torvalds committed
1218

1219 1220 1221 1222 1223 1224 1225
	*err = udf_map_block(inode, &map);
	if (*err || !(map.oflags & UDF_BLK_MAPPED))
		return NULL;

	bh = sb_getblk(inode->i_sb, map.pblk);
	if (!bh) {
		*err = -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
1226
		return NULL;
1227 1228 1229 1230 1231 1232 1233 1234 1235
	}
	if (map.oflags & UDF_BLK_NEW) {
		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;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1236

Zhang Yi's avatar
Zhang Yi committed
1237
	if (bh_read(bh, 0) >= 0)
Linus Torvalds's avatar
Linus Torvalds committed
1238
		return bh;
1239

Linus Torvalds's avatar
Linus Torvalds committed
1240 1241 1242 1243 1244
	brelse(bh);
	*err = -EIO;
	return NULL;
}

1245
int udf_setsize(struct inode *inode, loff_t newsize)
Linus Torvalds's avatar
Linus Torvalds committed
1246
{
1247
	int err = 0;
1248
	struct udf_inode_info *iinfo;
1249
	unsigned int bsize = i_blocksize(inode);
Linus Torvalds's avatar
Linus Torvalds committed
1250 1251

	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1252
	      S_ISLNK(inode->i_mode)))
1253
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
1254
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
1255
		return -EPERM;
Linus Torvalds's avatar
Linus Torvalds committed
1256

1257
	filemap_invalidate_lock(inode->i_mapping);
1258
	iinfo = UDF_I(inode);
1259 1260
	if (newsize > inode->i_size) {
		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
1261
			if (bsize >=
1262
			    (udf_file_entry_alloc_offset(inode) + newsize)) {
1263
				down_write(&iinfo->i_data_sem);
1264
				iinfo->i_lenAlloc = newsize;
1265
				up_write(&iinfo->i_data_sem);
1266 1267
				goto set_size;
			}
1268 1269
			err = udf_expand_file_adinicb(inode);
			if (err)
1270
				goto out_unlock;
1271 1272
		}
		err = udf_extend_file(inode, newsize);
1273
		if (err)
1274
			goto out_unlock;
1275
set_size:
1276
		truncate_setsize(inode, newsize);
1277
	} else {
1278 1279
		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
			down_write(&iinfo->i_data_sem);
1280
			udf_clear_extent_cache(inode);
1281
			memset(iinfo->i_data + iinfo->i_lenEAttr + newsize,
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
			       0x00, bsize - newsize -
			       udf_file_entry_alloc_offset(inode));
			iinfo->i_lenAlloc = newsize;
			truncate_setsize(inode, newsize);
			up_write(&iinfo->i_data_sem);
			goto update_time;
		}
		err = block_truncate_page(inode->i_mapping, newsize,
					  udf_get_block);
		if (err)
1292
			goto out_unlock;
1293
		truncate_setsize(inode, newsize);
1294
		down_write(&iinfo->i_data_sem);
1295
		udf_clear_extent_cache(inode);
1296
		err = udf_truncate_extents(inode);
1297
		up_write(&iinfo->i_data_sem);
1298
		if (err)
1299
			goto out_unlock;
1300
	}
1301
update_time:
1302
	inode->i_mtime = inode->i_ctime = current_time(inode);
Linus Torvalds's avatar
Linus Torvalds committed
1303
	if (IS_SYNC(inode))
1304
		udf_sync_inode(inode);
Linus Torvalds's avatar
Linus Torvalds committed
1305 1306
	else
		mark_inode_dirty(inode);
1307 1308 1309
out_unlock:
	filemap_invalidate_unlock(inode->i_mapping);
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
1310 1311
}

1312 1313 1314 1315 1316 1317 1318
/*
 * Maximum length of linked list formed by ICB hierarchy. The chosen number is
 * arbitrary - just that we hopefully don't limit any real use of rewritten
 * inode on write-once media but avoid looping for too long on corrupted media.
 */
#define UDF_MAX_ICB_NESTING 1024

1319
static int udf_read_inode(struct inode *inode, bool hidden_inode)
Linus Torvalds's avatar
Linus Torvalds committed
1320 1321 1322
{
	struct buffer_head *bh = NULL;
	struct fileEntry *fe;
1323
	struct extendedFileEntry *efe;
Linus Torvalds's avatar
Linus Torvalds committed
1324
	uint16_t ident;
1325
	struct udf_inode_info *iinfo = UDF_I(inode);
1326
	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
1327
	struct kernel_lb_addr *iloc = &iinfo->i_location;
1328
	unsigned int link_count;
1329
	unsigned int indirections = 0;
1330
	int bs = inode->i_sb->s_blocksize;
1331
	int ret = -EIO;
1332
	uint32_t uid, gid;
Linus Torvalds's avatar
Linus Torvalds committed
1333

1334
reread:
1335
	if (iloc->partitionReferenceNum >= sbi->s_partitions) {
1336
		udf_debug("partition reference: %u > logical volume partitions: %u\n",
1337 1338 1339 1340
			  iloc->partitionReferenceNum, sbi->s_partitions);
		return -EIO;
	}

1341 1342
	if (iloc->logicalBlockNum >=
	    sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
1343
		udf_debug("block=%u, partition=%u out of range\n",
1344 1345 1346 1347
			  iloc->logicalBlockNum, iloc->partitionReferenceNum);
		return -EIO;
	}

Linus Torvalds's avatar
Linus Torvalds committed
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
	/*
	 * 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;
	 */
1360
	bh = udf_read_ptagged(inode->i_sb, iloc, 0, &ident);
1361
	if (!bh) {
1362
		udf_err(inode->i_sb, "(ino %lu) failed !bh\n", inode->i_ino);
1363
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
1364 1365 1366
	}

	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
1367
	    ident != TAG_IDENT_USE) {
1368
		udf_err(inode->i_sb, "(ino %lu) failed ident=%u\n",
1369
			inode->i_ino, ident);
1370
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1371 1372 1373
	}

	fe = (struct fileEntry *)bh->b_data;
1374
	efe = (struct extendedFileEntry *)bh->b_data;
Linus Torvalds's avatar
Linus Torvalds committed
1375

1376
	if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
1377
		struct buffer_head *ibh;
Linus Torvalds's avatar
Linus Torvalds committed
1378

1379
		ibh = udf_read_ptagged(inode->i_sb, iloc, 1, &ident);
1380
		if (ident == TAG_IDENT_IE && ibh) {
1381
			struct kernel_lb_addr loc;
1382 1383 1384 1385 1386
			struct indirectEntry *ie;

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

1387 1388 1389 1390 1391 1392 1393 1394 1395
			if (ie->indirectICB.extLength) {
				brelse(ibh);
				memcpy(&iinfo->i_location, &loc,
				       sizeof(struct kernel_lb_addr));
				if (++indirections > UDF_MAX_ICB_NESTING) {
					udf_err(inode->i_sb,
						"too many ICBs in ICB hierarchy"
						" (max %d supported)\n",
						UDF_MAX_ICB_NESTING);
1396
					goto out;
1397
				}
1398
				brelse(bh);
1399
				goto reread;
Linus Torvalds's avatar
Linus Torvalds committed
1400
			}
1401
		}
1402
		brelse(ibh);
1403
	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
1404
		udf_err(inode->i_sb, "unsupported strategy type: %u\n",
1405
			le16_to_cpu(fe->icbTag.strategyType));
1406
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1407
	}
1408
	if (fe->icbTag.strategyType == cpu_to_le16(4))
1409
		iinfo->i_strat4096 = 0;
1410
	else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */
1411
		iinfo->i_strat4096 = 1;
Linus Torvalds's avatar
Linus Torvalds committed
1412

1413
	iinfo->i_alloc_type = le16_to_cpu(fe->icbTag.flags) &
Marcin Slusarz's avatar
Marcin Slusarz committed
1414
							ICBTAG_FLAG_AD_MASK;
Jan Kara's avatar
Jan Kara committed
1415 1416 1417 1418 1419 1420
	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_SHORT &&
	    iinfo->i_alloc_type != ICBTAG_FLAG_AD_LONG &&
	    iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
		ret = -EIO;
		goto out;
	}
1421
	iinfo->i_hidden = hidden_inode;
1422 1423 1424 1425 1426 1427
	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;
1428
	if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
1429 1430
		iinfo->i_efe = 1;
		iinfo->i_use = 0;
1431
		ret = udf_alloc_i_data(inode, bs -
1432 1433 1434
					sizeof(struct extendedFileEntry));
		if (ret)
			goto out;
1435
		memcpy(iinfo->i_data,
Marcin Slusarz's avatar
Marcin Slusarz committed
1436
		       bh->b_data + sizeof(struct extendedFileEntry),
1437
		       bs - sizeof(struct extendedFileEntry));
1438
	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
1439 1440
		iinfo->i_efe = 0;
		iinfo->i_use = 0;
1441
		ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry));
1442 1443
		if (ret)
			goto out;
1444
		memcpy(iinfo->i_data,
1445
		       bh->b_data + sizeof(struct fileEntry),
1446
		       bs - sizeof(struct fileEntry));
1447
	} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
1448 1449 1450
		iinfo->i_efe = 0;
		iinfo->i_use = 1;
		iinfo->i_lenAlloc = le32_to_cpu(
Marcin Slusarz's avatar
Marcin Slusarz committed
1451 1452
				((struct unallocSpaceEntry *)bh->b_data)->
				 lengthAllocDescs);
1453
		ret = udf_alloc_i_data(inode, bs -
1454 1455 1456
					sizeof(struct unallocSpaceEntry));
		if (ret)
			goto out;
1457
		memcpy(iinfo->i_data,
Marcin Slusarz's avatar
Marcin Slusarz committed
1458
		       bh->b_data + sizeof(struct unallocSpaceEntry),
1459
		       bs - sizeof(struct unallocSpaceEntry));
1460
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1461 1462
	}

1463
	ret = -EIO;
1464
	read_lock(&sbi->s_cred_lock);
1465 1466
	uid = le32_to_cpu(fe->uid);
	if (uid == UDF_INVALID_ID ||
1467
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))
1468 1469 1470
		inode->i_uid = sbi->s_uid;
	else
		i_uid_write(inode, uid);
Linus Torvalds's avatar
Linus Torvalds committed
1471

1472 1473
	gid = le32_to_cpu(fe->gid);
	if (gid == UDF_INVALID_ID ||
1474
	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
1475 1476 1477
		inode->i_gid = sbi->s_gid;
	else
		i_gid_write(inode, gid);
Linus Torvalds's avatar
Linus Torvalds committed
1478

1479
	if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&
1480
			sbi->s_fmode != UDF_INVALID_MODE)
1481 1482
		inode->i_mode = sbi->s_fmode;
	else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY &&
1483
			sbi->s_dmode != UDF_INVALID_MODE)
1484 1485 1486 1487
		inode->i_mode = sbi->s_dmode;
	else
		inode->i_mode = udf_convert_permissions(fe);
	inode->i_mode &= ~sbi->s_umask;
1488 1489
	iinfo->i_extraPerms = le32_to_cpu(fe->permissions) & ~FE_MAPPED_PERMS;

1490 1491
	read_unlock(&sbi->s_cred_lock);

1492
	link_count = le16_to_cpu(fe->fileLinkCount);
Jan Kara's avatar
Jan Kara committed
1493
	if (!link_count) {
1494 1495 1496 1497 1498
		if (!hidden_inode) {
			ret = -ESTALE;
			goto out;
		}
		link_count = 1;
Jan Kara's avatar
Jan Kara committed
1499
	}
1500
	set_nlink(inode, link_count);
1501 1502 1503

	inode->i_size = le64_to_cpu(fe->informationLength);
	iinfo->i_lenExtents = inode->i_size;
Linus Torvalds's avatar
Linus Torvalds committed
1504

1505
	if (iinfo->i_efe == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
1506
		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
1507
			(inode->i_sb->s_blocksize_bits - 9);
Linus Torvalds's avatar
Linus Torvalds committed
1508

1509 1510 1511
		udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime);
		udf_disk_stamp_to_time(&inode->i_mtime, fe->modificationTime);
		udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime);
Linus Torvalds's avatar
Linus Torvalds committed
1512

1513 1514 1515
		iinfo->i_unique = le64_to_cpu(fe->uniqueID);
		iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
		iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs);
1516
		iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint);
1517 1518
		iinfo->i_streamdir = 0;
		iinfo->i_lenStreams = 0;
1519
	} else {
1520
		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
1521
		    (inode->i_sb->s_blocksize_bits - 9);
Linus Torvalds's avatar
Linus Torvalds committed
1522

1523 1524
		udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime);
		udf_disk_stamp_to_time(&inode->i_mtime, efe->modificationTime);
1525
		udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime);
1526
		udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime);
Linus Torvalds's avatar
Linus Torvalds committed
1527

1528 1529 1530
		iinfo->i_unique = le64_to_cpu(efe->uniqueID);
		iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
		iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
1531
		iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541

		/* Named streams */
		iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0);
		iinfo->i_locStreamdir =
			lelb_to_cpu(efe->streamDirectoryICB.extLocation);
		iinfo->i_lenStreams = le64_to_cpu(efe->objectSize);
		if (iinfo->i_lenStreams >= inode->i_size)
			iinfo->i_lenStreams -= inode->i_size;
		else
			iinfo->i_lenStreams = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1542
	}
Jan Kara's avatar
Jan Kara committed
1543
	inode->i_generation = iinfo->i_unique;
Linus Torvalds's avatar
Linus Torvalds committed
1544

1545 1546 1547 1548 1549 1550 1551 1552 1553
	/*
	 * Sanity check length of allocation descriptors and extended attrs to
	 * avoid integer overflows
	 */
	if (iinfo->i_lenEAttr > bs || iinfo->i_lenAlloc > bs)
		goto out;
	/* Now do exact checks */
	if (udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc > bs)
		goto out;
1554 1555 1556 1557 1558 1559 1560 1561 1562
	/* Sanity checks for files in ICB so that we don't get confused later */
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		/*
		 * For file in ICB data is stored in allocation descriptor
		 * so sizes should match
		 */
		if (iinfo->i_lenAlloc != inode->i_size)
			goto out;
		/* File in ICB has to fit in there... */
1563
		if (inode->i_size > bs - udf_file_entry_alloc_offset(inode))
1564 1565 1566
			goto out;
	}

1567 1568
	switch (fe->icbTag.fileType) {
	case ICBTAG_FILE_TYPE_DIRECTORY:
1569 1570 1571 1572 1573
		inode->i_op = &udf_dir_inode_operations;
		inode->i_fop = &udf_dir_operations;
		inode->i_mode |= S_IFDIR;
		inc_nlink(inode);
		break;
1574 1575 1576
	case ICBTAG_FILE_TYPE_REALTIME:
	case ICBTAG_FILE_TYPE_REGULAR:
	case ICBTAG_FILE_TYPE_UNDEF:
Jan Kara's avatar
Jan Kara committed
1577
	case ICBTAG_FILE_TYPE_VAT20:
1578
		inode->i_data.a_ops = &udf_aops;
1579 1580 1581 1582
		inode->i_op = &udf_file_inode_operations;
		inode->i_fop = &udf_file_operations;
		inode->i_mode |= S_IFREG;
		break;
1583
	case ICBTAG_FILE_TYPE_BLOCK:
1584 1585
		inode->i_mode |= S_IFBLK;
		break;
1586
	case ICBTAG_FILE_TYPE_CHAR:
1587 1588
		inode->i_mode |= S_IFCHR;
		break;
1589
	case ICBTAG_FILE_TYPE_FIFO:
1590 1591
		init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
		break;
1592
	case ICBTAG_FILE_TYPE_SOCKET:
1593 1594
		init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
		break;
1595
	case ICBTAG_FILE_TYPE_SYMLINK:
1596
		inode->i_data.a_ops = &udf_symlink_aops;
1597
		inode->i_op = &udf_symlink_inode_operations;
1598
		inode_nohighmem(inode);
1599
		inode->i_mode = S_IFLNK | 0777;
1600
		break;
1601 1602 1603 1604 1605 1606 1607 1608 1609
	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;
1610
	default:
1611
		udf_err(inode->i_sb, "(ino %lu) failed unknown file type=%u\n",
1612
			inode->i_ino, fe->icbTag.fileType);
1613
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1614
	}
1615
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
Marcin Slusarz's avatar
Marcin Slusarz committed
1616 1617
		struct deviceSpec *dsea =
			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
1618 1619
		if (dsea) {
			init_special_inode(inode, inode->i_mode,
Marcin Slusarz's avatar
Marcin Slusarz committed
1620 1621
				MKDEV(le32_to_cpu(dsea->majorDeviceIdent),
				      le32_to_cpu(dsea->minorDeviceIdent)));
Linus Torvalds's avatar
Linus Torvalds committed
1622
			/* Developer ID ??? */
Marcin Slusarz's avatar
Marcin Slusarz committed
1623
		} else
1624
			goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1625
	}
1626 1627
	ret = 0;
out:
1628
	brelse(bh);
1629
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1630 1631
}

1632 1633
static int udf_alloc_i_data(struct inode *inode, size_t size)
{
1634
	struct udf_inode_info *iinfo = UDF_I(inode);
1635 1636
	iinfo->i_data = kmalloc(size, GFP_KERNEL);
	if (!iinfo->i_data)
1637 1638 1639 1640
		return -ENOMEM;
	return 0;
}

Al Viro's avatar
Al Viro committed
1641
static umode_t udf_convert_permissions(struct fileEntry *fe)
Linus Torvalds's avatar
Linus Torvalds committed
1642
{
Al Viro's avatar
Al Viro committed
1643
	umode_t mode;
Linus Torvalds's avatar
Linus Torvalds committed
1644 1645 1646 1647 1648 1649
	uint32_t permissions;
	uint32_t flags;

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

1650 1651 1652
	mode =	((permissions) & 0007) |
		((permissions >> 2) & 0070) |
		((permissions >> 4) & 0700) |
Marcin Slusarz's avatar
Marcin Slusarz committed
1653 1654 1655
		((flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) |
		((flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) |
		((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0);
Linus Torvalds's avatar
Linus Torvalds committed
1656 1657 1658 1659

	return mode;
}

1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676
void udf_update_extra_perms(struct inode *inode, umode_t mode)
{
	struct udf_inode_info *iinfo = UDF_I(inode);

	/*
	 * UDF 2.01 sec. 3.3.3.3 Note 2:
	 * In Unix, delete permission tracks write
	 */
	iinfo->i_extraPerms &= ~FE_DELETE_PERMS;
	if (mode & 0200)
		iinfo->i_extraPerms |= FE_PERM_U_DELETE;
	if (mode & 0020)
		iinfo->i_extraPerms |= FE_PERM_G_DELETE;
	if (mode & 0002)
		iinfo->i_extraPerms |= FE_PERM_O_DELETE;
}

1677
int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
Linus Torvalds's avatar
Linus Torvalds committed
1678
{
1679
	return udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
Linus Torvalds's avatar
Linus Torvalds committed
1680 1681
}

1682
static int udf_sync_inode(struct inode *inode)
Linus Torvalds's avatar
Linus Torvalds committed
1683 1684 1685 1686
{
	return udf_update_inode(inode, 1);
}

1687
static void udf_adjust_time(struct udf_inode_info *iinfo, struct timespec64 time)
1688 1689 1690 1691 1692 1693 1694
{
	if (iinfo->i_crtime.tv_sec > time.tv_sec ||
	    (iinfo->i_crtime.tv_sec == time.tv_sec &&
	     iinfo->i_crtime.tv_nsec > time.tv_nsec))
		iinfo->i_crtime = time;
}

1695
static int udf_update_inode(struct inode *inode, int do_sync)
Linus Torvalds's avatar
Linus Torvalds committed
1696 1697 1698 1699
{
	struct buffer_head *bh = NULL;
	struct fileEntry *fe;
	struct extendedFileEntry *efe;
1700
	uint64_t lb_recorded;
Linus Torvalds's avatar
Linus Torvalds committed
1701 1702 1703 1704
	uint32_t udfperms;
	uint16_t icbflags;
	uint16_t crclen;
	int err = 0;
1705
	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
Marcin Slusarz's avatar
Marcin Slusarz committed
1706
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
1707
	struct udf_inode_info *iinfo = UDF_I(inode);
Linus Torvalds's avatar
Linus Torvalds committed
1708

Jan Kara's avatar
Jan Kara committed
1709
	bh = sb_getblk(inode->i_sb,
1710
			udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
1711
	if (!bh) {
1712
		udf_debug("getblk failure\n");
1713
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
1714 1715
	}

1716 1717
	lock_buffer(bh);
	memset(bh->b_data, 0, inode->i_sb->s_blocksize);
Linus Torvalds's avatar
Linus Torvalds committed
1718 1719 1720
	fe = (struct fileEntry *)bh->b_data;
	efe = (struct extendedFileEntry *)bh->b_data;

1721
	if (iinfo->i_use) {
Linus Torvalds's avatar
Linus Torvalds committed
1722
		struct unallocSpaceEntry *use =
1723
			(struct unallocSpaceEntry *)bh->b_data;
Linus Torvalds's avatar
Linus Torvalds committed
1724

1725
		use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
Marcin Slusarz's avatar
Marcin Slusarz committed
1726
		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
1727
		       iinfo->i_data, inode->i_sb->s_blocksize -
Marcin Slusarz's avatar
Marcin Slusarz committed
1728
					sizeof(struct unallocSpaceEntry));
1729
		use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
1730
		crclen = sizeof(struct unallocSpaceEntry);
Linus Torvalds's avatar
Linus Torvalds committed
1731

1732
		goto finish;
Linus Torvalds's avatar
Linus Torvalds committed
1733 1734
	}

1735
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
1736
		fe->uid = cpu_to_le32(UDF_INVALID_ID);
1737
	else
1738
		fe->uid = cpu_to_le32(i_uid_read(inode));
Linus Torvalds's avatar
Linus Torvalds committed
1739

1740
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
1741
		fe->gid = cpu_to_le32(UDF_INVALID_ID);
1742
	else
1743
		fe->gid = cpu_to_le32(i_gid_read(inode));
Linus Torvalds's avatar
Linus Torvalds committed
1744

1745 1746 1747
	udfperms = ((inode->i_mode & 0007)) |
		   ((inode->i_mode & 0070) << 2) |
		   ((inode->i_mode & 0700) << 4);
Linus Torvalds's avatar
Linus Torvalds committed
1748

1749
	udfperms |= iinfo->i_extraPerms;
Linus Torvalds's avatar
Linus Torvalds committed
1750 1751
	fe->permissions = cpu_to_le32(udfperms);

1752
	if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0)
Linus Torvalds's avatar
Linus Torvalds committed
1753
		fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
1754 1755 1756 1757 1758 1759
	else {
		if (iinfo->i_hidden)
			fe->fileLinkCount = cpu_to_le16(0);
		else
			fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1760 1761 1762

	fe->informationLength = cpu_to_le64(inode->i_size);

1763
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
1764
		struct regid *eid;
1765 1766
		struct deviceSpec *dsea =
			(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
1767
		if (!dsea) {
Linus Torvalds's avatar
Linus Torvalds committed
1768
			dsea = (struct deviceSpec *)
1769 1770
				udf_add_extendedattr(inode,
						     sizeof(struct deviceSpec) +
1771
						     sizeof(struct regid), 12, 0x3);
Linus Torvalds's avatar
Linus Torvalds committed
1772 1773
			dsea->attrType = cpu_to_le32(12);
			dsea->attrSubtype = 1;
Marcin Slusarz's avatar
Marcin Slusarz committed
1774 1775
			dsea->attrLength = cpu_to_le32(
						sizeof(struct deviceSpec) +
1776 1777
						sizeof(struct regid));
			dsea->impUseLength = cpu_to_le32(sizeof(struct regid));
Linus Torvalds's avatar
Linus Torvalds committed
1778
		}
1779
		eid = (struct regid *)dsea->impUse;
1780
		memset(eid, 0, sizeof(*eid));
Linus Torvalds's avatar
Linus Torvalds committed
1781 1782 1783 1784 1785 1786 1787
		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));
	}

1788 1789 1790 1791 1792 1793 1794
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
		lb_recorded = 0; /* No extents => no blocks! */
	else
		lb_recorded =
			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
			(blocksize_bits - 9);

1795
	if (iinfo->i_efe == 0) {
1796
		memcpy(bh->b_data + sizeof(struct fileEntry),
1797
		       iinfo->i_data,
1798
		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
1799
		fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
Linus Torvalds's avatar
Linus Torvalds committed
1800

1801 1802 1803
		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);
1804
		memset(&(fe->impIdent), 0, sizeof(struct regid));
Linus Torvalds's avatar
Linus Torvalds committed
1805 1806 1807
		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1808 1809 1810
		fe->uniqueID = cpu_to_le64(iinfo->i_unique);
		fe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
		fe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
1811
		fe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);
Linus Torvalds's avatar
Linus Torvalds committed
1812 1813
		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
		crclen = sizeof(struct fileEntry);
1814
	} else {
Marcin Slusarz's avatar
Marcin Slusarz committed
1815
		memcpy(bh->b_data + sizeof(struct extendedFileEntry),
1816
		       iinfo->i_data,
Marcin Slusarz's avatar
Marcin Slusarz committed
1817 1818
		       inode->i_sb->s_blocksize -
					sizeof(struct extendedFileEntry));
1819 1820
		efe->objectSize =
			cpu_to_le64(inode->i_size + iinfo->i_lenStreams);
1821
		efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
Linus Torvalds's avatar
Linus Torvalds committed
1822

1823 1824 1825 1826 1827 1828 1829 1830 1831
		if (iinfo->i_streamdir) {
			struct long_ad *icb_lad = &efe->streamDirectoryICB;

			icb_lad->extLocation =
				cpu_to_lelb(iinfo->i_locStreamdir);
			icb_lad->extLength =
				cpu_to_le32(inode->i_sb->s_blocksize);
		}

1832 1833 1834
		udf_adjust_time(iinfo, inode->i_atime);
		udf_adjust_time(iinfo, inode->i_mtime);
		udf_adjust_time(iinfo, inode->i_ctime);
Linus Torvalds's avatar
Linus Torvalds committed
1835

1836 1837
		udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
		udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
1838
		udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
1839
		udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
Linus Torvalds's avatar
Linus Torvalds committed
1840

1841
		memset(&(efe->impIdent), 0, sizeof(efe->impIdent));
Linus Torvalds's avatar
Linus Torvalds committed
1842 1843 1844
		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
1845 1846 1847
		efe->uniqueID = cpu_to_le64(iinfo->i_unique);
		efe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);
		efe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
1848
		efe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);
Linus Torvalds's avatar
Linus Torvalds committed
1849 1850 1851
		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
		crclen = sizeof(struct extendedFileEntry);
	}
1852 1853

finish:
1854
	if (iinfo->i_strat4096) {
Linus Torvalds's avatar
Linus Torvalds committed
1855 1856 1857
		fe->icbTag.strategyType = cpu_to_le16(4096);
		fe->icbTag.strategyParameter = cpu_to_le16(1);
		fe->icbTag.numEntries = cpu_to_le16(2);
1858
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
1859 1860 1861 1862
		fe->icbTag.strategyType = cpu_to_le16(4);
		fe->icbTag.numEntries = cpu_to_le16(1);
	}

1863 1864 1865
	if (iinfo->i_use)
		fe->icbTag.fileType = ICBTAG_FILE_TYPE_USE;
	else if (S_ISDIR(inode->i_mode))
Linus Torvalds's avatar
Linus Torvalds committed
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
		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;

1880
	icbflags =	iinfo->i_alloc_type |
1881 1882 1883 1884 1885 1886
			((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));
Linus Torvalds's avatar
Linus Torvalds committed
1887 1888

	fe->icbTag.flags = cpu_to_le16(icbflags);
1889
	if (sbi->s_udfrev >= 0x0200)
Linus Torvalds's avatar
Linus Torvalds committed
1890 1891 1892
		fe->descTag.descVersion = cpu_to_le16(3);
	else
		fe->descTag.descVersion = cpu_to_le16(2);
1893
	fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
Marcin Slusarz's avatar
Marcin Slusarz committed
1894
	fe->descTag.tagLocation = cpu_to_le32(
1895
					iinfo->i_location.logicalBlockNum);
1896
	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
Linus Torvalds's avatar
Linus Torvalds committed
1897
	fe->descTag.descCRCLength = cpu_to_le16(crclen);
1898
	fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
1899
						  crclen));
1900
	fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
Linus Torvalds's avatar
Linus Torvalds committed
1901

1902
	set_buffer_uptodate(bh);
1903 1904
	unlock_buffer(bh);

Linus Torvalds's avatar
Linus Torvalds committed
1905 1906
	/* write the data blocks */
	mark_buffer_dirty(bh);
1907
	if (do_sync) {
Linus Torvalds's avatar
Linus Torvalds committed
1908
		sync_dirty_buffer(bh);
1909
		if (buffer_write_io_error(bh)) {
1910 1911
			udf_warn(inode->i_sb, "IO error syncing udf inode [%08lx]\n",
				 inode->i_ino);
Linus Torvalds's avatar
Linus Torvalds committed
1912 1913 1914
			err = -EIO;
		}
	}
Jan Kara's avatar
Jan Kara committed
1915
	brelse(bh);
1916

Linus Torvalds's avatar
Linus Torvalds committed
1917 1918 1919
	return err;
}

1920 1921
struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
			 bool hidden_inode)
Linus Torvalds's avatar
Linus Torvalds committed
1922 1923 1924
{
	unsigned long block = udf_get_lb_pblock(sb, ino, 0);
	struct inode *inode = iget_locked(sb, block);
1925
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
1926 1927

	if (!inode)
1928
		return ERR_PTR(-ENOMEM);
Linus Torvalds's avatar
Linus Torvalds committed
1929

1930 1931 1932 1933 1934
	if (!(inode->i_state & I_NEW)) {
		if (UDF_I(inode)->i_hidden != hidden_inode) {
			iput(inode);
			return ERR_PTR(-EFSCORRUPTED);
		}
1935
		return inode;
1936
	}
Linus Torvalds's avatar
Linus Torvalds committed
1937

1938
	memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
1939
	err = udf_read_inode(inode, hidden_inode);
1940 1941 1942
	if (err < 0) {
		iget_failed(inode);
		return ERR_PTR(err);
Linus Torvalds's avatar
Linus Torvalds committed
1943
	}
1944
	unlock_new_inode(inode);
Linus Torvalds's avatar
Linus Torvalds committed
1945 1946 1947 1948

	return inode;
}

1949
int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
1950
			    struct extent_position *epos)
Linus Torvalds's avatar
Linus Torvalds committed
1951
{
1952 1953
	struct super_block *sb = inode->i_sb;
	struct buffer_head *bh;
Linus Torvalds's avatar
Linus Torvalds committed
1954
	struct allocExtDesc *aed;
1955 1956 1957
	struct extent_position nepos;
	struct kernel_lb_addr neloc;
	int ver, adsize;
Linus Torvalds's avatar
Linus Torvalds committed
1958

1959 1960 1961 1962
	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		adsize = sizeof(struct short_ad);
	else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
		adsize = sizeof(struct long_ad);
Linus Torvalds's avatar
Linus Torvalds committed
1963
	else
1964
		return -EIO;
1965 1966 1967 1968

	neloc.logicalBlockNum = block;
	neloc.partitionReferenceNum = epos->block.partitionReferenceNum;

Jan Kara's avatar
Jan Kara committed
1969
	bh = sb_getblk(sb, udf_get_lb_pblock(sb, &neloc, 0));
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
	if (!bh)
		return -EIO;
	lock_buffer(bh);
	memset(bh->b_data, 0x00, sb->s_blocksize);
	set_buffer_uptodate(bh);
	unlock_buffer(bh);
	mark_buffer_dirty_inode(bh, inode);

	aed = (struct allocExtDesc *)(bh->b_data);
	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) {
		aed->previousAllocExtLocation =
				cpu_to_le32(epos->block.logicalBlockNum);
	}
	aed->lengthAllocDescs = cpu_to_le32(0);
	if (UDF_SB(sb)->s_udfrev >= 0x0200)
		ver = 3;
Linus Torvalds's avatar
Linus Torvalds committed
1986
	else
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
		ver = 2;
	udf_new_tag(bh->b_data, TAG_IDENT_AED, ver, 1, block,
		    sizeof(struct tag));

	nepos.block = neloc;
	nepos.offset = sizeof(struct allocExtDesc);
	nepos.bh = bh;

	/*
	 * Do we have to copy current last extent to make space for indirect
	 * one?
	 */
	if (epos->offset + adsize > sb->s_blocksize) {
		struct kernel_lb_addr cp_loc;
		uint32_t cp_len;
		int cp_type;

		epos->offset -= adsize;
		cp_type = udf_current_aext(inode, epos, &cp_loc, &cp_len, 0);
		cp_len |= ((uint32_t)cp_type) << 30;

		__udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1);
		udf_write_aext(inode, epos, &nepos.block,
2010
			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0);
2011 2012
	} else {
		__udf_add_aext(inode, epos, &nepos.block,
2013
			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0);
2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
	}

	brelse(epos->bh);
	*epos = nepos;

	return 0;
}

/*
 * Append extent at the given position - should be the first free one in inode
 * / indirect extent. This function assumes there is enough space in the inode
 * or indirect extent. Use udf_add_aext() if you didn't check for this before.
 */
int __udf_add_aext(struct inode *inode, struct extent_position *epos,
		   struct kernel_lb_addr *eloc, uint32_t elen, int inc)
{
	struct udf_inode_info *iinfo = UDF_I(inode);
	struct allocExtDesc *aed;
	int adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2033

2034
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
2035
		adsize = sizeof(struct short_ad);
2036
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
2037
		adsize = sizeof(struct long_ad);
Linus Torvalds's avatar
Linus Torvalds committed
2038
	else
2039
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
2040

2041 2042 2043 2044 2045 2046 2047 2048
	if (!epos->bh) {
		WARN_ON(iinfo->i_lenAlloc !=
			epos->offset - udf_file_entry_alloc_offset(inode));
	} else {
		aed = (struct allocExtDesc *)epos->bh->b_data;
		WARN_ON(le32_to_cpu(aed->lengthAllocDescs) !=
			epos->offset - sizeof(struct allocExtDesc));
		WARN_ON(epos->offset + adsize > inode->i_sb->s_blocksize);
Linus Torvalds's avatar
Linus Torvalds committed
2049 2050
	}

2051
	udf_write_aext(inode, epos, eloc, elen, inc);
Linus Torvalds's avatar
Linus Torvalds committed
2052

2053
	if (!epos->bh) {
2054
		iinfo->i_lenAlloc += adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2055
		mark_inode_dirty(inode);
2056
	} else {
2057
		aed = (struct allocExtDesc *)epos->bh->b_data;
2058
		le32_add_cpu(&aed->lengthAllocDescs, adsize);
Marcin Slusarz's avatar
Marcin Slusarz committed
2059 2060 2061 2062
		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));
Linus Torvalds's avatar
Linus Torvalds committed
2063
		else
Marcin Slusarz's avatar
Marcin Slusarz committed
2064 2065
			udf_update_tag(epos->bh->b_data,
					sizeof(struct allocExtDesc));
2066
		mark_buffer_dirty_inode(epos->bh, inode);
Linus Torvalds's avatar
Linus Torvalds committed
2067 2068
	}

2069
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
2070 2071
}

2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
/*
 * Append extent at given position - should be the first free one in inode
 * / indirect extent. Takes care of allocating and linking indirect blocks.
 */
int udf_add_aext(struct inode *inode, struct extent_position *epos,
		 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
{
	int adsize;
	struct super_block *sb = inode->i_sb;

	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
		adsize = sizeof(struct short_ad);
	else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
		adsize = sizeof(struct long_ad);
	else
		return -EIO;

	if (epos->offset + (2 * adsize) > sb->s_blocksize) {
		int err;
2091
		udf_pblk_t new_block;
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106

		new_block = udf_new_block(sb, NULL,
					  epos->block.partitionReferenceNum,
					  epos->block.logicalBlockNum, &err);
		if (!new_block)
			return -ENOSPC;

		err = udf_setup_indirect_aext(inode, new_block, epos);
		if (err)
			return err;
	}

	return __udf_add_aext(inode, epos, eloc, elen, inc);
}

2107 2108
void udf_write_aext(struct inode *inode, struct extent_position *epos,
		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
Linus Torvalds's avatar
Linus Torvalds committed
2109 2110 2111
{
	int adsize;
	uint8_t *ptr;
2112 2113
	struct short_ad *sad;
	struct long_ad *lad;
2114
	struct udf_inode_info *iinfo = UDF_I(inode);
Linus Torvalds's avatar
Linus Torvalds committed
2115

2116
	if (!epos->bh)
2117
		ptr = iinfo->i_data + epos->offset -
Marcin Slusarz's avatar
Marcin Slusarz committed
2118
			udf_file_entry_alloc_offset(inode) +
2119
			iinfo->i_lenEAttr;
Linus Torvalds's avatar
Linus Torvalds committed
2120
	else
2121
		ptr = epos->bh->b_data + epos->offset;
Linus Torvalds's avatar
Linus Torvalds committed
2122

2123
	switch (iinfo->i_alloc_type) {
2124
	case ICBTAG_FLAG_AD_SHORT:
2125
		sad = (struct short_ad *)ptr;
2126
		sad->extLength = cpu_to_le32(elen);
2127
		sad->extPosition = cpu_to_le32(eloc->logicalBlockNum);
2128
		adsize = sizeof(struct short_ad);
2129
		break;
2130
	case ICBTAG_FLAG_AD_LONG:
2131
		lad = (struct long_ad *)ptr;
2132
		lad->extLength = cpu_to_le32(elen);
2133
		lad->extLocation = cpu_to_lelb(*eloc);
2134
		memset(lad->impUse, 0x00, sizeof(lad->impUse));
2135
		adsize = sizeof(struct long_ad);
2136
		break;
2137
	default:
2138
		return;
Linus Torvalds's avatar
Linus Torvalds committed
2139 2140
	}

2141
	if (epos->bh) {
2142
		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
2143
		    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) {
Marcin Slusarz's avatar
Marcin Slusarz committed
2144 2145
			struct allocExtDesc *aed =
				(struct allocExtDesc *)epos->bh->b_data;
2146
			udf_update_tag(epos->bh->b_data,
Marcin Slusarz's avatar
Marcin Slusarz committed
2147 2148
				       le32_to_cpu(aed->lengthAllocDescs) +
				       sizeof(struct allocExtDesc));
Linus Torvalds's avatar
Linus Torvalds committed
2149
		}
2150
		mark_buffer_dirty_inode(epos->bh, inode);
2151
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
2152
		mark_inode_dirty(inode);
2153
	}
Linus Torvalds's avatar
Linus Torvalds committed
2154 2155

	if (inc)
2156
		epos->offset += adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2157 2158
}

2159 2160 2161 2162 2163 2164
/*
 * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
 * someone does some weird stuff.
 */
#define UDF_MAX_INDIR_EXTS 16

Marcin Slusarz's avatar
Marcin Slusarz committed
2165
int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
2166
		     struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
Linus Torvalds's avatar
Linus Torvalds committed
2167 2168
{
	int8_t etype;
2169
	unsigned int indirections = 0;
Linus Torvalds's avatar
Linus Torvalds committed
2170

2171
	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
2172
	       (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
2173
		udf_pblk_t block;
2174 2175 2176 2177 2178 2179 2180 2181

		if (++indirections > UDF_MAX_INDIR_EXTS) {
			udf_err(inode->i_sb,
				"too many indirect extents in inode %lu\n",
				inode->i_ino);
			return -1;
		}

2182 2183
		epos->block = *eloc;
		epos->offset = sizeof(struct allocExtDesc);
Jan Kara's avatar
Jan Kara committed
2184
		brelse(epos->bh);
2185
		block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0);
Jan Kara's avatar
Jan Kara committed
2186
		epos->bh = sb_bread(inode->i_sb, block);
Marcin Slusarz's avatar
Marcin Slusarz committed
2187
		if (!epos->bh) {
2188
			udf_debug("reading block %u failed!\n", block);
Linus Torvalds's avatar
Linus Torvalds committed
2189 2190 2191 2192 2193 2194 2195
			return -1;
		}
	}

	return etype;
}

Marcin Slusarz's avatar
Marcin Slusarz committed
2196
int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
2197
			struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
Linus Torvalds's avatar
Linus Torvalds committed
2198 2199 2200 2201
{
	int alen;
	int8_t etype;
	uint8_t *ptr;
2202 2203
	struct short_ad *sad;
	struct long_ad *lad;
2204
	struct udf_inode_info *iinfo = UDF_I(inode);
2205

2206
	if (!epos->bh) {
2207 2208
		if (!epos->offset)
			epos->offset = udf_file_entry_alloc_offset(inode);
2209
		ptr = iinfo->i_data + epos->offset -
Marcin Slusarz's avatar
Marcin Slusarz committed
2210
			udf_file_entry_alloc_offset(inode) +
2211
			iinfo->i_lenEAttr;
Marcin Slusarz's avatar
Marcin Slusarz committed
2212
		alen = udf_file_entry_alloc_offset(inode) +
2213
							iinfo->i_lenAlloc;
2214
	} else {
2215 2216 2217
		if (!epos->offset)
			epos->offset = sizeof(struct allocExtDesc);
		ptr = epos->bh->b_data + epos->offset;
2218
		alen = sizeof(struct allocExtDesc) +
Marcin Slusarz's avatar
Marcin Slusarz committed
2219 2220
			le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->
							lengthAllocDescs);
Linus Torvalds's avatar
Linus Torvalds committed
2221 2222
	}

2223
	switch (iinfo->i_alloc_type) {
2224
	case ICBTAG_FLAG_AD_SHORT:
Marcin Slusarz's avatar
Marcin Slusarz committed
2225 2226
		sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc);
		if (!sad)
2227 2228 2229
			return -1;
		etype = le32_to_cpu(sad->extLength) >> 30;
		eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
Marcin Slusarz's avatar
Marcin Slusarz committed
2230
		eloc->partitionReferenceNum =
2231
				iinfo->i_location.partitionReferenceNum;
2232 2233
		*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
		break;
2234
	case ICBTAG_FLAG_AD_LONG:
Marcin Slusarz's avatar
Marcin Slusarz committed
2235 2236
		lad = udf_get_filelongad(ptr, alen, &epos->offset, inc);
		if (!lad)
Linus Torvalds's avatar
Linus Torvalds committed
2237
			return -1;
2238 2239 2240 2241 2242
		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:
2243
		udf_debug("alloc_type = %u unsupported\n", iinfo->i_alloc_type);
2244
		return -1;
Linus Torvalds's avatar
Linus Torvalds committed
2245 2246 2247 2248 2249
	}

	return etype;
}

2250 2251
static int udf_insert_aext(struct inode *inode, struct extent_position epos,
			   struct kernel_lb_addr neloc, uint32_t nelen)
Linus Torvalds's avatar
Linus Torvalds committed
2252
{
2253
	struct kernel_lb_addr oeloc;
Linus Torvalds's avatar
Linus Torvalds committed
2254 2255
	uint32_t oelen;
	int8_t etype;
2256
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
2257

2258
	if (epos.bh)
Jan Kara's avatar
Jan Kara committed
2259
		get_bh(epos.bh);
Linus Torvalds's avatar
Linus Torvalds committed
2260

2261
	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {
2262
		udf_write_aext(inode, &epos, &neloc, nelen, 1);
Linus Torvalds's avatar
Linus Torvalds committed
2263 2264 2265
		neloc = oeloc;
		nelen = (etype << 30) | oelen;
	}
2266
	err = udf_add_aext(inode, &epos, &neloc, nelen, 1);
Jan Kara's avatar
Jan Kara committed
2267
	brelse(epos.bh);
2268

2269
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
2270 2271
}

2272
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
Linus Torvalds's avatar
Linus Torvalds committed
2273
{
2274 2275
	struct extent_position oepos;
	int adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2276 2277
	int8_t etype;
	struct allocExtDesc *aed;
2278
	struct udf_inode_info *iinfo;
2279 2280
	struct kernel_lb_addr eloc;
	uint32_t elen;
Linus Torvalds's avatar
Linus Torvalds committed
2281

2282
	if (epos.bh) {
Jan Kara's avatar
Jan Kara committed
2283 2284
		get_bh(epos.bh);
		get_bh(epos.bh);
Linus Torvalds's avatar
Linus Torvalds committed
2285 2286
	}

2287 2288
	iinfo = UDF_I(inode);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
2289
		adsize = sizeof(struct short_ad);
2290
	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
2291
		adsize = sizeof(struct long_ad);
Linus Torvalds's avatar
Linus Torvalds committed
2292 2293 2294
	else
		adsize = 0;

2295 2296
	oepos = epos;
	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
Linus Torvalds's avatar
Linus Torvalds committed
2297 2298
		return -1;

2299
	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
2300
		udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1);
2301
		if (oepos.bh != epos.bh) {
2302
			oepos.block = epos.block;
Jan Kara's avatar
Jan Kara committed
2303 2304
			brelse(oepos.bh);
			get_bh(epos.bh);
2305 2306
			oepos.bh = epos.bh;
			oepos.offset = epos.offset - adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2307 2308
		}
	}
2309
	memset(&eloc, 0x00, sizeof(struct kernel_lb_addr));
Linus Torvalds's avatar
Linus Torvalds committed
2310 2311
	elen = 0;

2312
	if (epos.bh != oepos.bh) {
2313 2314 2315
		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);
2316
		if (!oepos.bh) {
2317
			iinfo->i_lenAlloc -= (adsize * 2);
Linus Torvalds's avatar
Linus Torvalds committed
2318
			mark_inode_dirty(inode);
2319
		} else {
2320
			aed = (struct allocExtDesc *)oepos.bh->b_data;
2321
			le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
2322
			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
2323
			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
Marcin Slusarz's avatar
Marcin Slusarz committed
2324 2325
				udf_update_tag(oepos.bh->b_data,
						oepos.offset - (2 * adsize));
Linus Torvalds's avatar
Linus Torvalds committed
2326
			else
Marcin Slusarz's avatar
Marcin Slusarz committed
2327 2328
				udf_update_tag(oepos.bh->b_data,
						sizeof(struct allocExtDesc));
2329
			mark_buffer_dirty_inode(oepos.bh, inode);
Linus Torvalds's avatar
Linus Torvalds committed
2330
		}
2331
	} else {
2332
		udf_write_aext(inode, &oepos, &eloc, elen, 1);
2333
		if (!oepos.bh) {
2334
			iinfo->i_lenAlloc -= adsize;
Linus Torvalds's avatar
Linus Torvalds committed
2335
			mark_inode_dirty(inode);
2336
		} else {
2337
			aed = (struct allocExtDesc *)oepos.bh->b_data;
2338
			le32_add_cpu(&aed->lengthAllocDescs, -adsize);
2339
			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
2340
			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
Marcin Slusarz's avatar
Marcin Slusarz committed
2341 2342
				udf_update_tag(oepos.bh->b_data,
						epos.offset - adsize);
Linus Torvalds's avatar
Linus Torvalds committed
2343
			else
Marcin Slusarz's avatar
Marcin Slusarz committed
2344 2345
				udf_update_tag(oepos.bh->b_data,
						sizeof(struct allocExtDesc));
2346
			mark_buffer_dirty_inode(oepos.bh, inode);
Linus Torvalds's avatar
Linus Torvalds committed
2347 2348
		}
	}
2349

Jan Kara's avatar
Jan Kara committed
2350 2351
	brelse(epos.bh);
	brelse(oepos.bh);
2352

Linus Torvalds's avatar
Linus Torvalds committed
2353 2354 2355
	return (elen >> 30);
}

Marcin Slusarz's avatar
Marcin Slusarz committed
2356
int8_t inode_bmap(struct inode *inode, sector_t block,
2357
		  struct extent_position *pos, struct kernel_lb_addr *eloc,
Marcin Slusarz's avatar
Marcin Slusarz committed
2358
		  uint32_t *elen, sector_t *offset)
Linus Torvalds's avatar
Linus Torvalds committed
2359
{
Marcin Slusarz's avatar
Marcin Slusarz committed
2360
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
2361
	loff_t lbcount = 0, bcount = (loff_t) block << blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
2362
	int8_t etype;
2363
	struct udf_inode_info *iinfo;
Linus Torvalds's avatar
Linus Torvalds committed
2364

2365
	iinfo = UDF_I(inode);
2366 2367 2368 2369 2370
	if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) {
		pos->offset = 0;
		pos->block = iinfo->i_location;
		pos->bh = NULL;
	}
Linus Torvalds's avatar
Linus Torvalds committed
2371
	*elen = 0;
2372
	do {
Marcin Slusarz's avatar
Marcin Slusarz committed
2373 2374 2375
		etype = udf_next_aext(inode, pos, eloc, elen, 1);
		if (etype == -1) {
			*offset = (bcount - lbcount) >> blocksize_bits;
2376
			iinfo->i_lenExtents = lbcount;
Linus Torvalds's avatar
Linus Torvalds committed
2377 2378 2379 2380
			return -1;
		}
		lbcount += *elen;
	} while (lbcount <= bcount);
2381
	/* update extent cache */
2382
	udf_update_extent_cache(inode, lbcount - *elen, pos);
Marcin Slusarz's avatar
Marcin Slusarz committed
2383
	*offset = (bcount + *elen - lbcount) >> blocksize_bits;
Linus Torvalds's avatar
Linus Torvalds committed
2384 2385 2386

	return etype;
}