xref: /openbmc/linux/fs/udf/inode.c (revision ff116fc8d1d43927c7651b91d5aec41eb30c4429)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * inode.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * PURPOSE
51da177e4SLinus Torvalds  *  Inode handling routines for the OSTA-UDF(tm) filesystem.
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * COPYRIGHT
81da177e4SLinus Torvalds  *  This file is distributed under the terms of the GNU General Public
91da177e4SLinus Torvalds  *  License (GPL). Copies of the GPL can be obtained from:
101da177e4SLinus Torvalds  *    ftp://prep.ai.mit.edu/pub/gnu/GPL
111da177e4SLinus Torvalds  *  Each contributing author retains all rights to their own work.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *  (C) 1998 Dave Boynton
141da177e4SLinus Torvalds  *  (C) 1998-2004 Ben Fennema
151da177e4SLinus Torvalds  *  (C) 1999-2000 Stelias Computing Inc
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  * HISTORY
181da177e4SLinus Torvalds  *
191da177e4SLinus Torvalds  *  10/04/98 dgb  Added rudimentary directory functions
201da177e4SLinus Torvalds  *  10/07/98      Fully working udf_block_map! It works!
211da177e4SLinus Torvalds  *  11/25/98      bmap altered to better support extents
221da177e4SLinus Torvalds  *  12/06/98 blf  partition support in udf_iget, udf_block_map and udf_read_inode
231da177e4SLinus Torvalds  *  12/12/98      rewrote udf_block_map to handle next extents and descs across
241da177e4SLinus Torvalds  *                block boundaries (which is not actually allowed)
251da177e4SLinus Torvalds  *  12/20/98      added support for strategy 4096
261da177e4SLinus Torvalds  *  03/07/99      rewrote udf_block_map (again)
271da177e4SLinus Torvalds  *                New funcs, inode_bmap, udf_next_aext
281da177e4SLinus Torvalds  *  04/19/99      Support for writing device EA's for major/minor #
291da177e4SLinus Torvalds  */
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #include "udfdecl.h"
321da177e4SLinus Torvalds #include <linux/mm.h>
331da177e4SLinus Torvalds #include <linux/smp_lock.h>
341da177e4SLinus Torvalds #include <linux/module.h>
351da177e4SLinus Torvalds #include <linux/pagemap.h>
361da177e4SLinus Torvalds #include <linux/buffer_head.h>
371da177e4SLinus Torvalds #include <linux/writeback.h>
381da177e4SLinus Torvalds #include <linux/slab.h>
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #include "udf_i.h"
411da177e4SLinus Torvalds #include "udf_sb.h"
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds MODULE_AUTHOR("Ben Fennema");
441da177e4SLinus Torvalds MODULE_DESCRIPTION("Universal Disk Format Filesystem");
451da177e4SLinus Torvalds MODULE_LICENSE("GPL");
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds #define EXTENT_MERGE_SIZE 5
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds static mode_t udf_convert_permissions(struct fileEntry *);
501da177e4SLinus Torvalds static int udf_update_inode(struct inode *, int);
511da177e4SLinus Torvalds static void udf_fill_inode(struct inode *, struct buffer_head *);
5260448b1dSJan Kara static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
531da177e4SLinus Torvalds 	long *, int *);
54*ff116fc8SJan Kara static int8_t udf_insert_aext(struct inode *, struct extent_position,
55*ff116fc8SJan Kara 	kernel_lb_addr, uint32_t);
561da177e4SLinus Torvalds static void udf_split_extents(struct inode *, int *, int, int,
571da177e4SLinus Torvalds 	kernel_long_ad [EXTENT_MERGE_SIZE], int *);
581da177e4SLinus Torvalds static void udf_prealloc_extents(struct inode *, int, int,
591da177e4SLinus Torvalds 	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
601da177e4SLinus Torvalds static void udf_merge_extents(struct inode *,
611da177e4SLinus Torvalds 	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
621da177e4SLinus Torvalds static void udf_update_extents(struct inode *,
631da177e4SLinus Torvalds 	kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
64*ff116fc8SJan Kara 	struct extent_position *);
651da177e4SLinus Torvalds static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds /*
681da177e4SLinus Torvalds  * udf_delete_inode
691da177e4SLinus Torvalds  *
701da177e4SLinus Torvalds  * PURPOSE
711da177e4SLinus Torvalds  *	Clean-up before the specified inode is destroyed.
721da177e4SLinus Torvalds  *
731da177e4SLinus Torvalds  * DESCRIPTION
741da177e4SLinus Torvalds  *	This routine is called when the kernel destroys an inode structure
751da177e4SLinus Torvalds  *	ie. when iput() finds i_count == 0.
761da177e4SLinus Torvalds  *
771da177e4SLinus Torvalds  * HISTORY
781da177e4SLinus Torvalds  *	July 1, 1997 - Andrew E. Mileski
791da177e4SLinus Torvalds  *	Written, tested, and released.
801da177e4SLinus Torvalds  *
811da177e4SLinus Torvalds  *  Called at the last iput() if i_nlink is zero.
821da177e4SLinus Torvalds  */
831da177e4SLinus Torvalds void udf_delete_inode(struct inode * inode)
841da177e4SLinus Torvalds {
85fef26658SMark Fasheh 	truncate_inode_pages(&inode->i_data, 0);
86fef26658SMark Fasheh 
871da177e4SLinus Torvalds 	if (is_bad_inode(inode))
881da177e4SLinus Torvalds 		goto no_delete;
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	inode->i_size = 0;
911da177e4SLinus Torvalds 	udf_truncate(inode);
921da177e4SLinus Torvalds 	lock_kernel();
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds 	udf_update_inode(inode, IS_SYNC(inode));
951da177e4SLinus Torvalds 	udf_free_inode(inode);
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds 	unlock_kernel();
981da177e4SLinus Torvalds 	return;
991da177e4SLinus Torvalds no_delete:
1001da177e4SLinus Torvalds 	clear_inode(inode);
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds void udf_clear_inode(struct inode *inode)
1041da177e4SLinus Torvalds {
1051da177e4SLinus Torvalds 	if (!(inode->i_sb->s_flags & MS_RDONLY)) {
1061da177e4SLinus Torvalds 		lock_kernel();
1071da177e4SLinus Torvalds 		udf_discard_prealloc(inode);
1081da177e4SLinus Torvalds 		unlock_kernel();
1091da177e4SLinus Torvalds 	}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	kfree(UDF_I_DATA(inode));
1121da177e4SLinus Torvalds 	UDF_I_DATA(inode) = NULL;
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int udf_writepage(struct page *page, struct writeback_control *wbc)
1161da177e4SLinus Torvalds {
1171da177e4SLinus Torvalds 	return block_write_full_page(page, udf_get_block, wbc);
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds static int udf_readpage(struct file *file, struct page *page)
1211da177e4SLinus Torvalds {
1221da177e4SLinus Torvalds 	return block_read_full_page(page, udf_get_block);
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds static int udf_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds 	return block_prepare_write(page, from, to, udf_get_block);
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds static sector_t udf_bmap(struct address_space *mapping, sector_t block)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds 	return generic_block_bmap(mapping,block,udf_get_block);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
135f5e54d6eSChristoph Hellwig const struct address_space_operations udf_aops = {
1361da177e4SLinus Torvalds 	.readpage		= udf_readpage,
1371da177e4SLinus Torvalds 	.writepage		= udf_writepage,
1381da177e4SLinus Torvalds 	.sync_page		= block_sync_page,
1391da177e4SLinus Torvalds 	.prepare_write		= udf_prepare_write,
1401da177e4SLinus Torvalds 	.commit_write		= generic_commit_write,
1411da177e4SLinus Torvalds 	.bmap			= udf_bmap,
1421da177e4SLinus Torvalds };
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
1451da177e4SLinus Torvalds {
1461da177e4SLinus Torvalds 	struct page *page;
1471da177e4SLinus Torvalds 	char *kaddr;
1481da177e4SLinus Torvalds 	struct writeback_control udf_wbc = {
1491da177e4SLinus Torvalds 		.sync_mode = WB_SYNC_NONE,
1501da177e4SLinus Torvalds 		.nr_to_write = 1,
1511da177e4SLinus Torvalds 	};
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds 	/* from now on we have normal address_space methods */
1541da177e4SLinus Torvalds 	inode->i_data.a_ops = &udf_aops;
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 	if (!UDF_I_LENALLOC(inode))
1571da177e4SLinus Torvalds 	{
1581da177e4SLinus Torvalds 		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
1591da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
1601da177e4SLinus Torvalds 		else
1611da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
1621da177e4SLinus Torvalds 		mark_inode_dirty(inode);
1631da177e4SLinus Torvalds 		return;
1641da177e4SLinus Torvalds 	}
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds 	page = grab_cache_page(inode->i_mapping, 0);
167cd7619d6SMatt Mackall 	BUG_ON(!PageLocked(page));
168cd7619d6SMatt Mackall 
1691da177e4SLinus Torvalds 	if (!PageUptodate(page))
1701da177e4SLinus Torvalds 	{
1711da177e4SLinus Torvalds 		kaddr = kmap(page);
1721da177e4SLinus Torvalds 		memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
1731da177e4SLinus Torvalds 			PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
1741da177e4SLinus Torvalds 		memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
1751da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode));
1761da177e4SLinus Torvalds 		flush_dcache_page(page);
1771da177e4SLinus Torvalds 		SetPageUptodate(page);
1781da177e4SLinus Torvalds 		kunmap(page);
1791da177e4SLinus Torvalds 	}
1801da177e4SLinus Torvalds 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
1811da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode));
1821da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
1831da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
1841da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
1851da177e4SLinus Torvalds 	else
1861da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
1871da177e4SLinus Torvalds 
1881da177e4SLinus Torvalds 	inode->i_data.a_ops->writepage(page, &udf_wbc);
1891da177e4SLinus Torvalds 	page_cache_release(page);
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds 	mark_inode_dirty(inode);
1921da177e4SLinus Torvalds }
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
1951da177e4SLinus Torvalds {
1961da177e4SLinus Torvalds 	int newblock;
197*ff116fc8SJan Kara 	struct buffer_head *dbh = NULL;
198*ff116fc8SJan Kara 	kernel_lb_addr eloc;
199*ff116fc8SJan Kara 	uint32_t elen;
2001da177e4SLinus Torvalds 	uint8_t alloctype;
201*ff116fc8SJan Kara 	struct extent_position epos;
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 	struct udf_fileident_bh sfibh, dfibh;
2041da177e4SLinus Torvalds 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
2051da177e4SLinus Torvalds 	int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
2061da177e4SLinus Torvalds 	struct fileIdentDesc cfi, *sfi, *dfi;
2071da177e4SLinus Torvalds 
2081da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
2091da177e4SLinus Torvalds 		alloctype = ICBTAG_FLAG_AD_SHORT;
2101da177e4SLinus Torvalds 	else
2111da177e4SLinus Torvalds 		alloctype = ICBTAG_FLAG_AD_LONG;
2121da177e4SLinus Torvalds 
2131da177e4SLinus Torvalds 	if (!inode->i_size)
2141da177e4SLinus Torvalds 	{
2151da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = alloctype;
2161da177e4SLinus Torvalds 		mark_inode_dirty(inode);
2171da177e4SLinus Torvalds 		return NULL;
2181da177e4SLinus Torvalds 	}
2191da177e4SLinus Torvalds 
2201da177e4SLinus Torvalds 	/* alloc block, and copy data to it */
2211da177e4SLinus Torvalds 	*block = udf_new_block(inode->i_sb, inode,
2221da177e4SLinus Torvalds 		UDF_I_LOCATION(inode).partitionReferenceNum,
2231da177e4SLinus Torvalds 		UDF_I_LOCATION(inode).logicalBlockNum, err);
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 	if (!(*block))
2261da177e4SLinus Torvalds 		return NULL;
2271da177e4SLinus Torvalds 	newblock = udf_get_pblock(inode->i_sb, *block,
2281da177e4SLinus Torvalds 		UDF_I_LOCATION(inode).partitionReferenceNum, 0);
2291da177e4SLinus Torvalds 	if (!newblock)
2301da177e4SLinus Torvalds 		return NULL;
2311da177e4SLinus Torvalds 	dbh = udf_tgetblk(inode->i_sb, newblock);
2321da177e4SLinus Torvalds 	if (!dbh)
2331da177e4SLinus Torvalds 		return NULL;
2341da177e4SLinus Torvalds 	lock_buffer(dbh);
2351da177e4SLinus Torvalds 	memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize);
2361da177e4SLinus Torvalds 	set_buffer_uptodate(dbh);
2371da177e4SLinus Torvalds 	unlock_buffer(dbh);
2381da177e4SLinus Torvalds 	mark_buffer_dirty_inode(dbh, inode);
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
241*ff116fc8SJan Kara 	sfibh.sbh = sfibh.ebh = NULL;
2421da177e4SLinus Torvalds 	dfibh.soffset = dfibh.eoffset = 0;
2431da177e4SLinus Torvalds 	dfibh.sbh = dfibh.ebh = dbh;
2441da177e4SLinus Torvalds 	while ( (f_pos < size) )
2451da177e4SLinus Torvalds 	{
2461da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
247*ff116fc8SJan Kara 		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
2481da177e4SLinus Torvalds 		if (!sfi)
2491da177e4SLinus Torvalds 		{
2501da177e4SLinus Torvalds 			udf_release_data(dbh);
2511da177e4SLinus Torvalds 			return NULL;
2521da177e4SLinus Torvalds 		}
2531da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = alloctype;
2541da177e4SLinus Torvalds 		sfi->descTag.tagLocation = cpu_to_le32(*block);
2551da177e4SLinus Torvalds 		dfibh.soffset = dfibh.eoffset;
2561da177e4SLinus Torvalds 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
2571da177e4SLinus Torvalds 		dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
2581da177e4SLinus Torvalds 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
2591da177e4SLinus Torvalds 			sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
2601da177e4SLinus Torvalds 		{
2611da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
2621da177e4SLinus Torvalds 			udf_release_data(dbh);
2631da177e4SLinus Torvalds 			return NULL;
2641da177e4SLinus Torvalds 		}
2651da177e4SLinus Torvalds 	}
2661da177e4SLinus Torvalds 	mark_buffer_dirty_inode(dbh, inode);
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
2691da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
2701da177e4SLinus Torvalds 	eloc.logicalBlockNum = *block;
2711da177e4SLinus Torvalds 	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
2721da177e4SLinus Torvalds 	elen = inode->i_size;
2731da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = elen;
274*ff116fc8SJan Kara 	epos.bh = NULL;
275*ff116fc8SJan Kara 	epos.block = UDF_I_LOCATION(inode);
276*ff116fc8SJan Kara 	epos.offset = udf_file_entry_alloc_offset(inode);
277*ff116fc8SJan Kara 	udf_add_aext(inode, &epos, eloc, elen, 0);
2781da177e4SLinus Torvalds 	/* UniqueID stuff */
2791da177e4SLinus Torvalds 
280*ff116fc8SJan Kara 	udf_release_data(epos.bh);
2811da177e4SLinus Torvalds 	mark_inode_dirty(inode);
2821da177e4SLinus Torvalds 	return dbh;
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
2861da177e4SLinus Torvalds {
2871da177e4SLinus Torvalds 	int err, new;
2881da177e4SLinus Torvalds 	struct buffer_head *bh;
2891da177e4SLinus Torvalds 	unsigned long phys;
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds 	if (!create)
2921da177e4SLinus Torvalds 	{
2931da177e4SLinus Torvalds 		phys = udf_block_map(inode, block);
2941da177e4SLinus Torvalds 		if (phys)
2951da177e4SLinus Torvalds 			map_bh(bh_result, inode->i_sb, phys);
2961da177e4SLinus Torvalds 		return 0;
2971da177e4SLinus Torvalds 	}
2981da177e4SLinus Torvalds 
2991da177e4SLinus Torvalds 	err = -EIO;
3001da177e4SLinus Torvalds 	new = 0;
3011da177e4SLinus Torvalds 	bh = NULL;
3021da177e4SLinus Torvalds 
3031da177e4SLinus Torvalds 	lock_kernel();
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 	if (block < 0)
3061da177e4SLinus Torvalds 		goto abort_negative;
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds 	if (block == UDF_I_NEXT_ALLOC_BLOCK(inode) + 1)
3091da177e4SLinus Torvalds 	{
3101da177e4SLinus Torvalds 		UDF_I_NEXT_ALLOC_BLOCK(inode) ++;
3111da177e4SLinus Torvalds 		UDF_I_NEXT_ALLOC_GOAL(inode) ++;
3121da177e4SLinus Torvalds 	}
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	err = 0;
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds 	bh = inode_getblk(inode, block, &err, &phys, &new);
3172c2111c2SEric Sesterhenn 	BUG_ON(bh);
3181da177e4SLinus Torvalds 	if (err)
3191da177e4SLinus Torvalds 		goto abort;
3202c2111c2SEric Sesterhenn 	BUG_ON(!phys);
3211da177e4SLinus Torvalds 
3221da177e4SLinus Torvalds 	if (new)
3231da177e4SLinus Torvalds 		set_buffer_new(bh_result);
3241da177e4SLinus Torvalds 	map_bh(bh_result, inode->i_sb, phys);
3251da177e4SLinus Torvalds abort:
3261da177e4SLinus Torvalds 	unlock_kernel();
3271da177e4SLinus Torvalds 	return err;
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds abort_negative:
3301da177e4SLinus Torvalds 	udf_warning(inode->i_sb, "udf_get_block", "block < 0");
3311da177e4SLinus Torvalds 	goto abort;
3321da177e4SLinus Torvalds }
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds static struct buffer_head *
3351da177e4SLinus Torvalds udf_getblk(struct inode *inode, long block, int create, int *err)
3361da177e4SLinus Torvalds {
3371da177e4SLinus Torvalds 	struct buffer_head dummy;
3381da177e4SLinus Torvalds 
3391da177e4SLinus Torvalds 	dummy.b_state = 0;
3401da177e4SLinus Torvalds 	dummy.b_blocknr = -1000;
3411da177e4SLinus Torvalds 	*err = udf_get_block(inode, block, &dummy, create);
3421da177e4SLinus Torvalds 	if (!*err && buffer_mapped(&dummy))
3431da177e4SLinus Torvalds 	{
3441da177e4SLinus Torvalds 		struct buffer_head *bh;
3451da177e4SLinus Torvalds 		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
3461da177e4SLinus Torvalds 		if (buffer_new(&dummy))
3471da177e4SLinus Torvalds 		{
3481da177e4SLinus Torvalds 			lock_buffer(bh);
3491da177e4SLinus Torvalds 			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
3501da177e4SLinus Torvalds 			set_buffer_uptodate(bh);
3511da177e4SLinus Torvalds 			unlock_buffer(bh);
3521da177e4SLinus Torvalds 			mark_buffer_dirty_inode(bh, inode);
3531da177e4SLinus Torvalds 		}
3541da177e4SLinus Torvalds 		return bh;
3551da177e4SLinus Torvalds 	}
3561da177e4SLinus Torvalds 	return NULL;
3571da177e4SLinus Torvalds }
3581da177e4SLinus Torvalds 
35960448b1dSJan Kara static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
3601da177e4SLinus Torvalds 	int *err, long *phys, int *new)
3611da177e4SLinus Torvalds {
362*ff116fc8SJan Kara 	struct buffer_head *result = NULL;
3631da177e4SLinus Torvalds 	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
364*ff116fc8SJan Kara 	struct extent_position prev_epos, cur_epos, next_epos;
3651da177e4SLinus Torvalds 	int count = 0, startnum = 0, endnum = 0;
3661da177e4SLinus Torvalds 	uint32_t elen = 0;
367*ff116fc8SJan Kara 	kernel_lb_addr eloc;
3681da177e4SLinus Torvalds 	int c = 1;
36960448b1dSJan Kara 	loff_t lbcount = 0, b_off = 0;
37060448b1dSJan Kara 	uint32_t newblocknum, newblock;
37160448b1dSJan Kara 	sector_t offset = 0;
3721da177e4SLinus Torvalds 	int8_t etype;
3731da177e4SLinus Torvalds 	int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
3741da177e4SLinus Torvalds 	char lastblock = 0;
3751da177e4SLinus Torvalds 
376*ff116fc8SJan Kara 	prev_epos.offset = udf_file_entry_alloc_offset(inode);
377*ff116fc8SJan Kara 	prev_epos.block = UDF_I_LOCATION(inode);
378*ff116fc8SJan Kara 	prev_epos.bh = NULL;
379*ff116fc8SJan Kara 	cur_epos = next_epos = prev_epos;
38060448b1dSJan Kara 	b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
3811da177e4SLinus Torvalds 
3821da177e4SLinus Torvalds 	/* find the extent which contains the block we are looking for.
3831da177e4SLinus Torvalds        alternate between laarr[0] and laarr[1] for locations of the
3841da177e4SLinus Torvalds        current extent, and the previous extent */
3851da177e4SLinus Torvalds 	do
3861da177e4SLinus Torvalds 	{
387*ff116fc8SJan Kara 		if (prev_epos.bh != cur_epos.bh)
3881da177e4SLinus Torvalds 		{
389*ff116fc8SJan Kara 			udf_release_data(prev_epos.bh);
390*ff116fc8SJan Kara 			atomic_inc(&cur_epos.bh->b_count);
391*ff116fc8SJan Kara 			prev_epos.bh = cur_epos.bh;
3921da177e4SLinus Torvalds 		}
393*ff116fc8SJan Kara 		if (cur_epos.bh != next_epos.bh)
3941da177e4SLinus Torvalds 		{
395*ff116fc8SJan Kara 			udf_release_data(cur_epos.bh);
396*ff116fc8SJan Kara 			atomic_inc(&next_epos.bh->b_count);
397*ff116fc8SJan Kara 			cur_epos.bh = next_epos.bh;
3981da177e4SLinus Torvalds 		}
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 		lbcount += elen;
4011da177e4SLinus Torvalds 
402*ff116fc8SJan Kara 		prev_epos.block = cur_epos.block;
403*ff116fc8SJan Kara 		cur_epos.block = next_epos.block;
4041da177e4SLinus Torvalds 
405*ff116fc8SJan Kara 		prev_epos.offset = cur_epos.offset;
406*ff116fc8SJan Kara 		cur_epos.offset = next_epos.offset;
4071da177e4SLinus Torvalds 
408*ff116fc8SJan Kara 		if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1)) == -1)
4091da177e4SLinus Torvalds 			break;
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 		c = !c;
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 		laarr[c].extLength = (etype << 30) | elen;
4141da177e4SLinus Torvalds 		laarr[c].extLocation = eloc;
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 		if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
4171da177e4SLinus Torvalds 			pgoal = eloc.logicalBlockNum +
4181da177e4SLinus Torvalds 				((elen + inode->i_sb->s_blocksize - 1) >>
4191da177e4SLinus Torvalds 				inode->i_sb->s_blocksize_bits);
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 		count ++;
4221da177e4SLinus Torvalds 	} while (lbcount + elen <= b_off);
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 	b_off -= lbcount;
4251da177e4SLinus Torvalds 	offset = b_off >> inode->i_sb->s_blocksize_bits;
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 	/* if the extent is allocated and recorded, return the block
4281da177e4SLinus Torvalds        if the extent is not a multiple of the blocksize, round up */
4291da177e4SLinus Torvalds 
4301da177e4SLinus Torvalds 	if (etype == (EXT_RECORDED_ALLOCATED >> 30))
4311da177e4SLinus Torvalds 	{
4321da177e4SLinus Torvalds 		if (elen & (inode->i_sb->s_blocksize - 1))
4331da177e4SLinus Torvalds 		{
4341da177e4SLinus Torvalds 			elen = EXT_RECORDED_ALLOCATED |
4351da177e4SLinus Torvalds 				((elen + inode->i_sb->s_blocksize - 1) &
4361da177e4SLinus Torvalds 				~(inode->i_sb->s_blocksize - 1));
437*ff116fc8SJan Kara 			etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
4381da177e4SLinus Torvalds 		}
439*ff116fc8SJan Kara 		udf_release_data(prev_epos.bh);
440*ff116fc8SJan Kara 		udf_release_data(cur_epos.bh);
441*ff116fc8SJan Kara 		udf_release_data(next_epos.bh);
4421da177e4SLinus Torvalds 		newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
4431da177e4SLinus Torvalds 		*phys = newblock;
4441da177e4SLinus Torvalds 		return NULL;
4451da177e4SLinus Torvalds 	}
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds 	if (etype == -1)
4481da177e4SLinus Torvalds 	{
4491da177e4SLinus Torvalds 		endnum = startnum = ((count > 1) ? 1 : count);
4501da177e4SLinus Torvalds 		if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
4511da177e4SLinus Torvalds 		{
4521da177e4SLinus Torvalds 			laarr[c].extLength =
4531da177e4SLinus Torvalds 				(laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
4541da177e4SLinus Torvalds 				(((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
4551da177e4SLinus Torvalds 					inode->i_sb->s_blocksize - 1) &
4561da177e4SLinus Torvalds 				~(inode->i_sb->s_blocksize - 1));
4571da177e4SLinus Torvalds 			UDF_I_LENEXTENTS(inode) =
4581da177e4SLinus Torvalds 				(UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) &
4591da177e4SLinus Torvalds 					~(inode->i_sb->s_blocksize - 1);
4601da177e4SLinus Torvalds 		}
4611da177e4SLinus Torvalds 		c = !c;
4621da177e4SLinus Torvalds 		laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
4631da177e4SLinus Torvalds 			((offset + 1) << inode->i_sb->s_blocksize_bits);
4641da177e4SLinus Torvalds 		memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
4651da177e4SLinus Torvalds 		count ++;
4661da177e4SLinus Torvalds 		endnum ++;
4671da177e4SLinus Torvalds 		lastblock = 1;
4681da177e4SLinus Torvalds 	}
4691da177e4SLinus Torvalds 	else
4701da177e4SLinus Torvalds 		endnum = startnum = ((count > 2) ? 2 : count);
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds 	/* if the current extent is in position 0, swap it with the previous */
4731da177e4SLinus Torvalds 	if (!c && count != 1)
4741da177e4SLinus Torvalds 	{
4751da177e4SLinus Torvalds 		laarr[2] = laarr[0];
4761da177e4SLinus Torvalds 		laarr[0] = laarr[1];
4771da177e4SLinus Torvalds 		laarr[1] = laarr[2];
4781da177e4SLinus Torvalds 		c = 1;
4791da177e4SLinus Torvalds 	}
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 	/* if the current block is located in a extent, read the next extent */
4821da177e4SLinus Torvalds 	if (etype != -1)
4831da177e4SLinus Torvalds 	{
484*ff116fc8SJan Kara 		if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
4851da177e4SLinus Torvalds 		{
4861da177e4SLinus Torvalds 			laarr[c+1].extLength = (etype << 30) | elen;
4871da177e4SLinus Torvalds 			laarr[c+1].extLocation = eloc;
4881da177e4SLinus Torvalds 			count ++;
4891da177e4SLinus Torvalds 			startnum ++;
4901da177e4SLinus Torvalds 			endnum ++;
4911da177e4SLinus Torvalds 		}
4921da177e4SLinus Torvalds 		else
4931da177e4SLinus Torvalds 			lastblock = 1;
4941da177e4SLinus Torvalds 	}
495*ff116fc8SJan Kara 	udf_release_data(cur_epos.bh);
496*ff116fc8SJan Kara 	udf_release_data(next_epos.bh);
4971da177e4SLinus Torvalds 
4981da177e4SLinus Torvalds 	/* if the current extent is not recorded but allocated, get the
4991da177e4SLinus Torvalds 		block in the extent corresponding to the requested block */
5001da177e4SLinus Torvalds 	if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
5011da177e4SLinus Torvalds 		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
5021da177e4SLinus Torvalds 	else /* otherwise, allocate a new block */
5031da177e4SLinus Torvalds 	{
5041da177e4SLinus Torvalds 		if (UDF_I_NEXT_ALLOC_BLOCK(inode) == block)
5051da177e4SLinus Torvalds 			goal = UDF_I_NEXT_ALLOC_GOAL(inode);
5061da177e4SLinus Torvalds 
5071da177e4SLinus Torvalds 		if (!goal)
5081da177e4SLinus Torvalds 		{
5091da177e4SLinus Torvalds 			if (!(goal = pgoal))
5101da177e4SLinus Torvalds 				goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
5111da177e4SLinus Torvalds 		}
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds 		if (!(newblocknum = udf_new_block(inode->i_sb, inode,
5141da177e4SLinus Torvalds 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
5151da177e4SLinus Torvalds 		{
516*ff116fc8SJan Kara 			udf_release_data(prev_epos.bh);
5171da177e4SLinus Torvalds 			*err = -ENOSPC;
5181da177e4SLinus Torvalds 			return NULL;
5191da177e4SLinus Torvalds 		}
5201da177e4SLinus Torvalds 		UDF_I_LENEXTENTS(inode) += inode->i_sb->s_blocksize;
5211da177e4SLinus Torvalds 	}
5221da177e4SLinus Torvalds 
5231da177e4SLinus Torvalds 	/* if the extent the requsted block is located in contains multiple blocks,
5241da177e4SLinus Torvalds        split the extent into at most three extents. blocks prior to requested
5251da177e4SLinus Torvalds        block, requested block, and blocks after requested block */
5261da177e4SLinus Torvalds 	udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);
5271da177e4SLinus Torvalds 
5281da177e4SLinus Torvalds #ifdef UDF_PREALLOCATE
5291da177e4SLinus Torvalds 	/* preallocate blocks */
5301da177e4SLinus Torvalds 	udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
5311da177e4SLinus Torvalds #endif
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds 	/* merge any continuous blocks in laarr */
5341da177e4SLinus Torvalds 	udf_merge_extents(inode, laarr, &endnum);
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds 	/* write back the new extents, inserting new extents if the new number
5371da177e4SLinus Torvalds        of extents is greater than the old number, and deleting extents if
5381da177e4SLinus Torvalds        the new number of extents is less than the old number */
539*ff116fc8SJan Kara 	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
5401da177e4SLinus Torvalds 
541*ff116fc8SJan Kara 	udf_release_data(prev_epos.bh);
5421da177e4SLinus Torvalds 
5431da177e4SLinus Torvalds 	if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
5441da177e4SLinus Torvalds 		UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
5451da177e4SLinus Torvalds 	{
5461da177e4SLinus Torvalds 		return NULL;
5471da177e4SLinus Torvalds 	}
5481da177e4SLinus Torvalds 	*phys = newblock;
5491da177e4SLinus Torvalds 	*err = 0;
5501da177e4SLinus Torvalds 	*new = 1;
5511da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_BLOCK(inode) = block;
5521da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum;
5531da177e4SLinus Torvalds 	inode->i_ctime = current_fs_time(inode->i_sb);
5541da177e4SLinus Torvalds 
5551da177e4SLinus Torvalds 	if (IS_SYNC(inode))
5561da177e4SLinus Torvalds 		udf_sync_inode(inode);
5571da177e4SLinus Torvalds 	else
5581da177e4SLinus Torvalds 		mark_inode_dirty(inode);
5591da177e4SLinus Torvalds 	return result;
5601da177e4SLinus Torvalds }
5611da177e4SLinus Torvalds 
5621da177e4SLinus Torvalds static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
5631da177e4SLinus Torvalds 	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
5641da177e4SLinus Torvalds {
5651da177e4SLinus Torvalds 	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
5661da177e4SLinus Torvalds 		(laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
5671da177e4SLinus Torvalds 	{
5681da177e4SLinus Torvalds 		int curr = *c;
5691da177e4SLinus Torvalds 		int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
5701da177e4SLinus Torvalds 			inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
5711da177e4SLinus Torvalds 		int8_t etype = (laarr[curr].extLength >> 30);
5721da177e4SLinus Torvalds 
5731da177e4SLinus Torvalds 		if (blen == 1)
5741da177e4SLinus Torvalds 			;
5751da177e4SLinus Torvalds 		else if (!offset || blen == offset + 1)
5761da177e4SLinus Torvalds 		{
5771da177e4SLinus Torvalds 			laarr[curr+2] = laarr[curr+1];
5781da177e4SLinus Torvalds 			laarr[curr+1] = laarr[curr];
5791da177e4SLinus Torvalds 		}
5801da177e4SLinus Torvalds 		else
5811da177e4SLinus Torvalds 		{
5821da177e4SLinus Torvalds 			laarr[curr+3] = laarr[curr+1];
5831da177e4SLinus Torvalds 			laarr[curr+2] = laarr[curr+1] = laarr[curr];
5841da177e4SLinus Torvalds 		}
5851da177e4SLinus Torvalds 
5861da177e4SLinus Torvalds 		if (offset)
5871da177e4SLinus Torvalds 		{
5881da177e4SLinus Torvalds 			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
5891da177e4SLinus Torvalds 			{
5901da177e4SLinus Torvalds 				udf_free_blocks(inode->i_sb, inode, laarr[curr].extLocation, 0, offset);
5911da177e4SLinus Torvalds 				laarr[curr].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
5921da177e4SLinus Torvalds 					(offset << inode->i_sb->s_blocksize_bits);
5931da177e4SLinus Torvalds 				laarr[curr].extLocation.logicalBlockNum = 0;
5941da177e4SLinus Torvalds 				laarr[curr].extLocation.partitionReferenceNum = 0;
5951da177e4SLinus Torvalds 			}
5961da177e4SLinus Torvalds 			else
5971da177e4SLinus Torvalds 				laarr[curr].extLength = (etype << 30) |
5981da177e4SLinus Torvalds 					(offset << inode->i_sb->s_blocksize_bits);
5991da177e4SLinus Torvalds 			curr ++;
6001da177e4SLinus Torvalds 			(*c) ++;
6011da177e4SLinus Torvalds 			(*endnum) ++;
6021da177e4SLinus Torvalds 		}
6031da177e4SLinus Torvalds 
6041da177e4SLinus Torvalds 		laarr[curr].extLocation.logicalBlockNum = newblocknum;
6051da177e4SLinus Torvalds 		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
6061da177e4SLinus Torvalds 			laarr[curr].extLocation.partitionReferenceNum =
6071da177e4SLinus Torvalds 				UDF_I_LOCATION(inode).partitionReferenceNum;
6081da177e4SLinus Torvalds 		laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
6091da177e4SLinus Torvalds 			inode->i_sb->s_blocksize;
6101da177e4SLinus Torvalds 		curr ++;
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 		if (blen != offset + 1)
6131da177e4SLinus Torvalds 		{
6141da177e4SLinus Torvalds 			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
6151da177e4SLinus Torvalds 				laarr[curr].extLocation.logicalBlockNum += (offset + 1);
6161da177e4SLinus Torvalds 			laarr[curr].extLength = (etype << 30) |
6171da177e4SLinus Torvalds 				((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits);
6181da177e4SLinus Torvalds 			curr ++;
6191da177e4SLinus Torvalds 			(*endnum) ++;
6201da177e4SLinus Torvalds 		}
6211da177e4SLinus Torvalds 	}
6221da177e4SLinus Torvalds }
6231da177e4SLinus Torvalds 
6241da177e4SLinus Torvalds static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
6251da177e4SLinus Torvalds 	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
6261da177e4SLinus Torvalds {
6271da177e4SLinus Torvalds 	int start, length = 0, currlength = 0, i;
6281da177e4SLinus Torvalds 
6291da177e4SLinus Torvalds 	if (*endnum >= (c+1))
6301da177e4SLinus Torvalds 	{
6311da177e4SLinus Torvalds 		if (!lastblock)
6321da177e4SLinus Torvalds 			return;
6331da177e4SLinus Torvalds 		else
6341da177e4SLinus Torvalds 			start = c;
6351da177e4SLinus Torvalds 	}
6361da177e4SLinus Torvalds 	else
6371da177e4SLinus Torvalds 	{
6381da177e4SLinus Torvalds 		if ((laarr[c+1].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
6391da177e4SLinus Torvalds 		{
6401da177e4SLinus Torvalds 			start = c+1;
6411da177e4SLinus Torvalds 			length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) +
6421da177e4SLinus Torvalds 				inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
6431da177e4SLinus Torvalds 		}
6441da177e4SLinus Torvalds 		else
6451da177e4SLinus Torvalds 			start = c;
6461da177e4SLinus Torvalds 	}
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds 	for (i=start+1; i<=*endnum; i++)
6491da177e4SLinus Torvalds 	{
6501da177e4SLinus Torvalds 		if (i == *endnum)
6511da177e4SLinus Torvalds 		{
6521da177e4SLinus Torvalds 			if (lastblock)
6531da177e4SLinus Torvalds 				length += UDF_DEFAULT_PREALLOC_BLOCKS;
6541da177e4SLinus Torvalds 		}
6551da177e4SLinus Torvalds 		else if ((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
6561da177e4SLinus Torvalds 			length += (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
6571da177e4SLinus Torvalds 				inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
6581da177e4SLinus Torvalds 		else
6591da177e4SLinus Torvalds 			break;
6601da177e4SLinus Torvalds 	}
6611da177e4SLinus Torvalds 
6621da177e4SLinus Torvalds 	if (length)
6631da177e4SLinus Torvalds 	{
6641da177e4SLinus Torvalds 		int next = laarr[start].extLocation.logicalBlockNum +
6651da177e4SLinus Torvalds 			(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
6661da177e4SLinus Torvalds 			inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
6671da177e4SLinus Torvalds 		int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
6681da177e4SLinus Torvalds 			laarr[start].extLocation.partitionReferenceNum,
6691da177e4SLinus Torvalds 			next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length :
6701da177e4SLinus Torvalds 				UDF_DEFAULT_PREALLOC_BLOCKS) - currlength);
6711da177e4SLinus Torvalds 
6721da177e4SLinus Torvalds 		if (numalloc)
6731da177e4SLinus Torvalds 		{
6741da177e4SLinus Torvalds 			if (start == (c+1))
6751da177e4SLinus Torvalds 				laarr[start].extLength +=
6761da177e4SLinus Torvalds 					(numalloc << inode->i_sb->s_blocksize_bits);
6771da177e4SLinus Torvalds 			else
6781da177e4SLinus Torvalds 			{
6791da177e4SLinus Torvalds 				memmove(&laarr[c+2], &laarr[c+1],
6801da177e4SLinus Torvalds 					sizeof(long_ad) * (*endnum - (c+1)));
6811da177e4SLinus Torvalds 				(*endnum) ++;
6821da177e4SLinus Torvalds 				laarr[c+1].extLocation.logicalBlockNum = next;
6831da177e4SLinus Torvalds 				laarr[c+1].extLocation.partitionReferenceNum =
6841da177e4SLinus Torvalds 					laarr[c].extLocation.partitionReferenceNum;
6851da177e4SLinus Torvalds 				laarr[c+1].extLength = EXT_NOT_RECORDED_ALLOCATED |
6861da177e4SLinus Torvalds 					(numalloc << inode->i_sb->s_blocksize_bits);
6871da177e4SLinus Torvalds 				start = c+1;
6881da177e4SLinus Torvalds 			}
6891da177e4SLinus Torvalds 
6901da177e4SLinus Torvalds 			for (i=start+1; numalloc && i<*endnum; i++)
6911da177e4SLinus Torvalds 			{
6921da177e4SLinus Torvalds 				int elen = ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
6931da177e4SLinus Torvalds 					inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds 				if (elen > numalloc)
6961da177e4SLinus Torvalds 				{
6971da177e4SLinus Torvalds 					laarr[i].extLength -=
6981da177e4SLinus Torvalds 						(numalloc << inode->i_sb->s_blocksize_bits);
6991da177e4SLinus Torvalds 					numalloc = 0;
7001da177e4SLinus Torvalds 				}
7011da177e4SLinus Torvalds 				else
7021da177e4SLinus Torvalds 				{
7031da177e4SLinus Torvalds 					numalloc -= elen;
7041da177e4SLinus Torvalds 					if (*endnum > (i+1))
7051da177e4SLinus Torvalds 						memmove(&laarr[i], &laarr[i+1],
7061da177e4SLinus Torvalds 							sizeof(long_ad) * (*endnum - (i+1)));
7071da177e4SLinus Torvalds 					i --;
7081da177e4SLinus Torvalds 					(*endnum) --;
7091da177e4SLinus Torvalds 				}
7101da177e4SLinus Torvalds 			}
7111da177e4SLinus Torvalds 			UDF_I_LENEXTENTS(inode) += numalloc << inode->i_sb->s_blocksize_bits;
7121da177e4SLinus Torvalds 		}
7131da177e4SLinus Torvalds 	}
7141da177e4SLinus Torvalds }
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds static void udf_merge_extents(struct inode *inode,
7171da177e4SLinus Torvalds 	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
7181da177e4SLinus Torvalds {
7191da177e4SLinus Torvalds 	int i;
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds 	for (i=0; i<(*endnum-1); i++)
7221da177e4SLinus Torvalds 	{
7231da177e4SLinus Torvalds 		if ((laarr[i].extLength >> 30) == (laarr[i+1].extLength >> 30))
7241da177e4SLinus Torvalds 		{
7251da177e4SLinus Torvalds 			if (((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) ||
7261da177e4SLinus Torvalds 				((laarr[i+1].extLocation.logicalBlockNum - laarr[i].extLocation.logicalBlockNum) ==
7271da177e4SLinus Torvalds 				(((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7281da177e4SLinus Torvalds 				inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits)))
7291da177e4SLinus Torvalds 			{
7301da177e4SLinus Torvalds 				if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7311da177e4SLinus Torvalds 					(laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) +
7321da177e4SLinus Torvalds 					inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK)
7331da177e4SLinus Torvalds 				{
7341da177e4SLinus Torvalds 					laarr[i+1].extLength = (laarr[i+1].extLength -
7351da177e4SLinus Torvalds 						(laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7361da177e4SLinus Torvalds 						UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
7371da177e4SLinus Torvalds 					laarr[i].extLength = (laarr[i].extLength & UDF_EXTENT_FLAG_MASK) +
7381da177e4SLinus Torvalds 						(UDF_EXTENT_LENGTH_MASK + 1) - inode->i_sb->s_blocksize;
7391da177e4SLinus Torvalds 					laarr[i+1].extLocation.logicalBlockNum =
7401da177e4SLinus Torvalds 						laarr[i].extLocation.logicalBlockNum +
7411da177e4SLinus Torvalds 						((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >>
7421da177e4SLinus Torvalds 							inode->i_sb->s_blocksize_bits);
7431da177e4SLinus Torvalds 				}
7441da177e4SLinus Torvalds 				else
7451da177e4SLinus Torvalds 				{
7461da177e4SLinus Torvalds 					laarr[i].extLength = laarr[i+1].extLength +
7471da177e4SLinus Torvalds 						(((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7481da177e4SLinus Torvalds 						inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
7491da177e4SLinus Torvalds 					if (*endnum > (i+2))
7501da177e4SLinus Torvalds 						memmove(&laarr[i+1], &laarr[i+2],
7511da177e4SLinus Torvalds 							sizeof(long_ad) * (*endnum - (i+2)));
7521da177e4SLinus Torvalds 					i --;
7531da177e4SLinus Torvalds 					(*endnum) --;
7541da177e4SLinus Torvalds 				}
7551da177e4SLinus Torvalds 			}
7561da177e4SLinus Torvalds 		}
7571da177e4SLinus Torvalds 		else if (((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
7581da177e4SLinus Torvalds 			((laarr[i+1].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)))
7591da177e4SLinus Torvalds 		{
7601da177e4SLinus Torvalds 			udf_free_blocks(inode->i_sb, inode, laarr[i].extLocation, 0,
7611da177e4SLinus Torvalds 				((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7621da177e4SLinus Torvalds 				inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
7631da177e4SLinus Torvalds 			laarr[i].extLocation.logicalBlockNum = 0;
7641da177e4SLinus Torvalds 			laarr[i].extLocation.partitionReferenceNum = 0;
7651da177e4SLinus Torvalds 
7661da177e4SLinus Torvalds 			if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7671da177e4SLinus Torvalds 				(laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) +
7681da177e4SLinus Torvalds 				inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK)
7691da177e4SLinus Torvalds 			{
7701da177e4SLinus Torvalds 				laarr[i+1].extLength = (laarr[i+1].extLength -
7711da177e4SLinus Torvalds 					(laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7721da177e4SLinus Torvalds 					UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
7731da177e4SLinus Torvalds 				laarr[i].extLength = (laarr[i].extLength & UDF_EXTENT_FLAG_MASK) +
7741da177e4SLinus Torvalds 					(UDF_EXTENT_LENGTH_MASK + 1) - inode->i_sb->s_blocksize;
7751da177e4SLinus Torvalds 			}
7761da177e4SLinus Torvalds 			else
7771da177e4SLinus Torvalds 			{
7781da177e4SLinus Torvalds 				laarr[i].extLength = laarr[i+1].extLength +
7791da177e4SLinus Torvalds 					(((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7801da177e4SLinus Torvalds 					inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
7811da177e4SLinus Torvalds 				if (*endnum > (i+2))
7821da177e4SLinus Torvalds 					memmove(&laarr[i+1], &laarr[i+2],
7831da177e4SLinus Torvalds 						sizeof(long_ad) * (*endnum - (i+2)));
7841da177e4SLinus Torvalds 				i --;
7851da177e4SLinus Torvalds 				(*endnum) --;
7861da177e4SLinus Torvalds 			}
7871da177e4SLinus Torvalds 		}
7881da177e4SLinus Torvalds 		else if ((laarr[i].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
7891da177e4SLinus Torvalds 		{
7901da177e4SLinus Torvalds 			udf_free_blocks(inode->i_sb, inode, laarr[i].extLocation, 0,
7911da177e4SLinus Torvalds 				((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
7921da177e4SLinus Torvalds 			       inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
7931da177e4SLinus Torvalds 			laarr[i].extLocation.logicalBlockNum = 0;
7941da177e4SLinus Torvalds 			laarr[i].extLocation.partitionReferenceNum = 0;
7951da177e4SLinus Torvalds 			laarr[i].extLength = (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) |
7961da177e4SLinus Torvalds 				EXT_NOT_RECORDED_NOT_ALLOCATED;
7971da177e4SLinus Torvalds 		}
7981da177e4SLinus Torvalds 	}
7991da177e4SLinus Torvalds }
8001da177e4SLinus Torvalds 
8011da177e4SLinus Torvalds static void udf_update_extents(struct inode *inode,
8021da177e4SLinus Torvalds 	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
803*ff116fc8SJan Kara 	struct extent_position *epos)
8041da177e4SLinus Torvalds {
8051da177e4SLinus Torvalds 	int start = 0, i;
8061da177e4SLinus Torvalds 	kernel_lb_addr tmploc;
8071da177e4SLinus Torvalds 	uint32_t tmplen;
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 	if (startnum > endnum)
8101da177e4SLinus Torvalds 	{
8111da177e4SLinus Torvalds 		for (i=0; i<(startnum-endnum); i++)
812*ff116fc8SJan Kara 			udf_delete_aext(inode, *epos, laarr[i].extLocation,
813*ff116fc8SJan Kara 				laarr[i].extLength);
8141da177e4SLinus Torvalds 	}
8151da177e4SLinus Torvalds 	else if (startnum < endnum)
8161da177e4SLinus Torvalds 	{
8171da177e4SLinus Torvalds 		for (i=0; i<(endnum-startnum); i++)
8181da177e4SLinus Torvalds 		{
819*ff116fc8SJan Kara 			udf_insert_aext(inode, *epos, laarr[i].extLocation,
820*ff116fc8SJan Kara 				laarr[i].extLength);
821*ff116fc8SJan Kara 			udf_next_aext(inode, epos, &laarr[i].extLocation,
822*ff116fc8SJan Kara 				&laarr[i].extLength, 1);
8231da177e4SLinus Torvalds 			start ++;
8241da177e4SLinus Torvalds 		}
8251da177e4SLinus Torvalds 	}
8261da177e4SLinus Torvalds 
8271da177e4SLinus Torvalds 	for (i=start; i<endnum; i++)
8281da177e4SLinus Torvalds 	{
829*ff116fc8SJan Kara 		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
830*ff116fc8SJan Kara 		udf_write_aext(inode, epos, laarr[i].extLocation,
831*ff116fc8SJan Kara 			laarr[i].extLength, 1);
8321da177e4SLinus Torvalds 	}
8331da177e4SLinus Torvalds }
8341da177e4SLinus Torvalds 
8351da177e4SLinus Torvalds struct buffer_head * udf_bread(struct inode * inode, int block,
8361da177e4SLinus Torvalds 	int create, int * err)
8371da177e4SLinus Torvalds {
8381da177e4SLinus Torvalds 	struct buffer_head * bh = NULL;
8391da177e4SLinus Torvalds 
8401da177e4SLinus Torvalds 	bh = udf_getblk(inode, block, create, err);
8411da177e4SLinus Torvalds 	if (!bh)
8421da177e4SLinus Torvalds 		return NULL;
8431da177e4SLinus Torvalds 
8441da177e4SLinus Torvalds 	if (buffer_uptodate(bh))
8451da177e4SLinus Torvalds 		return bh;
8461da177e4SLinus Torvalds 	ll_rw_block(READ, 1, &bh);
8471da177e4SLinus Torvalds 	wait_on_buffer(bh);
8481da177e4SLinus Torvalds 	if (buffer_uptodate(bh))
8491da177e4SLinus Torvalds 		return bh;
8501da177e4SLinus Torvalds 	brelse(bh);
8511da177e4SLinus Torvalds 	*err = -EIO;
8521da177e4SLinus Torvalds 	return NULL;
8531da177e4SLinus Torvalds }
8541da177e4SLinus Torvalds 
8551da177e4SLinus Torvalds void udf_truncate(struct inode * inode)
8561da177e4SLinus Torvalds {
8571da177e4SLinus Torvalds 	int offset;
8581da177e4SLinus Torvalds 	int err;
8591da177e4SLinus Torvalds 
8601da177e4SLinus Torvalds 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
8611da177e4SLinus Torvalds 			S_ISLNK(inode->i_mode)))
8621da177e4SLinus Torvalds 		return;
8631da177e4SLinus Torvalds 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
8641da177e4SLinus Torvalds 		return;
8651da177e4SLinus Torvalds 
8661da177e4SLinus Torvalds 	lock_kernel();
8671da177e4SLinus Torvalds 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
8681da177e4SLinus Torvalds 	{
8691da177e4SLinus Torvalds 		if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
8701da177e4SLinus Torvalds 			inode->i_size))
8711da177e4SLinus Torvalds 		{
8721da177e4SLinus Torvalds 			udf_expand_file_adinicb(inode, inode->i_size, &err);
8731da177e4SLinus Torvalds 			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
8741da177e4SLinus Torvalds 			{
8751da177e4SLinus Torvalds 				inode->i_size = UDF_I_LENALLOC(inode);
8761da177e4SLinus Torvalds 				unlock_kernel();
8771da177e4SLinus Torvalds 				return;
8781da177e4SLinus Torvalds 			}
8791da177e4SLinus Torvalds 			else
8801da177e4SLinus Torvalds 				udf_truncate_extents(inode);
8811da177e4SLinus Torvalds 		}
8821da177e4SLinus Torvalds 		else
8831da177e4SLinus Torvalds 		{
8841da177e4SLinus Torvalds 			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
8851da177e4SLinus Torvalds 			memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
8861da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) = inode->i_size;
8871da177e4SLinus Torvalds 		}
8881da177e4SLinus Torvalds 	}
8891da177e4SLinus Torvalds 	else
8901da177e4SLinus Torvalds 	{
8911da177e4SLinus Torvalds 		block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block);
8921da177e4SLinus Torvalds 		udf_truncate_extents(inode);
8931da177e4SLinus Torvalds 	}
8941da177e4SLinus Torvalds 
8951da177e4SLinus Torvalds 	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
8961da177e4SLinus Torvalds 	if (IS_SYNC(inode))
8971da177e4SLinus Torvalds 		udf_sync_inode (inode);
8981da177e4SLinus Torvalds 	else
8991da177e4SLinus Torvalds 		mark_inode_dirty(inode);
9001da177e4SLinus Torvalds 	unlock_kernel();
9011da177e4SLinus Torvalds }
9021da177e4SLinus Torvalds 
9031da177e4SLinus Torvalds static void
9041da177e4SLinus Torvalds __udf_read_inode(struct inode *inode)
9051da177e4SLinus Torvalds {
9061da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
9071da177e4SLinus Torvalds 	struct fileEntry *fe;
9081da177e4SLinus Torvalds 	uint16_t ident;
9091da177e4SLinus Torvalds 
9101da177e4SLinus Torvalds 	/*
9111da177e4SLinus Torvalds 	 * Set defaults, but the inode is still incomplete!
9121da177e4SLinus Torvalds 	 * Note: get_new_inode() sets the following on a new inode:
9131da177e4SLinus Torvalds 	 *      i_sb = sb
9141da177e4SLinus Torvalds 	 *      i_no = ino
9151da177e4SLinus Torvalds 	 *      i_flags = sb->s_flags
9161da177e4SLinus Torvalds 	 *      i_state = 0
9171da177e4SLinus Torvalds 	 * clean_inode(): zero fills and sets
9181da177e4SLinus Torvalds 	 *      i_count = 1
9191da177e4SLinus Torvalds 	 *      i_nlink = 1
9201da177e4SLinus Torvalds 	 *      i_op = NULL;
9211da177e4SLinus Torvalds 	 */
9221da177e4SLinus Torvalds 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
9231da177e4SLinus Torvalds 
9241da177e4SLinus Torvalds 	if (!bh)
9251da177e4SLinus Torvalds 	{
9261da177e4SLinus Torvalds 		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
9271da177e4SLinus Torvalds 			inode->i_ino);
9281da177e4SLinus Torvalds 		make_bad_inode(inode);
9291da177e4SLinus Torvalds 		return;
9301da177e4SLinus Torvalds 	}
9311da177e4SLinus Torvalds 
9321da177e4SLinus Torvalds 	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
9331da177e4SLinus Torvalds 		ident != TAG_IDENT_USE)
9341da177e4SLinus Torvalds 	{
9351da177e4SLinus Torvalds 		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
9361da177e4SLinus Torvalds 			inode->i_ino, ident);
9371da177e4SLinus Torvalds 		udf_release_data(bh);
9381da177e4SLinus Torvalds 		make_bad_inode(inode);
9391da177e4SLinus Torvalds 		return;
9401da177e4SLinus Torvalds 	}
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
9431da177e4SLinus Torvalds 
9441da177e4SLinus Torvalds 	if (le16_to_cpu(fe->icbTag.strategyType) == 4096)
9451da177e4SLinus Torvalds 	{
9461da177e4SLinus Torvalds 		struct buffer_head *ibh = NULL, *nbh = NULL;
9471da177e4SLinus Torvalds 		struct indirectEntry *ie;
9481da177e4SLinus Torvalds 
9491da177e4SLinus Torvalds 		ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident);
9501da177e4SLinus Torvalds 		if (ident == TAG_IDENT_IE)
9511da177e4SLinus Torvalds 		{
9521da177e4SLinus Torvalds 			if (ibh)
9531da177e4SLinus Torvalds 			{
9541da177e4SLinus Torvalds 				kernel_lb_addr loc;
9551da177e4SLinus Torvalds 				ie = (struct indirectEntry *)ibh->b_data;
9561da177e4SLinus Torvalds 
9571da177e4SLinus Torvalds 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
9581da177e4SLinus Torvalds 
9591da177e4SLinus Torvalds 				if (ie->indirectICB.extLength &&
9601da177e4SLinus Torvalds 					(nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
9611da177e4SLinus Torvalds 				{
9621da177e4SLinus Torvalds 					if (ident == TAG_IDENT_FE ||
9631da177e4SLinus Torvalds 						ident == TAG_IDENT_EFE)
9641da177e4SLinus Torvalds 					{
9651da177e4SLinus Torvalds 						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
9661da177e4SLinus Torvalds 						udf_release_data(bh);
9671da177e4SLinus Torvalds 						udf_release_data(ibh);
9681da177e4SLinus Torvalds 						udf_release_data(nbh);
9691da177e4SLinus Torvalds 						__udf_read_inode(inode);
9701da177e4SLinus Torvalds 						return;
9711da177e4SLinus Torvalds 					}
9721da177e4SLinus Torvalds 					else
9731da177e4SLinus Torvalds 					{
9741da177e4SLinus Torvalds 						udf_release_data(nbh);
9751da177e4SLinus Torvalds 						udf_release_data(ibh);
9761da177e4SLinus Torvalds 					}
9771da177e4SLinus Torvalds 				}
9781da177e4SLinus Torvalds 				else
9791da177e4SLinus Torvalds 					udf_release_data(ibh);
9801da177e4SLinus Torvalds 			}
9811da177e4SLinus Torvalds 		}
9821da177e4SLinus Torvalds 		else
9831da177e4SLinus Torvalds 			udf_release_data(ibh);
9841da177e4SLinus Torvalds 	}
9851da177e4SLinus Torvalds 	else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
9861da177e4SLinus Torvalds 	{
9871da177e4SLinus Torvalds 		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
9881da177e4SLinus Torvalds 			le16_to_cpu(fe->icbTag.strategyType));
9891da177e4SLinus Torvalds 		udf_release_data(bh);
9901da177e4SLinus Torvalds 		make_bad_inode(inode);
9911da177e4SLinus Torvalds 		return;
9921da177e4SLinus Torvalds 	}
9931da177e4SLinus Torvalds 	udf_fill_inode(inode, bh);
9941da177e4SLinus Torvalds 	udf_release_data(bh);
9951da177e4SLinus Torvalds }
9961da177e4SLinus Torvalds 
9971da177e4SLinus Torvalds static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
9981da177e4SLinus Torvalds {
9991da177e4SLinus Torvalds 	struct fileEntry *fe;
10001da177e4SLinus Torvalds 	struct extendedFileEntry *efe;
10011da177e4SLinus Torvalds 	time_t convtime;
10021da177e4SLinus Torvalds 	long convtime_usec;
10031da177e4SLinus Torvalds 	int offset;
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
10061da177e4SLinus Torvalds 	efe = (struct extendedFileEntry *)bh->b_data;
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds 	if (le16_to_cpu(fe->icbTag.strategyType) == 4)
10091da177e4SLinus Torvalds 		UDF_I_STRAT4096(inode) = 0;
10101da177e4SLinus Torvalds 	else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */
10111da177e4SLinus Torvalds 		UDF_I_STRAT4096(inode) = 1;
10121da177e4SLinus Torvalds 
10131da177e4SLinus Torvalds 	UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK;
10141da177e4SLinus Torvalds 	UDF_I_UNIQUE(inode) = 0;
10151da177e4SLinus Torvalds 	UDF_I_LENEATTR(inode) = 0;
10161da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = 0;
10171da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
10181da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
10191da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
10201da177e4SLinus Torvalds 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
10211da177e4SLinus Torvalds 	{
10221da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 1;
10231da177e4SLinus Torvalds 		UDF_I_USE(inode) = 0;
10241da177e4SLinus Torvalds 		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
10251da177e4SLinus Torvalds 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
10261da177e4SLinus Torvalds 	}
10271da177e4SLinus Torvalds 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
10281da177e4SLinus Torvalds 	{
10291da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 0;
10301da177e4SLinus Torvalds 		UDF_I_USE(inode) = 0;
10311da177e4SLinus Torvalds 		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
10321da177e4SLinus Torvalds 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
10331da177e4SLinus Torvalds 	}
10341da177e4SLinus Torvalds 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
10351da177e4SLinus Torvalds 	{
10361da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 0;
10371da177e4SLinus Torvalds 		UDF_I_USE(inode) = 1;
10381da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) =
10391da177e4SLinus Torvalds 			le32_to_cpu(
10401da177e4SLinus Torvalds 				((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
10411da177e4SLinus Torvalds 		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
10421da177e4SLinus Torvalds 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
10431da177e4SLinus Torvalds 		return;
10441da177e4SLinus Torvalds 	}
10451da177e4SLinus Torvalds 
10461da177e4SLinus Torvalds 	inode->i_uid = le32_to_cpu(fe->uid);
10474d6660ebSPhillip Susi 	if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb,
10484d6660ebSPhillip Susi 					UDF_FLAG_UID_IGNORE))
10494d6660ebSPhillip Susi 		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
10501da177e4SLinus Torvalds 
10511da177e4SLinus Torvalds 	inode->i_gid = le32_to_cpu(fe->gid);
10524d6660ebSPhillip Susi 	if (inode->i_gid == -1 || UDF_QUERY_FLAG(inode->i_sb,
10534d6660ebSPhillip Susi 					UDF_FLAG_GID_IGNORE))
10544d6660ebSPhillip Susi 		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
10571da177e4SLinus Torvalds 	if (!inode->i_nlink)
10581da177e4SLinus Torvalds 		inode->i_nlink = 1;
10591da177e4SLinus Torvalds 
10601da177e4SLinus Torvalds 	inode->i_size = le64_to_cpu(fe->informationLength);
10611da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = inode->i_size;
10621da177e4SLinus Torvalds 
10631da177e4SLinus Torvalds 	inode->i_mode = udf_convert_permissions(fe);
10641da177e4SLinus Torvalds 	inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds 	if (UDF_I_EFE(inode) == 0)
10671da177e4SLinus Torvalds 	{
10681da177e4SLinus Torvalds 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
10691da177e4SLinus Torvalds 			(inode->i_sb->s_blocksize_bits - 9);
10701da177e4SLinus Torvalds 
10711da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
10721da177e4SLinus Torvalds 			lets_to_cpu(fe->accessTime)) )
10731da177e4SLinus Torvalds 		{
10741da177e4SLinus Torvalds 			inode->i_atime.tv_sec = convtime;
10751da177e4SLinus Torvalds 			inode->i_atime.tv_nsec = convtime_usec * 1000;
10761da177e4SLinus Torvalds 		}
10771da177e4SLinus Torvalds 		else
10781da177e4SLinus Torvalds 		{
10791da177e4SLinus Torvalds 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
10801da177e4SLinus Torvalds 		}
10811da177e4SLinus Torvalds 
10821da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
10831da177e4SLinus Torvalds 			lets_to_cpu(fe->modificationTime)) )
10841da177e4SLinus Torvalds 		{
10851da177e4SLinus Torvalds 			inode->i_mtime.tv_sec = convtime;
10861da177e4SLinus Torvalds 			inode->i_mtime.tv_nsec = convtime_usec * 1000;
10871da177e4SLinus Torvalds 		}
10881da177e4SLinus Torvalds 		else
10891da177e4SLinus Torvalds 		{
10901da177e4SLinus Torvalds 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
10911da177e4SLinus Torvalds 		}
10921da177e4SLinus Torvalds 
10931da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
10941da177e4SLinus Torvalds 			lets_to_cpu(fe->attrTime)) )
10951da177e4SLinus Torvalds 		{
10961da177e4SLinus Torvalds 			inode->i_ctime.tv_sec = convtime;
10971da177e4SLinus Torvalds 			inode->i_ctime.tv_nsec = convtime_usec * 1000;
10981da177e4SLinus Torvalds 		}
10991da177e4SLinus Torvalds 		else
11001da177e4SLinus Torvalds 		{
11011da177e4SLinus Torvalds 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
11021da177e4SLinus Torvalds 		}
11031da177e4SLinus Torvalds 
11041da177e4SLinus Torvalds 		UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
11051da177e4SLinus Torvalds 		UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
11061da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
11071da177e4SLinus Torvalds 		offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
11081da177e4SLinus Torvalds 	}
11091da177e4SLinus Torvalds 	else
11101da177e4SLinus Torvalds 	{
11111da177e4SLinus Torvalds 		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
11121da177e4SLinus Torvalds 			(inode->i_sb->s_blocksize_bits - 9);
11131da177e4SLinus Torvalds 
11141da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
11151da177e4SLinus Torvalds 			lets_to_cpu(efe->accessTime)) )
11161da177e4SLinus Torvalds 		{
11171da177e4SLinus Torvalds 			inode->i_atime.tv_sec = convtime;
11181da177e4SLinus Torvalds 			inode->i_atime.tv_nsec = convtime_usec * 1000;
11191da177e4SLinus Torvalds 		}
11201da177e4SLinus Torvalds 		else
11211da177e4SLinus Torvalds 		{
11221da177e4SLinus Torvalds 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
11231da177e4SLinus Torvalds 		}
11241da177e4SLinus Torvalds 
11251da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
11261da177e4SLinus Torvalds 			lets_to_cpu(efe->modificationTime)) )
11271da177e4SLinus Torvalds 		{
11281da177e4SLinus Torvalds 			inode->i_mtime.tv_sec = convtime;
11291da177e4SLinus Torvalds 			inode->i_mtime.tv_nsec = convtime_usec * 1000;
11301da177e4SLinus Torvalds 		}
11311da177e4SLinus Torvalds 		else
11321da177e4SLinus Torvalds 		{
11331da177e4SLinus Torvalds 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
11341da177e4SLinus Torvalds 		}
11351da177e4SLinus Torvalds 
11361da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
11371da177e4SLinus Torvalds 			lets_to_cpu(efe->createTime)) )
11381da177e4SLinus Torvalds 		{
11391da177e4SLinus Torvalds 			UDF_I_CRTIME(inode).tv_sec = convtime;
11401da177e4SLinus Torvalds 			UDF_I_CRTIME(inode).tv_nsec = convtime_usec * 1000;
11411da177e4SLinus Torvalds 		}
11421da177e4SLinus Torvalds 		else
11431da177e4SLinus Torvalds 		{
11441da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb);
11451da177e4SLinus Torvalds 		}
11461da177e4SLinus Torvalds 
11471da177e4SLinus Torvalds 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
11481da177e4SLinus Torvalds 			lets_to_cpu(efe->attrTime)) )
11491da177e4SLinus Torvalds 		{
11501da177e4SLinus Torvalds 			inode->i_ctime.tv_sec = convtime;
11511da177e4SLinus Torvalds 			inode->i_ctime.tv_nsec = convtime_usec * 1000;
11521da177e4SLinus Torvalds 		}
11531da177e4SLinus Torvalds 		else
11541da177e4SLinus Torvalds 		{
11551da177e4SLinus Torvalds 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
11561da177e4SLinus Torvalds 		}
11571da177e4SLinus Torvalds 
11581da177e4SLinus Torvalds 		UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);
11591da177e4SLinus Torvalds 		UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
11601da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
11611da177e4SLinus Torvalds 		offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
11621da177e4SLinus Torvalds 	}
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds 	switch (fe->icbTag.fileType)
11651da177e4SLinus Torvalds 	{
11661da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_DIRECTORY:
11671da177e4SLinus Torvalds 		{
11681da177e4SLinus Torvalds 			inode->i_op = &udf_dir_inode_operations;
11691da177e4SLinus Torvalds 			inode->i_fop = &udf_dir_operations;
11701da177e4SLinus Torvalds 			inode->i_mode |= S_IFDIR;
1171d8c76e6fSDave Hansen 			inc_nlink(inode);
11721da177e4SLinus Torvalds 			break;
11731da177e4SLinus Torvalds 		}
11741da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_REALTIME:
11751da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_REGULAR:
11761da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_UNDEF:
11771da177e4SLinus Torvalds 		{
11781da177e4SLinus Torvalds 			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
11791da177e4SLinus Torvalds 				inode->i_data.a_ops = &udf_adinicb_aops;
11801da177e4SLinus Torvalds 			else
11811da177e4SLinus Torvalds 				inode->i_data.a_ops = &udf_aops;
11821da177e4SLinus Torvalds 			inode->i_op = &udf_file_inode_operations;
11831da177e4SLinus Torvalds 			inode->i_fop = &udf_file_operations;
11841da177e4SLinus Torvalds 			inode->i_mode |= S_IFREG;
11851da177e4SLinus Torvalds 			break;
11861da177e4SLinus Torvalds 		}
11871da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_BLOCK:
11881da177e4SLinus Torvalds 		{
11891da177e4SLinus Torvalds 			inode->i_mode |= S_IFBLK;
11901da177e4SLinus Torvalds 			break;
11911da177e4SLinus Torvalds 		}
11921da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_CHAR:
11931da177e4SLinus Torvalds 		{
11941da177e4SLinus Torvalds 			inode->i_mode |= S_IFCHR;
11951da177e4SLinus Torvalds 			break;
11961da177e4SLinus Torvalds 		}
11971da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_FIFO:
11981da177e4SLinus Torvalds 		{
11991da177e4SLinus Torvalds 			init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
12001da177e4SLinus Torvalds 			break;
12011da177e4SLinus Torvalds 		}
12021da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_SOCKET:
12031da177e4SLinus Torvalds 		{
12041da177e4SLinus Torvalds 			init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
12051da177e4SLinus Torvalds 			break;
12061da177e4SLinus Torvalds 		}
12071da177e4SLinus Torvalds 		case ICBTAG_FILE_TYPE_SYMLINK:
12081da177e4SLinus Torvalds 		{
12091da177e4SLinus Torvalds 			inode->i_data.a_ops = &udf_symlink_aops;
12101da177e4SLinus Torvalds 			inode->i_op = &page_symlink_inode_operations;
12111da177e4SLinus Torvalds 			inode->i_mode = S_IFLNK|S_IRWXUGO;
12121da177e4SLinus Torvalds 			break;
12131da177e4SLinus Torvalds 		}
12141da177e4SLinus Torvalds 		default:
12151da177e4SLinus Torvalds 		{
12161da177e4SLinus Torvalds 			printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n",
12171da177e4SLinus Torvalds 				inode->i_ino, fe->icbTag.fileType);
12181da177e4SLinus Torvalds 			make_bad_inode(inode);
12191da177e4SLinus Torvalds 			return;
12201da177e4SLinus Torvalds 		}
12211da177e4SLinus Torvalds 	}
12221da177e4SLinus Torvalds 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
12231da177e4SLinus Torvalds 	{
12241da177e4SLinus Torvalds 		struct deviceSpec *dsea =
12251da177e4SLinus Torvalds 			(struct deviceSpec *)
12261da177e4SLinus Torvalds 				udf_get_extendedattr(inode, 12, 1);
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 		if (dsea)
12291da177e4SLinus Torvalds 		{
12301da177e4SLinus Torvalds 			init_special_inode(inode, inode->i_mode, MKDEV(
12311da177e4SLinus Torvalds 				le32_to_cpu(dsea->majorDeviceIdent),
12321da177e4SLinus Torvalds 				le32_to_cpu(dsea->minorDeviceIdent)));
12331da177e4SLinus Torvalds 			/* Developer ID ??? */
12341da177e4SLinus Torvalds 		}
12351da177e4SLinus Torvalds 		else
12361da177e4SLinus Torvalds 		{
12371da177e4SLinus Torvalds 			make_bad_inode(inode);
12381da177e4SLinus Torvalds 		}
12391da177e4SLinus Torvalds 	}
12401da177e4SLinus Torvalds }
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds static mode_t
12431da177e4SLinus Torvalds udf_convert_permissions(struct fileEntry *fe)
12441da177e4SLinus Torvalds {
12451da177e4SLinus Torvalds 	mode_t mode;
12461da177e4SLinus Torvalds 	uint32_t permissions;
12471da177e4SLinus Torvalds 	uint32_t flags;
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds 	permissions = le32_to_cpu(fe->permissions);
12501da177e4SLinus Torvalds 	flags = le16_to_cpu(fe->icbTag.flags);
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	mode =	(( permissions      ) & S_IRWXO) |
12531da177e4SLinus Torvalds 		(( permissions >> 2 ) & S_IRWXG) |
12541da177e4SLinus Torvalds 		(( permissions >> 4 ) & S_IRWXU) |
12551da177e4SLinus Torvalds 		(( flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) |
12561da177e4SLinus Torvalds 		(( flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) |
12571da177e4SLinus Torvalds 		(( flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0);
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 	return mode;
12601da177e4SLinus Torvalds }
12611da177e4SLinus Torvalds 
12621da177e4SLinus Torvalds /*
12631da177e4SLinus Torvalds  * udf_write_inode
12641da177e4SLinus Torvalds  *
12651da177e4SLinus Torvalds  * PURPOSE
12661da177e4SLinus Torvalds  *	Write out the specified inode.
12671da177e4SLinus Torvalds  *
12681da177e4SLinus Torvalds  * DESCRIPTION
12691da177e4SLinus Torvalds  *	This routine is called whenever an inode is synced.
12701da177e4SLinus Torvalds  *	Currently this routine is just a placeholder.
12711da177e4SLinus Torvalds  *
12721da177e4SLinus Torvalds  * HISTORY
12731da177e4SLinus Torvalds  *	July 1, 1997 - Andrew E. Mileski
12741da177e4SLinus Torvalds  *	Written, tested, and released.
12751da177e4SLinus Torvalds  */
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds int udf_write_inode(struct inode * inode, int sync)
12781da177e4SLinus Torvalds {
12791da177e4SLinus Torvalds 	int ret;
12801da177e4SLinus Torvalds 	lock_kernel();
12811da177e4SLinus Torvalds 	ret = udf_update_inode(inode, sync);
12821da177e4SLinus Torvalds 	unlock_kernel();
12831da177e4SLinus Torvalds 	return ret;
12841da177e4SLinus Torvalds }
12851da177e4SLinus Torvalds 
12861da177e4SLinus Torvalds int udf_sync_inode(struct inode * inode)
12871da177e4SLinus Torvalds {
12881da177e4SLinus Torvalds 	return udf_update_inode(inode, 1);
12891da177e4SLinus Torvalds }
12901da177e4SLinus Torvalds 
12911da177e4SLinus Torvalds static int
12921da177e4SLinus Torvalds udf_update_inode(struct inode *inode, int do_sync)
12931da177e4SLinus Torvalds {
12941da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
12951da177e4SLinus Torvalds 	struct fileEntry *fe;
12961da177e4SLinus Torvalds 	struct extendedFileEntry *efe;
12971da177e4SLinus Torvalds 	uint32_t udfperms;
12981da177e4SLinus Torvalds 	uint16_t icbflags;
12991da177e4SLinus Torvalds 	uint16_t crclen;
13001da177e4SLinus Torvalds 	int i;
13011da177e4SLinus Torvalds 	kernel_timestamp cpu_time;
13021da177e4SLinus Torvalds 	int err = 0;
13031da177e4SLinus Torvalds 
13041da177e4SLinus Torvalds 	bh = udf_tread(inode->i_sb,
13051da177e4SLinus Torvalds 		udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
13061da177e4SLinus Torvalds 
13071da177e4SLinus Torvalds 	if (!bh)
13081da177e4SLinus Torvalds 	{
13091da177e4SLinus Torvalds 		udf_debug("bread failure\n");
13101da177e4SLinus Torvalds 		return -EIO;
13111da177e4SLinus Torvalds 	}
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
13141da177e4SLinus Torvalds 
13151da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
13161da177e4SLinus Torvalds 	efe = (struct extendedFileEntry *)bh->b_data;
13171da177e4SLinus Torvalds 
13181da177e4SLinus Torvalds 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
13191da177e4SLinus Torvalds 	{
13201da177e4SLinus Torvalds 		struct unallocSpaceEntry *use =
13211da177e4SLinus Torvalds 			(struct unallocSpaceEntry *)bh->b_data;
13221da177e4SLinus Torvalds 
13231da177e4SLinus Torvalds 		use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
13241da177e4SLinus Torvalds 		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
13251da177e4SLinus Torvalds 		crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
13261da177e4SLinus Torvalds 			sizeof(tag);
13271da177e4SLinus Torvalds 		use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
13281da177e4SLinus Torvalds 		use->descTag.descCRCLength = cpu_to_le16(crclen);
13291da177e4SLinus Torvalds 		use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds 		use->descTag.tagChecksum = 0;
13321da177e4SLinus Torvalds 		for (i=0; i<16; i++)
13331da177e4SLinus Torvalds 			if (i != 4)
13341da177e4SLinus Torvalds 				use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i];
13351da177e4SLinus Torvalds 
13361da177e4SLinus Torvalds 		mark_buffer_dirty(bh);
13371da177e4SLinus Torvalds 		udf_release_data(bh);
13381da177e4SLinus Torvalds 		return err;
13391da177e4SLinus Torvalds 	}
13401da177e4SLinus Torvalds 
13414d6660ebSPhillip Susi 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
13424d6660ebSPhillip Susi 		fe->uid = cpu_to_le32(-1);
13430e6b3e5eSPhillip Susi 	else fe->uid = cpu_to_le32(inode->i_uid);
13441da177e4SLinus Torvalds 
13454d6660ebSPhillip Susi 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
13464d6660ebSPhillip Susi 		fe->gid = cpu_to_le32(-1);
13470e6b3e5eSPhillip Susi 	else fe->gid = cpu_to_le32(inode->i_gid);
13481da177e4SLinus Torvalds 
13491da177e4SLinus Torvalds 	udfperms =	((inode->i_mode & S_IRWXO)     ) |
13501da177e4SLinus Torvalds 			((inode->i_mode & S_IRWXG) << 2) |
13511da177e4SLinus Torvalds 			((inode->i_mode & S_IRWXU) << 4);
13521da177e4SLinus Torvalds 
13531da177e4SLinus Torvalds 	udfperms |=	(le32_to_cpu(fe->permissions) &
13541da177e4SLinus Torvalds 			(FE_PERM_O_DELETE | FE_PERM_O_CHATTR |
13551da177e4SLinus Torvalds 			 FE_PERM_G_DELETE | FE_PERM_G_CHATTR |
13561da177e4SLinus Torvalds 			 FE_PERM_U_DELETE | FE_PERM_U_CHATTR));
13571da177e4SLinus Torvalds 	fe->permissions = cpu_to_le32(udfperms);
13581da177e4SLinus Torvalds 
13591da177e4SLinus Torvalds 	if (S_ISDIR(inode->i_mode))
13601da177e4SLinus Torvalds 		fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
13611da177e4SLinus Torvalds 	else
13621da177e4SLinus Torvalds 		fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
13631da177e4SLinus Torvalds 
13641da177e4SLinus Torvalds 	fe->informationLength = cpu_to_le64(inode->i_size);
13651da177e4SLinus Torvalds 
13661da177e4SLinus Torvalds 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
13671da177e4SLinus Torvalds 	{
13681da177e4SLinus Torvalds 		regid *eid;
13691da177e4SLinus Torvalds 		struct deviceSpec *dsea =
13701da177e4SLinus Torvalds 			(struct deviceSpec *)
13711da177e4SLinus Torvalds 				udf_get_extendedattr(inode, 12, 1);
13721da177e4SLinus Torvalds 
13731da177e4SLinus Torvalds 		if (!dsea)
13741da177e4SLinus Torvalds 		{
13751da177e4SLinus Torvalds 			dsea = (struct deviceSpec *)
13761da177e4SLinus Torvalds 				udf_add_extendedattr(inode,
13771da177e4SLinus Torvalds 					sizeof(struct deviceSpec) +
13781da177e4SLinus Torvalds 					sizeof(regid), 12, 0x3);
13791da177e4SLinus Torvalds 			dsea->attrType = cpu_to_le32(12);
13801da177e4SLinus Torvalds 			dsea->attrSubtype = 1;
13811da177e4SLinus Torvalds 			dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) +
13821da177e4SLinus Torvalds 				sizeof(regid));
13831da177e4SLinus Torvalds 			dsea->impUseLength = cpu_to_le32(sizeof(regid));
13841da177e4SLinus Torvalds 		}
13851da177e4SLinus Torvalds 		eid = (regid *)dsea->impUse;
13861da177e4SLinus Torvalds 		memset(eid, 0, sizeof(regid));
13871da177e4SLinus Torvalds 		strcpy(eid->ident, UDF_ID_DEVELOPER);
13881da177e4SLinus Torvalds 		eid->identSuffix[0] = UDF_OS_CLASS_UNIX;
13891da177e4SLinus Torvalds 		eid->identSuffix[1] = UDF_OS_ID_LINUX;
13901da177e4SLinus Torvalds 		dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));
13911da177e4SLinus Torvalds 		dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));
13921da177e4SLinus Torvalds 	}
13931da177e4SLinus Torvalds 
13941da177e4SLinus Torvalds 	if (UDF_I_EFE(inode) == 0)
13951da177e4SLinus Torvalds 	{
13961da177e4SLinus Torvalds 		memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
13971da177e4SLinus Torvalds 		fe->logicalBlocksRecorded = cpu_to_le64(
13981da177e4SLinus Torvalds 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
13991da177e4SLinus Torvalds 			(inode->i_sb->s_blocksize_bits - 9));
14001da177e4SLinus Torvalds 
14011da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
14021da177e4SLinus Torvalds 			fe->accessTime = cpu_to_lets(cpu_time);
14031da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
14041da177e4SLinus Torvalds 			fe->modificationTime = cpu_to_lets(cpu_time);
14051da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
14061da177e4SLinus Torvalds 			fe->attrTime = cpu_to_lets(cpu_time);
14071da177e4SLinus Torvalds 		memset(&(fe->impIdent), 0, sizeof(regid));
14081da177e4SLinus Torvalds 		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
14091da177e4SLinus Torvalds 		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
14101da177e4SLinus Torvalds 		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
14111da177e4SLinus Torvalds 		fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
14121da177e4SLinus Torvalds 		fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
14131da177e4SLinus Torvalds 		fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
14141da177e4SLinus Torvalds 		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
14151da177e4SLinus Torvalds 		crclen = sizeof(struct fileEntry);
14161da177e4SLinus Torvalds 	}
14171da177e4SLinus Torvalds 	else
14181da177e4SLinus Torvalds 	{
14191da177e4SLinus Torvalds 		memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
14201da177e4SLinus Torvalds 		efe->objectSize = cpu_to_le64(inode->i_size);
14211da177e4SLinus Torvalds 		efe->logicalBlocksRecorded = cpu_to_le64(
14221da177e4SLinus Torvalds 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
14231da177e4SLinus Torvalds 			(inode->i_sb->s_blocksize_bits - 9));
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_atime.tv_sec ||
14261da177e4SLinus Torvalds 			(UDF_I_CRTIME(inode).tv_sec == inode->i_atime.tv_sec &&
14271da177e4SLinus Torvalds 			 UDF_I_CRTIME(inode).tv_nsec > inode->i_atime.tv_nsec))
14281da177e4SLinus Torvalds 		{
14291da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_atime;
14301da177e4SLinus Torvalds 		}
14311da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_mtime.tv_sec ||
14321da177e4SLinus Torvalds 			(UDF_I_CRTIME(inode).tv_sec == inode->i_mtime.tv_sec &&
14331da177e4SLinus Torvalds 			 UDF_I_CRTIME(inode).tv_nsec > inode->i_mtime.tv_nsec))
14341da177e4SLinus Torvalds 		{
14351da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_mtime;
14361da177e4SLinus Torvalds 		}
14371da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_ctime.tv_sec ||
14381da177e4SLinus Torvalds 			(UDF_I_CRTIME(inode).tv_sec == inode->i_ctime.tv_sec &&
14391da177e4SLinus Torvalds 			 UDF_I_CRTIME(inode).tv_nsec > inode->i_ctime.tv_nsec))
14401da177e4SLinus Torvalds 		{
14411da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_ctime;
14421da177e4SLinus Torvalds 		}
14431da177e4SLinus Torvalds 
14441da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
14451da177e4SLinus Torvalds 			efe->accessTime = cpu_to_lets(cpu_time);
14461da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
14471da177e4SLinus Torvalds 			efe->modificationTime = cpu_to_lets(cpu_time);
14481da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode)))
14491da177e4SLinus Torvalds 			efe->createTime = cpu_to_lets(cpu_time);
14501da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
14511da177e4SLinus Torvalds 			efe->attrTime = cpu_to_lets(cpu_time);
14521da177e4SLinus Torvalds 
14531da177e4SLinus Torvalds 		memset(&(efe->impIdent), 0, sizeof(regid));
14541da177e4SLinus Torvalds 		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
14551da177e4SLinus Torvalds 		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
14561da177e4SLinus Torvalds 		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
14571da177e4SLinus Torvalds 		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
14581da177e4SLinus Torvalds 		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
14591da177e4SLinus Torvalds 		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
14601da177e4SLinus Torvalds 		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
14611da177e4SLinus Torvalds 		crclen = sizeof(struct extendedFileEntry);
14621da177e4SLinus Torvalds 	}
14631da177e4SLinus Torvalds 	if (UDF_I_STRAT4096(inode))
14641da177e4SLinus Torvalds 	{
14651da177e4SLinus Torvalds 		fe->icbTag.strategyType = cpu_to_le16(4096);
14661da177e4SLinus Torvalds 		fe->icbTag.strategyParameter = cpu_to_le16(1);
14671da177e4SLinus Torvalds 		fe->icbTag.numEntries = cpu_to_le16(2);
14681da177e4SLinus Torvalds 	}
14691da177e4SLinus Torvalds 	else
14701da177e4SLinus Torvalds 	{
14711da177e4SLinus Torvalds 		fe->icbTag.strategyType = cpu_to_le16(4);
14721da177e4SLinus Torvalds 		fe->icbTag.numEntries = cpu_to_le16(1);
14731da177e4SLinus Torvalds 	}
14741da177e4SLinus Torvalds 
14751da177e4SLinus Torvalds 	if (S_ISDIR(inode->i_mode))
14761da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY;
14771da177e4SLinus Torvalds 	else if (S_ISREG(inode->i_mode))
14781da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;
14791da177e4SLinus Torvalds 	else if (S_ISLNK(inode->i_mode))
14801da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK;
14811da177e4SLinus Torvalds 	else if (S_ISBLK(inode->i_mode))
14821da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK;
14831da177e4SLinus Torvalds 	else if (S_ISCHR(inode->i_mode))
14841da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
14851da177e4SLinus Torvalds 	else if (S_ISFIFO(inode->i_mode))
14861da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;
14871da177e4SLinus Torvalds 	else if (S_ISSOCK(inode->i_mode))
14881da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;
14891da177e4SLinus Torvalds 
14901da177e4SLinus Torvalds 	icbflags =	UDF_I_ALLOCTYPE(inode) |
14911da177e4SLinus Torvalds 			((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |
14921da177e4SLinus Torvalds 			((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) |
14931da177e4SLinus Torvalds 			((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) |
14941da177e4SLinus Torvalds 			(le16_to_cpu(fe->icbTag.flags) &
14951da177e4SLinus Torvalds 				~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID |
14961da177e4SLinus Torvalds 				ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY));
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds 	fe->icbTag.flags = cpu_to_le16(icbflags);
14991da177e4SLinus Torvalds 	if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
15001da177e4SLinus Torvalds 		fe->descTag.descVersion = cpu_to_le16(3);
15011da177e4SLinus Torvalds 	else
15021da177e4SLinus Torvalds 		fe->descTag.descVersion = cpu_to_le16(2);
15031da177e4SLinus Torvalds 	fe->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
15041da177e4SLinus Torvalds 	fe->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
15051da177e4SLinus Torvalds 	crclen += UDF_I_LENEATTR(inode) + UDF_I_LENALLOC(inode) - sizeof(tag);
15061da177e4SLinus Torvalds 	fe->descTag.descCRCLength = cpu_to_le16(crclen);
15071da177e4SLinus Torvalds 	fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag), crclen, 0));
15081da177e4SLinus Torvalds 
15091da177e4SLinus Torvalds 	fe->descTag.tagChecksum = 0;
15101da177e4SLinus Torvalds 	for (i=0; i<16; i++)
15111da177e4SLinus Torvalds 		if (i != 4)
15121da177e4SLinus Torvalds 			fe->descTag.tagChecksum += ((uint8_t *)&(fe->descTag))[i];
15131da177e4SLinus Torvalds 
15141da177e4SLinus Torvalds 	/* write the data blocks */
15151da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
15161da177e4SLinus Torvalds 	if (do_sync)
15171da177e4SLinus Torvalds 	{
15181da177e4SLinus Torvalds 		sync_dirty_buffer(bh);
15191da177e4SLinus Torvalds 		if (buffer_req(bh) && !buffer_uptodate(bh))
15201da177e4SLinus Torvalds 		{
15211da177e4SLinus Torvalds 			printk("IO error syncing udf inode [%s:%08lx]\n",
15221da177e4SLinus Torvalds 				inode->i_sb->s_id, inode->i_ino);
15231da177e4SLinus Torvalds 			err = -EIO;
15241da177e4SLinus Torvalds 		}
15251da177e4SLinus Torvalds 	}
15261da177e4SLinus Torvalds 	udf_release_data(bh);
15271da177e4SLinus Torvalds 	return err;
15281da177e4SLinus Torvalds }
15291da177e4SLinus Torvalds 
15301da177e4SLinus Torvalds struct inode *
15311da177e4SLinus Torvalds udf_iget(struct super_block *sb, kernel_lb_addr ino)
15321da177e4SLinus Torvalds {
15331da177e4SLinus Torvalds 	unsigned long block = udf_get_lb_pblock(sb, ino, 0);
15341da177e4SLinus Torvalds 	struct inode *inode = iget_locked(sb, block);
15351da177e4SLinus Torvalds 
15361da177e4SLinus Torvalds 	if (!inode)
15371da177e4SLinus Torvalds 		return NULL;
15381da177e4SLinus Torvalds 
15391da177e4SLinus Torvalds 	if (inode->i_state & I_NEW) {
15401da177e4SLinus Torvalds 		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));
15411da177e4SLinus Torvalds 		__udf_read_inode(inode);
15421da177e4SLinus Torvalds 		unlock_new_inode(inode);
15431da177e4SLinus Torvalds 	}
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 	if (is_bad_inode(inode))
15461da177e4SLinus Torvalds 		goto out_iput;
15471da177e4SLinus Torvalds 
15481da177e4SLinus Torvalds 	if (ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum)) {
15491da177e4SLinus Torvalds 		udf_debug("block=%d, partition=%d out of range\n",
15501da177e4SLinus Torvalds 			ino.logicalBlockNum, ino.partitionReferenceNum);
15511da177e4SLinus Torvalds 		make_bad_inode(inode);
15521da177e4SLinus Torvalds 		goto out_iput;
15531da177e4SLinus Torvalds 	}
15541da177e4SLinus Torvalds 
15551da177e4SLinus Torvalds 	return inode;
15561da177e4SLinus Torvalds 
15571da177e4SLinus Torvalds  out_iput:
15581da177e4SLinus Torvalds 	iput(inode);
15591da177e4SLinus Torvalds 	return NULL;
15601da177e4SLinus Torvalds }
15611da177e4SLinus Torvalds 
1562*ff116fc8SJan Kara int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
1563*ff116fc8SJan Kara 	kernel_lb_addr eloc, uint32_t elen, int inc)
15641da177e4SLinus Torvalds {
15651da177e4SLinus Torvalds 	int adsize;
15661da177e4SLinus Torvalds 	short_ad *sad = NULL;
15671da177e4SLinus Torvalds 	long_ad *lad = NULL;
15681da177e4SLinus Torvalds 	struct allocExtDesc *aed;
15691da177e4SLinus Torvalds 	int8_t etype;
15701da177e4SLinus Torvalds 	uint8_t *ptr;
15711da177e4SLinus Torvalds 
1572*ff116fc8SJan Kara 	if (!epos->bh)
1573*ff116fc8SJan Kara 		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
15741da177e4SLinus Torvalds 	else
1575*ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
15781da177e4SLinus Torvalds 		adsize = sizeof(short_ad);
15791da177e4SLinus Torvalds 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
15801da177e4SLinus Torvalds 		adsize = sizeof(long_ad);
15811da177e4SLinus Torvalds 	else
15821da177e4SLinus Torvalds 		return -1;
15831da177e4SLinus Torvalds 
1584*ff116fc8SJan Kara 	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize)
15851da177e4SLinus Torvalds 	{
15861da177e4SLinus Torvalds 		char *sptr, *dptr;
15871da177e4SLinus Torvalds 		struct buffer_head *nbh;
15881da177e4SLinus Torvalds 		int err, loffset;
1589*ff116fc8SJan Kara 		kernel_lb_addr obloc = epos->block;
15901da177e4SLinus Torvalds 
1591*ff116fc8SJan Kara 		if (!(epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
15921da177e4SLinus Torvalds 			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
15931da177e4SLinus Torvalds 		{
15941da177e4SLinus Torvalds 			return -1;
15951da177e4SLinus Torvalds 		}
15961da177e4SLinus Torvalds 		if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
1597*ff116fc8SJan Kara 			epos->block, 0))))
15981da177e4SLinus Torvalds 		{
15991da177e4SLinus Torvalds 			return -1;
16001da177e4SLinus Torvalds 		}
16011da177e4SLinus Torvalds 		lock_buffer(nbh);
16021da177e4SLinus Torvalds 		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
16031da177e4SLinus Torvalds 		set_buffer_uptodate(nbh);
16041da177e4SLinus Torvalds 		unlock_buffer(nbh);
16051da177e4SLinus Torvalds 		mark_buffer_dirty_inode(nbh, inode);
16061da177e4SLinus Torvalds 
16071da177e4SLinus Torvalds 		aed = (struct allocExtDesc *)(nbh->b_data);
16081da177e4SLinus Torvalds 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
16091da177e4SLinus Torvalds 			aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
1610*ff116fc8SJan Kara 		if (epos->offset + adsize > inode->i_sb->s_blocksize)
16111da177e4SLinus Torvalds 		{
1612*ff116fc8SJan Kara 			loffset = epos->offset;
16131da177e4SLinus Torvalds 			aed->lengthAllocDescs = cpu_to_le32(adsize);
16141da177e4SLinus Torvalds 			sptr = ptr - adsize;
16151da177e4SLinus Torvalds 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
16161da177e4SLinus Torvalds 			memcpy(dptr, sptr, adsize);
1617*ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc) + adsize;
16181da177e4SLinus Torvalds 		}
16191da177e4SLinus Torvalds 		else
16201da177e4SLinus Torvalds 		{
1621*ff116fc8SJan Kara 			loffset = epos->offset + adsize;
16221da177e4SLinus Torvalds 			aed->lengthAllocDescs = cpu_to_le32(0);
16231da177e4SLinus Torvalds 			sptr = ptr;
1624*ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc);
16251da177e4SLinus Torvalds 
1626*ff116fc8SJan Kara 			if (epos->bh)
16271da177e4SLinus Torvalds 			{
1628*ff116fc8SJan Kara 				aed = (struct allocExtDesc *)epos->bh->b_data;
16291da177e4SLinus Torvalds 				aed->lengthAllocDescs =
16301da177e4SLinus Torvalds 					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
16311da177e4SLinus Torvalds 			}
16321da177e4SLinus Torvalds 			else
16331da177e4SLinus Torvalds 			{
16341da177e4SLinus Torvalds 				UDF_I_LENALLOC(inode) += adsize;
16351da177e4SLinus Torvalds 				mark_inode_dirty(inode);
16361da177e4SLinus Torvalds 			}
16371da177e4SLinus Torvalds 		}
16381da177e4SLinus Torvalds 		if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
16391da177e4SLinus Torvalds 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
1640*ff116fc8SJan Kara 				epos->block.logicalBlockNum, sizeof(tag));
16411da177e4SLinus Torvalds 		else
16421da177e4SLinus Torvalds 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
1643*ff116fc8SJan Kara 				epos->block.logicalBlockNum, sizeof(tag));
16441da177e4SLinus Torvalds 		switch (UDF_I_ALLOCTYPE(inode))
16451da177e4SLinus Torvalds 		{
16461da177e4SLinus Torvalds 			case ICBTAG_FLAG_AD_SHORT:
16471da177e4SLinus Torvalds 			{
16481da177e4SLinus Torvalds 				sad = (short_ad *)sptr;
16491da177e4SLinus Torvalds 				sad->extLength = cpu_to_le32(
16501da177e4SLinus Torvalds 					EXT_NEXT_EXTENT_ALLOCDECS |
16511da177e4SLinus Torvalds 					inode->i_sb->s_blocksize);
1652*ff116fc8SJan Kara 				sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum);
16531da177e4SLinus Torvalds 				break;
16541da177e4SLinus Torvalds 			}
16551da177e4SLinus Torvalds 			case ICBTAG_FLAG_AD_LONG:
16561da177e4SLinus Torvalds 			{
16571da177e4SLinus Torvalds 				lad = (long_ad *)sptr;
16581da177e4SLinus Torvalds 				lad->extLength = cpu_to_le32(
16591da177e4SLinus Torvalds 					EXT_NEXT_EXTENT_ALLOCDECS |
16601da177e4SLinus Torvalds 					inode->i_sb->s_blocksize);
1661*ff116fc8SJan Kara 				lad->extLocation = cpu_to_lelb(epos->block);
16621da177e4SLinus Torvalds 				memset(lad->impUse, 0x00, sizeof(lad->impUse));
16631da177e4SLinus Torvalds 				break;
16641da177e4SLinus Torvalds 			}
16651da177e4SLinus Torvalds 		}
1666*ff116fc8SJan Kara 		if (epos->bh)
16671da177e4SLinus Torvalds 		{
16681da177e4SLinus Torvalds 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1669*ff116fc8SJan Kara 				udf_update_tag(epos->bh->b_data, loffset);
16701da177e4SLinus Torvalds 			else
1671*ff116fc8SJan Kara 				udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
1672*ff116fc8SJan Kara 			mark_buffer_dirty_inode(epos->bh, inode);
1673*ff116fc8SJan Kara 			udf_release_data(epos->bh);
16741da177e4SLinus Torvalds 		}
16751da177e4SLinus Torvalds 		else
16761da177e4SLinus Torvalds 			mark_inode_dirty(inode);
1677*ff116fc8SJan Kara 		epos->bh = nbh;
16781da177e4SLinus Torvalds 	}
16791da177e4SLinus Torvalds 
1680*ff116fc8SJan Kara 	etype = udf_write_aext(inode, epos, eloc, elen, inc);
16811da177e4SLinus Torvalds 
1682*ff116fc8SJan Kara 	if (!epos->bh)
16831da177e4SLinus Torvalds 	{
16841da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) += adsize;
16851da177e4SLinus Torvalds 		mark_inode_dirty(inode);
16861da177e4SLinus Torvalds 	}
16871da177e4SLinus Torvalds 	else
16881da177e4SLinus Torvalds 	{
1689*ff116fc8SJan Kara 		aed = (struct allocExtDesc *)epos->bh->b_data;
16901da177e4SLinus Torvalds 		aed->lengthAllocDescs =
16911da177e4SLinus Torvalds 			cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
16921da177e4SLinus Torvalds 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1693*ff116fc8SJan Kara 			udf_update_tag(epos->bh->b_data, epos->offset + (inc ? 0 : adsize));
16941da177e4SLinus Torvalds 		else
1695*ff116fc8SJan Kara 			udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
1696*ff116fc8SJan Kara 		mark_buffer_dirty_inode(epos->bh, inode);
16971da177e4SLinus Torvalds 	}
16981da177e4SLinus Torvalds 
16991da177e4SLinus Torvalds 	return etype;
17001da177e4SLinus Torvalds }
17011da177e4SLinus Torvalds 
1702*ff116fc8SJan Kara int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
1703*ff116fc8SJan Kara     kernel_lb_addr eloc, uint32_t elen, int inc)
17041da177e4SLinus Torvalds {
17051da177e4SLinus Torvalds 	int adsize;
17061da177e4SLinus Torvalds 	uint8_t *ptr;
17071da177e4SLinus Torvalds 
1708*ff116fc8SJan Kara 	if (!epos->bh)
1709*ff116fc8SJan Kara 		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
17101da177e4SLinus Torvalds 	else
1711*ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds 	switch (UDF_I_ALLOCTYPE(inode))
17141da177e4SLinus Torvalds 	{
17151da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_SHORT:
17161da177e4SLinus Torvalds 		{
17171da177e4SLinus Torvalds 			short_ad *sad = (short_ad *)ptr;
17181da177e4SLinus Torvalds 			sad->extLength = cpu_to_le32(elen);
17191da177e4SLinus Torvalds 			sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
17201da177e4SLinus Torvalds 			adsize = sizeof(short_ad);
17211da177e4SLinus Torvalds 			break;
17221da177e4SLinus Torvalds 		}
17231da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_LONG:
17241da177e4SLinus Torvalds 		{
17251da177e4SLinus Torvalds 			long_ad *lad = (long_ad *)ptr;
17261da177e4SLinus Torvalds 			lad->extLength = cpu_to_le32(elen);
17271da177e4SLinus Torvalds 			lad->extLocation = cpu_to_lelb(eloc);
17281da177e4SLinus Torvalds 			memset(lad->impUse, 0x00, sizeof(lad->impUse));
17291da177e4SLinus Torvalds 			adsize = sizeof(long_ad);
17301da177e4SLinus Torvalds 			break;
17311da177e4SLinus Torvalds 		}
17321da177e4SLinus Torvalds 		default:
17331da177e4SLinus Torvalds 			return -1;
17341da177e4SLinus Torvalds 	}
17351da177e4SLinus Torvalds 
1736*ff116fc8SJan Kara 	if (epos->bh)
17371da177e4SLinus Torvalds 	{
17381da177e4SLinus Torvalds 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
17391da177e4SLinus Torvalds 		{
1740*ff116fc8SJan Kara 			struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data;
1741*ff116fc8SJan Kara 			udf_update_tag(epos->bh->b_data,
17421da177e4SLinus Torvalds 				le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
17431da177e4SLinus Torvalds 		}
1744*ff116fc8SJan Kara 		mark_buffer_dirty_inode(epos->bh, inode);
17451da177e4SLinus Torvalds 	}
17461da177e4SLinus Torvalds 	else
17471da177e4SLinus Torvalds 		mark_inode_dirty(inode);
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 	if (inc)
1750*ff116fc8SJan Kara 		epos->offset += adsize;
17511da177e4SLinus Torvalds 	return (elen >> 30);
17521da177e4SLinus Torvalds }
17531da177e4SLinus Torvalds 
1754*ff116fc8SJan Kara int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
1755*ff116fc8SJan Kara 	kernel_lb_addr *eloc, uint32_t *elen, int inc)
17561da177e4SLinus Torvalds {
17571da177e4SLinus Torvalds 	int8_t etype;
17581da177e4SLinus Torvalds 
1759*ff116fc8SJan Kara 	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
17601da177e4SLinus Torvalds 		(EXT_NEXT_EXTENT_ALLOCDECS >> 30))
17611da177e4SLinus Torvalds 	{
1762*ff116fc8SJan Kara 		epos->block = *eloc;
1763*ff116fc8SJan Kara 		epos->offset = sizeof(struct allocExtDesc);
1764*ff116fc8SJan Kara 		udf_release_data(epos->bh);
1765*ff116fc8SJan Kara 		if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0))))
17661da177e4SLinus Torvalds 		{
17671da177e4SLinus Torvalds 			udf_debug("reading block %d failed!\n",
1768*ff116fc8SJan Kara 				udf_get_lb_pblock(inode->i_sb, epos->block, 0));
17691da177e4SLinus Torvalds 			return -1;
17701da177e4SLinus Torvalds 		}
17711da177e4SLinus Torvalds 	}
17721da177e4SLinus Torvalds 
17731da177e4SLinus Torvalds 	return etype;
17741da177e4SLinus Torvalds }
17751da177e4SLinus Torvalds 
1776*ff116fc8SJan Kara int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
1777*ff116fc8SJan Kara 	kernel_lb_addr *eloc, uint32_t *elen, int inc)
17781da177e4SLinus Torvalds {
17791da177e4SLinus Torvalds 	int alen;
17801da177e4SLinus Torvalds 	int8_t etype;
17811da177e4SLinus Torvalds 	uint8_t *ptr;
17821da177e4SLinus Torvalds 
1783*ff116fc8SJan Kara 	if (!epos->bh)
17841da177e4SLinus Torvalds 	{
1785*ff116fc8SJan Kara 		if (!epos->offset)
1786*ff116fc8SJan Kara 			epos->offset = udf_file_entry_alloc_offset(inode);
1787*ff116fc8SJan Kara 		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
17881da177e4SLinus Torvalds 		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
17891da177e4SLinus Torvalds 	}
17901da177e4SLinus Torvalds 	else
17911da177e4SLinus Torvalds 	{
1792*ff116fc8SJan Kara 		if (!epos->offset)
1793*ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc);
1794*ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
1795*ff116fc8SJan Kara 		alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs);
17961da177e4SLinus Torvalds 	}
17971da177e4SLinus Torvalds 
17981da177e4SLinus Torvalds 	switch (UDF_I_ALLOCTYPE(inode))
17991da177e4SLinus Torvalds 	{
18001da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_SHORT:
18011da177e4SLinus Torvalds 		{
18021da177e4SLinus Torvalds 			short_ad *sad;
18031da177e4SLinus Torvalds 
1804*ff116fc8SJan Kara 			if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc)))
18051da177e4SLinus Torvalds 				return -1;
18061da177e4SLinus Torvalds 
18071da177e4SLinus Torvalds 			etype = le32_to_cpu(sad->extLength) >> 30;
18081da177e4SLinus Torvalds 			eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
18091da177e4SLinus Torvalds 			eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
18101da177e4SLinus Torvalds 			*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
18111da177e4SLinus Torvalds 			break;
18121da177e4SLinus Torvalds 		}
18131da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_LONG:
18141da177e4SLinus Torvalds 		{
18151da177e4SLinus Torvalds 			long_ad *lad;
18161da177e4SLinus Torvalds 
1817*ff116fc8SJan Kara 			if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc)))
18181da177e4SLinus Torvalds 				return -1;
18191da177e4SLinus Torvalds 
18201da177e4SLinus Torvalds 			etype = le32_to_cpu(lad->extLength) >> 30;
18211da177e4SLinus Torvalds 			*eloc = lelb_to_cpu(lad->extLocation);
18221da177e4SLinus Torvalds 			*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
18231da177e4SLinus Torvalds 			break;
18241da177e4SLinus Torvalds 		}
18251da177e4SLinus Torvalds 		default:
18261da177e4SLinus Torvalds 		{
18271da177e4SLinus Torvalds 			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
18281da177e4SLinus Torvalds 			return -1;
18291da177e4SLinus Torvalds 		}
18301da177e4SLinus Torvalds 	}
18311da177e4SLinus Torvalds 
18321da177e4SLinus Torvalds 	return etype;
18331da177e4SLinus Torvalds }
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds static int8_t
1836*ff116fc8SJan Kara udf_insert_aext(struct inode *inode, struct extent_position epos,
1837*ff116fc8SJan Kara 		kernel_lb_addr neloc, uint32_t nelen)
18381da177e4SLinus Torvalds {
18391da177e4SLinus Torvalds 	kernel_lb_addr oeloc;
18401da177e4SLinus Torvalds 	uint32_t oelen;
18411da177e4SLinus Torvalds 	int8_t etype;
18421da177e4SLinus Torvalds 
1843*ff116fc8SJan Kara 	if (epos.bh)
1844*ff116fc8SJan Kara 		atomic_inc(&epos.bh->b_count);
18451da177e4SLinus Torvalds 
1846*ff116fc8SJan Kara 	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1)
18471da177e4SLinus Torvalds 	{
1848*ff116fc8SJan Kara 		udf_write_aext(inode, &epos, neloc, nelen, 1);
18491da177e4SLinus Torvalds 
18501da177e4SLinus Torvalds 		neloc = oeloc;
18511da177e4SLinus Torvalds 		nelen = (etype << 30) | oelen;
18521da177e4SLinus Torvalds 	}
1853*ff116fc8SJan Kara 	udf_add_aext(inode, &epos, neloc, nelen, 1);
1854*ff116fc8SJan Kara 	udf_release_data(epos.bh);
18551da177e4SLinus Torvalds 	return (nelen >> 30);
18561da177e4SLinus Torvalds }
18571da177e4SLinus Torvalds 
1858*ff116fc8SJan Kara int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
1859*ff116fc8SJan Kara 	kernel_lb_addr eloc, uint32_t elen)
18601da177e4SLinus Torvalds {
1861*ff116fc8SJan Kara 	struct extent_position oepos;
1862*ff116fc8SJan Kara 	int adsize;
18631da177e4SLinus Torvalds 	int8_t etype;
18641da177e4SLinus Torvalds 	struct allocExtDesc *aed;
18651da177e4SLinus Torvalds 
1866*ff116fc8SJan Kara 	if (epos.bh)
18671da177e4SLinus Torvalds 	{
1868*ff116fc8SJan Kara 		atomic_inc(&epos.bh->b_count);
1869*ff116fc8SJan Kara 		atomic_inc(&epos.bh->b_count);
18701da177e4SLinus Torvalds 	}
18711da177e4SLinus Torvalds 
18721da177e4SLinus Torvalds 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
18731da177e4SLinus Torvalds 		adsize = sizeof(short_ad);
18741da177e4SLinus Torvalds 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
18751da177e4SLinus Torvalds 		adsize = sizeof(long_ad);
18761da177e4SLinus Torvalds 	else
18771da177e4SLinus Torvalds 		adsize = 0;
18781da177e4SLinus Torvalds 
1879*ff116fc8SJan Kara 	oepos = epos;
1880*ff116fc8SJan Kara 	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
18811da177e4SLinus Torvalds 		return -1;
18821da177e4SLinus Torvalds 
1883*ff116fc8SJan Kara 	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
18841da177e4SLinus Torvalds 	{
1885*ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);
1886*ff116fc8SJan Kara 		if (oepos.bh != epos.bh)
18871da177e4SLinus Torvalds 		{
1888*ff116fc8SJan Kara 			oepos.block = epos.block;
1889*ff116fc8SJan Kara 			udf_release_data(oepos.bh);
1890*ff116fc8SJan Kara 			atomic_inc(&epos.bh->b_count);
1891*ff116fc8SJan Kara 			oepos.bh = epos.bh;
1892*ff116fc8SJan Kara 			oepos.offset = epos.offset - adsize;
18931da177e4SLinus Torvalds 		}
18941da177e4SLinus Torvalds 	}
18951da177e4SLinus Torvalds 	memset(&eloc, 0x00, sizeof(kernel_lb_addr));
18961da177e4SLinus Torvalds 	elen = 0;
18971da177e4SLinus Torvalds 
1898*ff116fc8SJan Kara 	if (epos.bh != oepos.bh)
18991da177e4SLinus Torvalds 	{
1900*ff116fc8SJan Kara 		udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);
1901*ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
1902*ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
1903*ff116fc8SJan Kara 		if (!oepos.bh)
19041da177e4SLinus Torvalds 		{
19051da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) -= (adsize * 2);
19061da177e4SLinus Torvalds 			mark_inode_dirty(inode);
19071da177e4SLinus Torvalds 		}
19081da177e4SLinus Torvalds 		else
19091da177e4SLinus Torvalds 		{
1910*ff116fc8SJan Kara 			aed = (struct allocExtDesc *)oepos.bh->b_data;
19111da177e4SLinus Torvalds 			aed->lengthAllocDescs =
19121da177e4SLinus Torvalds 				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
19131da177e4SLinus Torvalds 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1914*ff116fc8SJan Kara 				udf_update_tag(oepos.bh->b_data, oepos.offset - (2*adsize));
19151da177e4SLinus Torvalds 			else
1916*ff116fc8SJan Kara 				udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
1917*ff116fc8SJan Kara 			mark_buffer_dirty_inode(oepos.bh, inode);
19181da177e4SLinus Torvalds 		}
19191da177e4SLinus Torvalds 	}
19201da177e4SLinus Torvalds 	else
19211da177e4SLinus Torvalds 	{
1922*ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
1923*ff116fc8SJan Kara 		if (!oepos.bh)
19241da177e4SLinus Torvalds 		{
19251da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) -= adsize;
19261da177e4SLinus Torvalds 			mark_inode_dirty(inode);
19271da177e4SLinus Torvalds 		}
19281da177e4SLinus Torvalds 		else
19291da177e4SLinus Torvalds 		{
1930*ff116fc8SJan Kara 			aed = (struct allocExtDesc *)oepos.bh->b_data;
19311da177e4SLinus Torvalds 			aed->lengthAllocDescs =
19321da177e4SLinus Torvalds 				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
19331da177e4SLinus Torvalds 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1934*ff116fc8SJan Kara 				udf_update_tag(oepos.bh->b_data, epos.offset - adsize);
19351da177e4SLinus Torvalds 			else
1936*ff116fc8SJan Kara 				udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
1937*ff116fc8SJan Kara 			mark_buffer_dirty_inode(oepos.bh, inode);
19381da177e4SLinus Torvalds 		}
19391da177e4SLinus Torvalds 	}
19401da177e4SLinus Torvalds 
1941*ff116fc8SJan Kara 	udf_release_data(epos.bh);
1942*ff116fc8SJan Kara 	udf_release_data(oepos.bh);
19431da177e4SLinus Torvalds 	return (elen >> 30);
19441da177e4SLinus Torvalds }
19451da177e4SLinus Torvalds 
1946*ff116fc8SJan Kara int8_t inode_bmap(struct inode *inode, sector_t block, struct extent_position *pos,
1947*ff116fc8SJan Kara 	kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset)
19481da177e4SLinus Torvalds {
194960448b1dSJan Kara 	loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
19501da177e4SLinus Torvalds 	int8_t etype;
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds 	if (block < 0)
19531da177e4SLinus Torvalds 	{
19541da177e4SLinus Torvalds 		printk(KERN_ERR "udf: inode_bmap: block < 0\n");
19551da177e4SLinus Torvalds 		return -1;
19561da177e4SLinus Torvalds 	}
19571da177e4SLinus Torvalds 
1958*ff116fc8SJan Kara 	pos->offset = 0;
1959*ff116fc8SJan Kara 	pos->block = UDF_I_LOCATION(inode);
1960*ff116fc8SJan Kara 	pos->bh = NULL;
19611da177e4SLinus Torvalds 	*elen = 0;
19621da177e4SLinus Torvalds 
19631da177e4SLinus Torvalds 	do
19641da177e4SLinus Torvalds 	{
1965*ff116fc8SJan Kara 		if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1)
19661da177e4SLinus Torvalds 		{
196760448b1dSJan Kara 			*offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
19681da177e4SLinus Torvalds 			UDF_I_LENEXTENTS(inode) = lbcount;
19691da177e4SLinus Torvalds 			return -1;
19701da177e4SLinus Torvalds 		}
19711da177e4SLinus Torvalds 		lbcount += *elen;
19721da177e4SLinus Torvalds 	} while (lbcount <= bcount);
19731da177e4SLinus Torvalds 
197460448b1dSJan Kara 	*offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits;
19751da177e4SLinus Torvalds 
19761da177e4SLinus Torvalds 	return etype;
19771da177e4SLinus Torvalds }
19781da177e4SLinus Torvalds 
197960448b1dSJan Kara long udf_block_map(struct inode *inode, sector_t block)
19801da177e4SLinus Torvalds {
1981*ff116fc8SJan Kara 	kernel_lb_addr eloc;
1982*ff116fc8SJan Kara 	uint32_t elen;
198360448b1dSJan Kara 	sector_t offset;
1984*ff116fc8SJan Kara 	struct extent_position epos = { NULL, 0, { 0, 0}};
19851da177e4SLinus Torvalds 	int ret;
19861da177e4SLinus Torvalds 
19871da177e4SLinus Torvalds 	lock_kernel();
19881da177e4SLinus Torvalds 
1989*ff116fc8SJan Kara 	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
199060448b1dSJan Kara 		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
19911da177e4SLinus Torvalds 	else
19921da177e4SLinus Torvalds 		ret = 0;
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	unlock_kernel();
1995*ff116fc8SJan Kara 	udf_release_data(epos.bh);
19961da177e4SLinus Torvalds 
19971da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
19981da177e4SLinus Torvalds 		return udf_fixed_to_variable(ret);
19991da177e4SLinus Torvalds 	else
20001da177e4SLinus Torvalds 		return ret;
20011da177e4SLinus Torvalds }
2002