xref: /openbmc/linux/fs/udf/inode.c (revision cb00ea3528eb3c09eae9871d6e7d038776e952e2)
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 *);
52647bd61aSCyrill Gorcunov static int udf_alloc_i_data(struct inode *inode, size_t size);
5360448b1dSJan Kara static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
541da177e4SLinus Torvalds 					long *, int *);
55ff116fc8SJan Kara static int8_t udf_insert_aext(struct inode *, struct extent_position,
56ff116fc8SJan Kara 			      kernel_lb_addr, uint32_t);
571da177e4SLinus Torvalds static void udf_split_extents(struct inode *, int *, int, int,
581da177e4SLinus Torvalds 			      kernel_long_ad[EXTENT_MERGE_SIZE], int *);
591da177e4SLinus Torvalds static void udf_prealloc_extents(struct inode *, int, int,
601da177e4SLinus Torvalds 				 kernel_long_ad[EXTENT_MERGE_SIZE], int *);
611da177e4SLinus Torvalds static void udf_merge_extents(struct inode *,
621da177e4SLinus Torvalds 			      kernel_long_ad[EXTENT_MERGE_SIZE], int *);
631da177e4SLinus Torvalds static void udf_update_extents(struct inode *,
641da177e4SLinus Torvalds 			       kernel_long_ad[EXTENT_MERGE_SIZE], int, int,
65ff116fc8SJan Kara 			       struct extent_position *);
661da177e4SLinus Torvalds static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds /*
691da177e4SLinus Torvalds  * udf_delete_inode
701da177e4SLinus Torvalds  *
711da177e4SLinus Torvalds  * PURPOSE
721da177e4SLinus Torvalds  *	Clean-up before the specified inode is destroyed.
731da177e4SLinus Torvalds  *
741da177e4SLinus Torvalds  * DESCRIPTION
751da177e4SLinus Torvalds  *	This routine is called when the kernel destroys an inode structure
761da177e4SLinus Torvalds  *	ie. when iput() finds i_count == 0.
771da177e4SLinus Torvalds  *
781da177e4SLinus Torvalds  * HISTORY
791da177e4SLinus Torvalds  *	July 1, 1997 - Andrew E. Mileski
801da177e4SLinus Torvalds  *	Written, tested, and released.
811da177e4SLinus Torvalds  *
821da177e4SLinus Torvalds  *  Called at the last iput() if i_nlink is zero.
831da177e4SLinus Torvalds  */
841da177e4SLinus Torvalds void udf_delete_inode(struct inode *inode)
851da177e4SLinus Torvalds {
86fef26658SMark Fasheh 	truncate_inode_pages(&inode->i_data, 0);
87fef26658SMark Fasheh 
881da177e4SLinus Torvalds 	if (is_bad_inode(inode))
891da177e4SLinus Torvalds 		goto no_delete;
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds 	inode->i_size = 0;
921da177e4SLinus Torvalds 	udf_truncate(inode);
931da177e4SLinus Torvalds 	lock_kernel();
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	udf_update_inode(inode, IS_SYNC(inode));
961da177e4SLinus Torvalds 	udf_free_inode(inode);
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	unlock_kernel();
991da177e4SLinus Torvalds 	return;
1001da177e4SLinus Torvalds       no_delete:
1011da177e4SLinus Torvalds 	clear_inode(inode);
1021da177e4SLinus Torvalds }
1031da177e4SLinus Torvalds 
10474584ae5SJan Kara /*
10574584ae5SJan Kara  * If we are going to release inode from memory, we discard preallocation and
10674584ae5SJan Kara  * truncate last inode extent to proper length. We could use drop_inode() but
10774584ae5SJan Kara  * it's called under inode_lock and thus we cannot mark inode dirty there.  We
10874584ae5SJan Kara  * use clear_inode() but we have to make sure to write inode as it's not written
10974584ae5SJan Kara  * automatically.
11074584ae5SJan Kara  */
1111da177e4SLinus Torvalds void udf_clear_inode(struct inode *inode)
1121da177e4SLinus Torvalds {
1131da177e4SLinus Torvalds 	if (!(inode->i_sb->s_flags & MS_RDONLY)) {
1141da177e4SLinus Torvalds 		lock_kernel();
11574584ae5SJan Kara 		/* Discard preallocation for directories, symlinks, etc. */
1161da177e4SLinus Torvalds 		udf_discard_prealloc(inode);
11774584ae5SJan Kara 		udf_truncate_tail_extent(inode);
1181da177e4SLinus Torvalds 		unlock_kernel();
11974584ae5SJan Kara 		write_inode_now(inode, 1);
1201da177e4SLinus Torvalds 	}
1211da177e4SLinus Torvalds 	kfree(UDF_I_DATA(inode));
1221da177e4SLinus Torvalds 	UDF_I_DATA(inode) = NULL;
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds static int udf_writepage(struct page *page, struct writeback_control *wbc)
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds 	return block_write_full_page(page, udf_get_block, wbc);
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds static int udf_readpage(struct file *file, struct page *page)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds 	return block_read_full_page(page, udf_get_block);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
135*cb00ea35SCyrill Gorcunov static int udf_prepare_write(struct file *file, struct page *page,
136*cb00ea35SCyrill Gorcunov 			     unsigned from, unsigned to)
1371da177e4SLinus Torvalds {
1381da177e4SLinus Torvalds 	return block_prepare_write(page, from, to, udf_get_block);
1391da177e4SLinus Torvalds }
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds static sector_t udf_bmap(struct address_space *mapping, sector_t block)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds 	return generic_block_bmap(mapping, block, udf_get_block);
1441da177e4SLinus Torvalds }
1451da177e4SLinus Torvalds 
146f5e54d6eSChristoph Hellwig const struct address_space_operations udf_aops = {
1471da177e4SLinus Torvalds 	.readpage = udf_readpage,
1481da177e4SLinus Torvalds 	.writepage = udf_writepage,
1491da177e4SLinus Torvalds 	.sync_page = block_sync_page,
1501da177e4SLinus Torvalds 	.prepare_write = udf_prepare_write,
1511da177e4SLinus Torvalds 	.commit_write = generic_commit_write,
1521da177e4SLinus Torvalds 	.bmap = udf_bmap,
1531da177e4SLinus Torvalds };
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
1561da177e4SLinus Torvalds {
1571da177e4SLinus Torvalds 	struct page *page;
1581da177e4SLinus Torvalds 	char *kaddr;
1591da177e4SLinus Torvalds 	struct writeback_control udf_wbc = {
1601da177e4SLinus Torvalds 		.sync_mode = WB_SYNC_NONE,
1611da177e4SLinus Torvalds 		.nr_to_write = 1,
1621da177e4SLinus Torvalds 	};
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds 	/* from now on we have normal address_space methods */
1651da177e4SLinus Torvalds 	inode->i_data.a_ops = &udf_aops;
1661da177e4SLinus Torvalds 
167*cb00ea35SCyrill Gorcunov 	if (!UDF_I_LENALLOC(inode)) {
1681da177e4SLinus Torvalds 		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
1691da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
1701da177e4SLinus Torvalds 		else
1711da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
1721da177e4SLinus Torvalds 		mark_inode_dirty(inode);
1731da177e4SLinus Torvalds 		return;
1741da177e4SLinus Torvalds 	}
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	page = grab_cache_page(inode->i_mapping, 0);
177cd7619d6SMatt Mackall 	BUG_ON(!PageLocked(page));
178cd7619d6SMatt Mackall 
179*cb00ea35SCyrill Gorcunov 	if (!PageUptodate(page)) {
1801da177e4SLinus Torvalds 		kaddr = kmap(page);
1811da177e4SLinus Torvalds 		memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
1821da177e4SLinus Torvalds 		       PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
1831da177e4SLinus Torvalds 		memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
1841da177e4SLinus Torvalds 		       UDF_I_LENALLOC(inode));
1851da177e4SLinus Torvalds 		flush_dcache_page(page);
1861da177e4SLinus Torvalds 		SetPageUptodate(page);
1871da177e4SLinus Torvalds 		kunmap(page);
1881da177e4SLinus Torvalds 	}
1891da177e4SLinus Torvalds 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
1901da177e4SLinus Torvalds 	       UDF_I_LENALLOC(inode));
1911da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
1921da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
1931da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
1941da177e4SLinus Torvalds 	else
1951da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds 	inode->i_data.a_ops->writepage(page, &udf_wbc);
1981da177e4SLinus Torvalds 	page_cache_release(page);
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	mark_inode_dirty(inode);
2011da177e4SLinus Torvalds }
2021da177e4SLinus Torvalds 
203*cb00ea35SCyrill Gorcunov struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
204*cb00ea35SCyrill Gorcunov 					   int *err)
2051da177e4SLinus Torvalds {
2061da177e4SLinus Torvalds 	int newblock;
207ff116fc8SJan Kara 	struct buffer_head *dbh = NULL;
208ff116fc8SJan Kara 	kernel_lb_addr eloc;
209ff116fc8SJan Kara 	uint32_t elen;
2101da177e4SLinus Torvalds 	uint8_t alloctype;
211ff116fc8SJan Kara 	struct extent_position epos;
2121da177e4SLinus Torvalds 
2131da177e4SLinus Torvalds 	struct udf_fileident_bh sfibh, dfibh;
2141da177e4SLinus Torvalds 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
2151da177e4SLinus Torvalds 	int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
2161da177e4SLinus Torvalds 	struct fileIdentDesc cfi, *sfi, *dfi;
2171da177e4SLinus Torvalds 
2181da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
2191da177e4SLinus Torvalds 		alloctype = ICBTAG_FLAG_AD_SHORT;
2201da177e4SLinus Torvalds 	else
2211da177e4SLinus Torvalds 		alloctype = ICBTAG_FLAG_AD_LONG;
2221da177e4SLinus Torvalds 
223*cb00ea35SCyrill Gorcunov 	if (!inode->i_size) {
2241da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = alloctype;
2251da177e4SLinus Torvalds 		mark_inode_dirty(inode);
2261da177e4SLinus Torvalds 		return NULL;
2271da177e4SLinus Torvalds 	}
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 	/* alloc block, and copy data to it */
2301da177e4SLinus Torvalds 	*block = udf_new_block(inode->i_sb, inode,
2311da177e4SLinus Torvalds 			       UDF_I_LOCATION(inode).partitionReferenceNum,
2321da177e4SLinus Torvalds 			       UDF_I_LOCATION(inode).logicalBlockNum, err);
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	if (!(*block))
2351da177e4SLinus Torvalds 		return NULL;
2361da177e4SLinus Torvalds 	newblock = udf_get_pblock(inode->i_sb, *block,
237*cb00ea35SCyrill Gorcunov 				  UDF_I_LOCATION(inode).partitionReferenceNum,
238*cb00ea35SCyrill Gorcunov 				  0);
2391da177e4SLinus Torvalds 	if (!newblock)
2401da177e4SLinus Torvalds 		return NULL;
2411da177e4SLinus Torvalds 	dbh = udf_tgetblk(inode->i_sb, newblock);
2421da177e4SLinus Torvalds 	if (!dbh)
2431da177e4SLinus Torvalds 		return NULL;
2441da177e4SLinus Torvalds 	lock_buffer(dbh);
2451da177e4SLinus Torvalds 	memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize);
2461da177e4SLinus Torvalds 	set_buffer_uptodate(dbh);
2471da177e4SLinus Torvalds 	unlock_buffer(dbh);
2481da177e4SLinus Torvalds 	mark_buffer_dirty_inode(dbh, inode);
2491da177e4SLinus Torvalds 
250*cb00ea35SCyrill Gorcunov 	sfibh.soffset = sfibh.eoffset =
251*cb00ea35SCyrill Gorcunov 	    (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
252ff116fc8SJan Kara 	sfibh.sbh = sfibh.ebh = NULL;
2531da177e4SLinus Torvalds 	dfibh.soffset = dfibh.eoffset = 0;
2541da177e4SLinus Torvalds 	dfibh.sbh = dfibh.ebh = dbh;
255*cb00ea35SCyrill Gorcunov 	while ((f_pos < size)) {
2561da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
257*cb00ea35SCyrill Gorcunov 		sfi =
258*cb00ea35SCyrill Gorcunov 		    udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL,
259*cb00ea35SCyrill Gorcunov 				       NULL, NULL);
260*cb00ea35SCyrill Gorcunov 		if (!sfi) {
2613bf25cb4SJan Kara 			brelse(dbh);
2621da177e4SLinus Torvalds 			return NULL;
2631da177e4SLinus Torvalds 		}
2641da177e4SLinus Torvalds 		UDF_I_ALLOCTYPE(inode) = alloctype;
2651da177e4SLinus Torvalds 		sfi->descTag.tagLocation = cpu_to_le32(*block);
2661da177e4SLinus Torvalds 		dfibh.soffset = dfibh.eoffset;
2671da177e4SLinus Torvalds 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
2681da177e4SLinus Torvalds 		dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
2691da177e4SLinus Torvalds 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
270*cb00ea35SCyrill Gorcunov 				 sfi->fileIdent +
271*cb00ea35SCyrill Gorcunov 				 le16_to_cpu(sfi->lengthOfImpUse))) {
2721da177e4SLinus Torvalds 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
2733bf25cb4SJan Kara 			brelse(dbh);
2741da177e4SLinus Torvalds 			return NULL;
2751da177e4SLinus Torvalds 		}
2761da177e4SLinus Torvalds 	}
2771da177e4SLinus Torvalds 	mark_buffer_dirty_inode(dbh, inode);
2781da177e4SLinus Torvalds 
279*cb00ea35SCyrill Gorcunov 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0,
280*cb00ea35SCyrill Gorcunov 	       UDF_I_LENALLOC(inode));
2811da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
2821da177e4SLinus Torvalds 	eloc.logicalBlockNum = *block;
283*cb00ea35SCyrill Gorcunov 	eloc.partitionReferenceNum =
284*cb00ea35SCyrill Gorcunov 	    UDF_I_LOCATION(inode).partitionReferenceNum;
2851da177e4SLinus Torvalds 	elen = inode->i_size;
2861da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = elen;
287ff116fc8SJan Kara 	epos.bh = NULL;
288ff116fc8SJan Kara 	epos.block = UDF_I_LOCATION(inode);
289ff116fc8SJan Kara 	epos.offset = udf_file_entry_alloc_offset(inode);
290ff116fc8SJan Kara 	udf_add_aext(inode, &epos, eloc, elen, 0);
2911da177e4SLinus Torvalds 	/* UniqueID stuff */
2921da177e4SLinus Torvalds 
2933bf25cb4SJan Kara 	brelse(epos.bh);
2941da177e4SLinus Torvalds 	mark_inode_dirty(inode);
2951da177e4SLinus Torvalds 	return dbh;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298*cb00ea35SCyrill Gorcunov static int udf_get_block(struct inode *inode, sector_t block,
299*cb00ea35SCyrill Gorcunov 			 struct buffer_head *bh_result, int create)
3001da177e4SLinus Torvalds {
3011da177e4SLinus Torvalds 	int err, new;
3021da177e4SLinus Torvalds 	struct buffer_head *bh;
3031da177e4SLinus Torvalds 	unsigned long phys;
3041da177e4SLinus Torvalds 
305*cb00ea35SCyrill Gorcunov 	if (!create) {
3061da177e4SLinus Torvalds 		phys = udf_block_map(inode, block);
3071da177e4SLinus Torvalds 		if (phys)
3081da177e4SLinus Torvalds 			map_bh(bh_result, inode->i_sb, phys);
3091da177e4SLinus Torvalds 		return 0;
3101da177e4SLinus Torvalds 	}
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 	err = -EIO;
3131da177e4SLinus Torvalds 	new = 0;
3141da177e4SLinus Torvalds 	bh = NULL;
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds 	lock_kernel();
3171da177e4SLinus Torvalds 
3181da177e4SLinus Torvalds 	if (block < 0)
3191da177e4SLinus Torvalds 		goto abort_negative;
3201da177e4SLinus Torvalds 
321*cb00ea35SCyrill Gorcunov 	if (block == UDF_I_NEXT_ALLOC_BLOCK(inode) + 1) {
3221da177e4SLinus Torvalds 		UDF_I_NEXT_ALLOC_BLOCK(inode)++;
3231da177e4SLinus Torvalds 		UDF_I_NEXT_ALLOC_GOAL(inode)++;
3241da177e4SLinus Torvalds 	}
3251da177e4SLinus Torvalds 
3261da177e4SLinus Torvalds 	err = 0;
3271da177e4SLinus Torvalds 
3281da177e4SLinus Torvalds 	bh = inode_getblk(inode, block, &err, &phys, &new);
3292c2111c2SEric Sesterhenn 	BUG_ON(bh);
3301da177e4SLinus Torvalds 	if (err)
3311da177e4SLinus Torvalds 		goto abort;
3322c2111c2SEric Sesterhenn 	BUG_ON(!phys);
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds 	if (new)
3351da177e4SLinus Torvalds 		set_buffer_new(bh_result);
3361da177e4SLinus Torvalds 	map_bh(bh_result, inode->i_sb, phys);
3371da177e4SLinus Torvalds       abort:
3381da177e4SLinus Torvalds 	unlock_kernel();
3391da177e4SLinus Torvalds 	return err;
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds       abort_negative:
3421da177e4SLinus Torvalds 	udf_warning(inode->i_sb, "udf_get_block", "block < 0");
3431da177e4SLinus Torvalds 	goto abort;
3441da177e4SLinus Torvalds }
3451da177e4SLinus Torvalds 
346*cb00ea35SCyrill Gorcunov static struct buffer_head *udf_getblk(struct inode *inode, long block,
347*cb00ea35SCyrill Gorcunov 				      int create, int *err)
3481da177e4SLinus Torvalds {
3491da177e4SLinus Torvalds 	struct buffer_head dummy;
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 	dummy.b_state = 0;
3521da177e4SLinus Torvalds 	dummy.b_blocknr = -1000;
3531da177e4SLinus Torvalds 	*err = udf_get_block(inode, block, &dummy, create);
354*cb00ea35SCyrill Gorcunov 	if (!*err && buffer_mapped(&dummy)) {
3551da177e4SLinus Torvalds 		struct buffer_head *bh;
3561da177e4SLinus Torvalds 		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
357*cb00ea35SCyrill Gorcunov 		if (buffer_new(&dummy)) {
3581da177e4SLinus Torvalds 			lock_buffer(bh);
3591da177e4SLinus Torvalds 			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
3601da177e4SLinus Torvalds 			set_buffer_uptodate(bh);
3611da177e4SLinus Torvalds 			unlock_buffer(bh);
3621da177e4SLinus Torvalds 			mark_buffer_dirty_inode(bh, inode);
3631da177e4SLinus Torvalds 		}
3641da177e4SLinus Torvalds 		return bh;
3651da177e4SLinus Torvalds 	}
3661da177e4SLinus Torvalds 	return NULL;
3671da177e4SLinus Torvalds }
3681da177e4SLinus Torvalds 
36931170b6aSJan Kara /* Extend the file by 'blocks' blocks, return the number of extents added */
37031170b6aSJan Kara int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
37131170b6aSJan Kara 		    kernel_long_ad * last_ext, sector_t blocks)
37231170b6aSJan Kara {
37331170b6aSJan Kara 	sector_t add;
37431170b6aSJan Kara 	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
37531170b6aSJan Kara 	struct super_block *sb = inode->i_sb;
37631170b6aSJan Kara 	kernel_lb_addr prealloc_loc = { 0, 0 };
37731170b6aSJan Kara 	int prealloc_len = 0;
37831170b6aSJan Kara 
37931170b6aSJan Kara 	/* The previous extent is fake and we should not extend by anything
38031170b6aSJan Kara 	 * - there's nothing to do... */
38131170b6aSJan Kara 	if (!blocks && fake)
38231170b6aSJan Kara 		return 0;
38331170b6aSJan Kara 	/* Round the last extent up to a multiple of block size */
38431170b6aSJan Kara 	if (last_ext->extLength & (sb->s_blocksize - 1)) {
38531170b6aSJan Kara 		last_ext->extLength =
38631170b6aSJan Kara 		    (last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
38731170b6aSJan Kara 		    (((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
38831170b6aSJan Kara 		      sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
38931170b6aSJan Kara 		UDF_I_LENEXTENTS(inode) =
39031170b6aSJan Kara 		    (UDF_I_LENEXTENTS(inode) + sb->s_blocksize - 1) &
39131170b6aSJan Kara 		    ~(sb->s_blocksize - 1);
39231170b6aSJan Kara 	}
39331170b6aSJan Kara 	/* Last extent are just preallocated blocks? */
394*cb00ea35SCyrill Gorcunov 	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
395*cb00ea35SCyrill Gorcunov 	    EXT_NOT_RECORDED_ALLOCATED) {
39631170b6aSJan Kara 		/* Save the extent so that we can reattach it to the end */
39731170b6aSJan Kara 		prealloc_loc = last_ext->extLocation;
39831170b6aSJan Kara 		prealloc_len = last_ext->extLength;
39931170b6aSJan Kara 		/* Mark the extent as a hole */
40031170b6aSJan Kara 		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
40131170b6aSJan Kara 		    (last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
40231170b6aSJan Kara 		last_ext->extLocation.logicalBlockNum = 0;
40331170b6aSJan Kara 		last_ext->extLocation.partitionReferenceNum = 0;
40431170b6aSJan Kara 	}
40531170b6aSJan Kara 	/* Can we merge with the previous extent? */
406*cb00ea35SCyrill Gorcunov 	if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) ==
407*cb00ea35SCyrill Gorcunov 	    EXT_NOT_RECORDED_NOT_ALLOCATED) {
408*cb00ea35SCyrill Gorcunov 		add =
409*cb00ea35SCyrill Gorcunov 		    ((1 << 30) - sb->s_blocksize -
410*cb00ea35SCyrill Gorcunov 		     (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >> sb->
411*cb00ea35SCyrill Gorcunov 		    s_blocksize_bits;
41231170b6aSJan Kara 		if (add > blocks)
41331170b6aSJan Kara 			add = blocks;
41431170b6aSJan Kara 		blocks -= add;
41531170b6aSJan Kara 		last_ext->extLength += add << sb->s_blocksize_bits;
41631170b6aSJan Kara 	}
41731170b6aSJan Kara 
41831170b6aSJan Kara 	if (fake) {
41931170b6aSJan Kara 		udf_add_aext(inode, last_pos, last_ext->extLocation,
42031170b6aSJan Kara 			     last_ext->extLength, 1);
42131170b6aSJan Kara 		count++;
422*cb00ea35SCyrill Gorcunov 	} else
423*cb00ea35SCyrill Gorcunov 		udf_write_aext(inode, last_pos, last_ext->extLocation,
424*cb00ea35SCyrill Gorcunov 			       last_ext->extLength, 1);
42531170b6aSJan Kara 	/* Managed to do everything necessary? */
42631170b6aSJan Kara 	if (!blocks)
42731170b6aSJan Kara 		goto out;
42831170b6aSJan Kara 
42931170b6aSJan Kara 	/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
43031170b6aSJan Kara 	last_ext->extLocation.logicalBlockNum = 0;
43131170b6aSJan Kara 	last_ext->extLocation.partitionReferenceNum = 0;
43231170b6aSJan Kara 	add = (1 << (30 - sb->s_blocksize_bits)) - 1;
433*cb00ea35SCyrill Gorcunov 	last_ext->extLength =
434*cb00ea35SCyrill Gorcunov 	    EXT_NOT_RECORDED_NOT_ALLOCATED | (add << sb->s_blocksize_bits);
43531170b6aSJan Kara 	/* Create enough extents to cover the whole hole */
43631170b6aSJan Kara 	while (blocks > add) {
43731170b6aSJan Kara 		blocks -= add;
43831170b6aSJan Kara 		if (udf_add_aext(inode, last_pos, last_ext->extLocation,
43931170b6aSJan Kara 				 last_ext->extLength, 1) == -1)
44031170b6aSJan Kara 			return -1;
44131170b6aSJan Kara 		count++;
44231170b6aSJan Kara 	}
44331170b6aSJan Kara 	if (blocks) {
44431170b6aSJan Kara 		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
44531170b6aSJan Kara 		    (blocks << sb->s_blocksize_bits);
44631170b6aSJan Kara 		if (udf_add_aext(inode, last_pos, last_ext->extLocation,
44731170b6aSJan Kara 				 last_ext->extLength, 1) == -1)
44831170b6aSJan Kara 			return -1;
44931170b6aSJan Kara 		count++;
45031170b6aSJan Kara 	}
45131170b6aSJan Kara       out:
45231170b6aSJan Kara 	/* Do we have some preallocated blocks saved? */
45331170b6aSJan Kara 	if (prealloc_len) {
454*cb00ea35SCyrill Gorcunov 		if (udf_add_aext(inode, last_pos, prealloc_loc, prealloc_len, 1)
455*cb00ea35SCyrill Gorcunov 		    == -1)
45631170b6aSJan Kara 			return -1;
45731170b6aSJan Kara 		last_ext->extLocation = prealloc_loc;
45831170b6aSJan Kara 		last_ext->extLength = prealloc_len;
45931170b6aSJan Kara 		count++;
46031170b6aSJan Kara 	}
46131170b6aSJan Kara 	/* last_pos should point to the last written extent... */
46231170b6aSJan Kara 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
46331170b6aSJan Kara 		last_pos->offset -= sizeof(short_ad);
46431170b6aSJan Kara 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
46531170b6aSJan Kara 		last_pos->offset -= sizeof(long_ad);
46631170b6aSJan Kara 	else
46731170b6aSJan Kara 		return -1;
46831170b6aSJan Kara 	return count;
46931170b6aSJan Kara }
47031170b6aSJan Kara 
47160448b1dSJan Kara static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
4721da177e4SLinus Torvalds 					int *err, long *phys, int *new)
4731da177e4SLinus Torvalds {
47431170b6aSJan Kara 	static sector_t last_block;
475ff116fc8SJan Kara 	struct buffer_head *result = NULL;
4761da177e4SLinus Torvalds 	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
477ff116fc8SJan Kara 	struct extent_position prev_epos, cur_epos, next_epos;
4781da177e4SLinus Torvalds 	int count = 0, startnum = 0, endnum = 0;
47985d71244SJan Kara 	uint32_t elen = 0, tmpelen;
48085d71244SJan Kara 	kernel_lb_addr eloc, tmpeloc;
4811da177e4SLinus Torvalds 	int c = 1;
48260448b1dSJan Kara 	loff_t lbcount = 0, b_off = 0;
48360448b1dSJan Kara 	uint32_t newblocknum, newblock;
48460448b1dSJan Kara 	sector_t offset = 0;
4851da177e4SLinus Torvalds 	int8_t etype;
4861da177e4SLinus Torvalds 	int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
48731170b6aSJan Kara 	int lastblock = 0;
4881da177e4SLinus Torvalds 
489ff116fc8SJan Kara 	prev_epos.offset = udf_file_entry_alloc_offset(inode);
490ff116fc8SJan Kara 	prev_epos.block = UDF_I_LOCATION(inode);
491ff116fc8SJan Kara 	prev_epos.bh = NULL;
492ff116fc8SJan Kara 	cur_epos = next_epos = prev_epos;
49360448b1dSJan Kara 	b_off = (loff_t) block << inode->i_sb->s_blocksize_bits;
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	/* find the extent which contains the block we are looking for.
4961da177e4SLinus Torvalds 	   alternate between laarr[0] and laarr[1] for locations of the
4971da177e4SLinus Torvalds 	   current extent, and the previous extent */
498*cb00ea35SCyrill Gorcunov 	do {
499*cb00ea35SCyrill Gorcunov 		if (prev_epos.bh != cur_epos.bh) {
5003bf25cb4SJan Kara 			brelse(prev_epos.bh);
5013bf25cb4SJan Kara 			get_bh(cur_epos.bh);
502ff116fc8SJan Kara 			prev_epos.bh = cur_epos.bh;
5031da177e4SLinus Torvalds 		}
504*cb00ea35SCyrill Gorcunov 		if (cur_epos.bh != next_epos.bh) {
5053bf25cb4SJan Kara 			brelse(cur_epos.bh);
5063bf25cb4SJan Kara 			get_bh(next_epos.bh);
507ff116fc8SJan Kara 			cur_epos.bh = next_epos.bh;
5081da177e4SLinus Torvalds 		}
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds 		lbcount += elen;
5111da177e4SLinus Torvalds 
512ff116fc8SJan Kara 		prev_epos.block = cur_epos.block;
513ff116fc8SJan Kara 		cur_epos.block = next_epos.block;
5141da177e4SLinus Torvalds 
515ff116fc8SJan Kara 		prev_epos.offset = cur_epos.offset;
516ff116fc8SJan Kara 		cur_epos.offset = next_epos.offset;
5171da177e4SLinus Torvalds 
518*cb00ea35SCyrill Gorcunov 		if ((etype =
519*cb00ea35SCyrill Gorcunov 		     udf_next_aext(inode, &next_epos, &eloc, &elen, 1)) == -1)
5201da177e4SLinus Torvalds 			break;
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 		c = !c;
5231da177e4SLinus Torvalds 
5241da177e4SLinus Torvalds 		laarr[c].extLength = (etype << 30) | elen;
5251da177e4SLinus Torvalds 		laarr[c].extLocation = eloc;
5261da177e4SLinus Torvalds 
5271da177e4SLinus Torvalds 		if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
5281da177e4SLinus Torvalds 			pgoal = eloc.logicalBlockNum +
5291da177e4SLinus Torvalds 			    ((elen + inode->i_sb->s_blocksize - 1) >>
5301da177e4SLinus Torvalds 			     inode->i_sb->s_blocksize_bits);
5311da177e4SLinus Torvalds 
5321da177e4SLinus Torvalds 		count++;
5331da177e4SLinus Torvalds 	} while (lbcount + elen <= b_off);
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds 	b_off -= lbcount;
5361da177e4SLinus Torvalds 	offset = b_off >> inode->i_sb->s_blocksize_bits;
53785d71244SJan Kara 	/*
53885d71244SJan Kara 	 * Move prev_epos and cur_epos into indirect extent if we are at
53985d71244SJan Kara 	 * the pointer to it
54085d71244SJan Kara 	 */
54185d71244SJan Kara 	udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
54285d71244SJan Kara 	udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);
5431da177e4SLinus Torvalds 
5441da177e4SLinus Torvalds 	/* if the extent is allocated and recorded, return the block
5451da177e4SLinus Torvalds 	   if the extent is not a multiple of the blocksize, round up */
5461da177e4SLinus Torvalds 
547*cb00ea35SCyrill Gorcunov 	if (etype == (EXT_RECORDED_ALLOCATED >> 30)) {
548*cb00ea35SCyrill Gorcunov 		if (elen & (inode->i_sb->s_blocksize - 1)) {
5491da177e4SLinus Torvalds 			elen = EXT_RECORDED_ALLOCATED |
5501da177e4SLinus Torvalds 			    ((elen + inode->i_sb->s_blocksize - 1) &
5511da177e4SLinus Torvalds 			     ~(inode->i_sb->s_blocksize - 1));
552ff116fc8SJan Kara 			etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
5531da177e4SLinus Torvalds 		}
5543bf25cb4SJan Kara 		brelse(prev_epos.bh);
5553bf25cb4SJan Kara 		brelse(cur_epos.bh);
5563bf25cb4SJan Kara 		brelse(next_epos.bh);
5571da177e4SLinus Torvalds 		newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
5581da177e4SLinus Torvalds 		*phys = newblock;
5591da177e4SLinus Torvalds 		return NULL;
5601da177e4SLinus Torvalds 	}
5611da177e4SLinus Torvalds 
56231170b6aSJan Kara 	last_block = block;
56331170b6aSJan Kara 	/* Are we beyond EOF? */
564*cb00ea35SCyrill Gorcunov 	if (etype == -1) {
56531170b6aSJan Kara 		int ret;
56631170b6aSJan Kara 
56731170b6aSJan Kara 		if (count) {
56831170b6aSJan Kara 			if (c)
56931170b6aSJan Kara 				laarr[0] = laarr[1];
57031170b6aSJan Kara 			startnum = 1;
571*cb00ea35SCyrill Gorcunov 		} else {
57231170b6aSJan Kara 			/* Create a fake extent when there's not one */
573*cb00ea35SCyrill Gorcunov 			memset(&laarr[0].extLocation, 0x00,
574*cb00ea35SCyrill Gorcunov 			       sizeof(kernel_lb_addr));
57531170b6aSJan Kara 			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
57631170b6aSJan Kara 			/* Will udf_extend_file() create real extent from a fake one? */
57731170b6aSJan Kara 			startnum = (offset > 0);
57831170b6aSJan Kara 		}
57931170b6aSJan Kara 		/* Create extents for the hole between EOF and offset */
58031170b6aSJan Kara 		ret = udf_extend_file(inode, &prev_epos, laarr, offset);
58131170b6aSJan Kara 		if (ret == -1) {
58231170b6aSJan Kara 			brelse(prev_epos.bh);
58331170b6aSJan Kara 			brelse(cur_epos.bh);
58431170b6aSJan Kara 			brelse(next_epos.bh);
58531170b6aSJan Kara 			/* We don't really know the error here so we just make
58631170b6aSJan Kara 			 * something up */
58731170b6aSJan Kara 			*err = -ENOSPC;
58831170b6aSJan Kara 			return NULL;
58931170b6aSJan Kara 		}
59031170b6aSJan Kara 		c = 0;
59131170b6aSJan Kara 		offset = 0;
59231170b6aSJan Kara 		count += ret;
59331170b6aSJan Kara 		/* We are not covered by a preallocated extent? */
594*cb00ea35SCyrill Gorcunov 		if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) !=
595*cb00ea35SCyrill Gorcunov 		    EXT_NOT_RECORDED_ALLOCATED) {
59631170b6aSJan Kara 			/* Is there any real extent? - otherwise we overwrite
59731170b6aSJan Kara 			 * the fake one... */
59831170b6aSJan Kara 			if (count)
5991da177e4SLinus Torvalds 				c = !c;
6001da177e4SLinus Torvalds 			laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
60131170b6aSJan Kara 			    inode->i_sb->s_blocksize;
602*cb00ea35SCyrill Gorcunov 			memset(&laarr[c].extLocation, 0x00,
603*cb00ea35SCyrill Gorcunov 			       sizeof(kernel_lb_addr));
6041da177e4SLinus Torvalds 			count++;
6051da177e4SLinus Torvalds 			endnum++;
60631170b6aSJan Kara 		}
60731170b6aSJan Kara 		endnum = c + 1;
6081da177e4SLinus Torvalds 		lastblock = 1;
609*cb00ea35SCyrill Gorcunov 	} else {
6101da177e4SLinus Torvalds 		endnum = startnum = ((count > 2) ? 2 : count);
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 		/* if the current extent is in position 0, swap it with the previous */
613*cb00ea35SCyrill Gorcunov 		if (!c && count != 1) {
6141da177e4SLinus Torvalds 			laarr[2] = laarr[0];
6151da177e4SLinus Torvalds 			laarr[0] = laarr[1];
6161da177e4SLinus Torvalds 			laarr[1] = laarr[2];
6171da177e4SLinus Torvalds 			c = 1;
6181da177e4SLinus Torvalds 		}
6191da177e4SLinus Torvalds 
62031170b6aSJan Kara 		/* if the current block is located in an extent, read the next extent */
621*cb00ea35SCyrill Gorcunov 		if ((etype =
622*cb00ea35SCyrill Gorcunov 		     udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1) {
6231da177e4SLinus Torvalds 			laarr[c + 1].extLength = (etype << 30) | elen;
6241da177e4SLinus Torvalds 			laarr[c + 1].extLocation = eloc;
6251da177e4SLinus Torvalds 			count++;
6261da177e4SLinus Torvalds 			startnum++;
6271da177e4SLinus Torvalds 			endnum++;
628*cb00ea35SCyrill Gorcunov 		} else {
6291da177e4SLinus Torvalds 			lastblock = 1;
6301da177e4SLinus Torvalds 		}
63131170b6aSJan Kara 	}
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds 	/* if the current extent is not recorded but allocated, get the
6341da177e4SLinus Torvalds 	   block in the extent corresponding to the requested block */
6351da177e4SLinus Torvalds 	if ((laarr[c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30))
6361da177e4SLinus Torvalds 		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
637*cb00ea35SCyrill Gorcunov 	else {			/* otherwise, allocate a new block */
638*cb00ea35SCyrill Gorcunov 
6391da177e4SLinus Torvalds 		if (UDF_I_NEXT_ALLOC_BLOCK(inode) == block)
6401da177e4SLinus Torvalds 			goal = UDF_I_NEXT_ALLOC_GOAL(inode);
6411da177e4SLinus Torvalds 
642*cb00ea35SCyrill Gorcunov 		if (!goal) {
6431da177e4SLinus Torvalds 			if (!(goal = pgoal))
644*cb00ea35SCyrill Gorcunov 				goal =
645*cb00ea35SCyrill Gorcunov 				    UDF_I_LOCATION(inode).logicalBlockNum + 1;
6461da177e4SLinus Torvalds 		}
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds 		if (!(newblocknum = udf_new_block(inode->i_sb, inode,
649*cb00ea35SCyrill Gorcunov 						  UDF_I_LOCATION(inode).
650*cb00ea35SCyrill Gorcunov 						  partitionReferenceNum, goal,
651*cb00ea35SCyrill Gorcunov 						  err))) {
6523bf25cb4SJan Kara 			brelse(prev_epos.bh);
6531da177e4SLinus Torvalds 			*err = -ENOSPC;
6541da177e4SLinus Torvalds 			return NULL;
6551da177e4SLinus Torvalds 		}
6561da177e4SLinus Torvalds 		UDF_I_LENEXTENTS(inode) += inode->i_sb->s_blocksize;
6571da177e4SLinus Torvalds 	}
6581da177e4SLinus Torvalds 
6591da177e4SLinus Torvalds 	/* if the extent the requsted block is located in contains multiple blocks,
6601da177e4SLinus Torvalds 	   split the extent into at most three extents. blocks prior to requested
6611da177e4SLinus Torvalds 	   block, requested block, and blocks after requested block */
6621da177e4SLinus Torvalds 	udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds #ifdef UDF_PREALLOCATE
6651da177e4SLinus Torvalds 	/* preallocate blocks */
6661da177e4SLinus Torvalds 	udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
6671da177e4SLinus Torvalds #endif
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	/* merge any continuous blocks in laarr */
6701da177e4SLinus Torvalds 	udf_merge_extents(inode, laarr, &endnum);
6711da177e4SLinus Torvalds 
6721da177e4SLinus Torvalds 	/* write back the new extents, inserting new extents if the new number
6731da177e4SLinus Torvalds 	   of extents is greater than the old number, and deleting extents if
6741da177e4SLinus Torvalds 	   the new number of extents is less than the old number */
675ff116fc8SJan Kara 	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
6761da177e4SLinus Torvalds 
6773bf25cb4SJan Kara 	brelse(prev_epos.bh);
6781da177e4SLinus Torvalds 
6791da177e4SLinus Torvalds 	if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
680*cb00ea35SCyrill Gorcunov 					UDF_I_LOCATION(inode).
681*cb00ea35SCyrill Gorcunov 					partitionReferenceNum, 0))) {
6821da177e4SLinus Torvalds 		return NULL;
6831da177e4SLinus Torvalds 	}
6841da177e4SLinus Torvalds 	*phys = newblock;
6851da177e4SLinus Torvalds 	*err = 0;
6861da177e4SLinus Torvalds 	*new = 1;
6871da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_BLOCK(inode) = block;
6881da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum;
6891da177e4SLinus Torvalds 	inode->i_ctime = current_fs_time(inode->i_sb);
6901da177e4SLinus Torvalds 
6911da177e4SLinus Torvalds 	if (IS_SYNC(inode))
6921da177e4SLinus Torvalds 		udf_sync_inode(inode);
6931da177e4SLinus Torvalds 	else
6941da177e4SLinus Torvalds 		mark_inode_dirty(inode);
6951da177e4SLinus Torvalds 	return result;
6961da177e4SLinus Torvalds }
6971da177e4SLinus Torvalds 
698*cb00ea35SCyrill Gorcunov static void udf_split_extents(struct inode *inode, int *c, int offset,
699*cb00ea35SCyrill Gorcunov 			      int newblocknum,
700*cb00ea35SCyrill Gorcunov 			      kernel_long_ad laarr[EXTENT_MERGE_SIZE],
701*cb00ea35SCyrill Gorcunov 			      int *endnum)
7021da177e4SLinus Torvalds {
7031da177e4SLinus Torvalds 	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
704*cb00ea35SCyrill Gorcunov 	    (laarr[*c].extLength >> 30) ==
705*cb00ea35SCyrill Gorcunov 	    (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) {
7061da177e4SLinus Torvalds 		int curr = *c;
7071da177e4SLinus Torvalds 		int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) +
708*cb00ea35SCyrill Gorcunov 			    inode->i_sb->s_blocksize -
709*cb00ea35SCyrill Gorcunov 			    1) >> inode->i_sb->s_blocksize_bits;
7101da177e4SLinus Torvalds 		int8_t etype = (laarr[curr].extLength >> 30);
7111da177e4SLinus Torvalds 
712*cb00ea35SCyrill Gorcunov 		if (blen == 1) ;
713*cb00ea35SCyrill Gorcunov 		else if (!offset || blen == offset + 1) {
7141da177e4SLinus Torvalds 			laarr[curr + 2] = laarr[curr + 1];
7151da177e4SLinus Torvalds 			laarr[curr + 1] = laarr[curr];
716*cb00ea35SCyrill Gorcunov 		} else {
7171da177e4SLinus Torvalds 			laarr[curr + 3] = laarr[curr + 1];
7181da177e4SLinus Torvalds 			laarr[curr + 2] = laarr[curr + 1] = laarr[curr];
7191da177e4SLinus Torvalds 		}
7201da177e4SLinus Torvalds 
721*cb00ea35SCyrill Gorcunov 		if (offset) {
722*cb00ea35SCyrill Gorcunov 			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
723*cb00ea35SCyrill Gorcunov 				udf_free_blocks(inode->i_sb, inode,
724*cb00ea35SCyrill Gorcunov 						laarr[curr].extLocation, 0,
725*cb00ea35SCyrill Gorcunov 						offset);
726*cb00ea35SCyrill Gorcunov 				laarr[curr].extLength =
727*cb00ea35SCyrill Gorcunov 				    EXT_NOT_RECORDED_NOT_ALLOCATED | (offset <<
728*cb00ea35SCyrill Gorcunov 								      inode->
729*cb00ea35SCyrill Gorcunov 								      i_sb->
730*cb00ea35SCyrill Gorcunov 								      s_blocksize_bits);
7311da177e4SLinus Torvalds 				laarr[curr].extLocation.logicalBlockNum = 0;
732*cb00ea35SCyrill Gorcunov 				laarr[curr].extLocation.partitionReferenceNum =
733*cb00ea35SCyrill Gorcunov 				    0;
734*cb00ea35SCyrill Gorcunov 			} else
7351da177e4SLinus Torvalds 				laarr[curr].extLength = (etype << 30) |
7361da177e4SLinus Torvalds 				    (offset << inode->i_sb->s_blocksize_bits);
7371da177e4SLinus Torvalds 			curr++;
7381da177e4SLinus Torvalds 			(*c)++;
7391da177e4SLinus Torvalds 			(*endnum)++;
7401da177e4SLinus Torvalds 		}
7411da177e4SLinus Torvalds 
7421da177e4SLinus Torvalds 		laarr[curr].extLocation.logicalBlockNum = newblocknum;
7431da177e4SLinus Torvalds 		if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
7441da177e4SLinus Torvalds 			laarr[curr].extLocation.partitionReferenceNum =
7451da177e4SLinus Torvalds 			    UDF_I_LOCATION(inode).partitionReferenceNum;
7461da177e4SLinus Torvalds 		laarr[curr].extLength = EXT_RECORDED_ALLOCATED |
7471da177e4SLinus Torvalds 		    inode->i_sb->s_blocksize;
7481da177e4SLinus Torvalds 		curr++;
7491da177e4SLinus Torvalds 
750*cb00ea35SCyrill Gorcunov 		if (blen != offset + 1) {
7511da177e4SLinus Torvalds 			if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
752*cb00ea35SCyrill Gorcunov 				laarr[curr].extLocation.logicalBlockNum +=
753*cb00ea35SCyrill Gorcunov 				    (offset + 1);
754*cb00ea35SCyrill Gorcunov 			laarr[curr].extLength =
755*cb00ea35SCyrill Gorcunov 			    (etype << 30) | ((blen - (offset + 1)) << inode->
756*cb00ea35SCyrill Gorcunov 					     i_sb->s_blocksize_bits);
7571da177e4SLinus Torvalds 			curr++;
7581da177e4SLinus Torvalds 			(*endnum)++;
7591da177e4SLinus Torvalds 		}
7601da177e4SLinus Torvalds 	}
7611da177e4SLinus Torvalds }
7621da177e4SLinus Torvalds 
7631da177e4SLinus Torvalds static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
764*cb00ea35SCyrill Gorcunov 				 kernel_long_ad laarr[EXTENT_MERGE_SIZE],
765*cb00ea35SCyrill Gorcunov 				 int *endnum)
7661da177e4SLinus Torvalds {
7671da177e4SLinus Torvalds 	int start, length = 0, currlength = 0, i;
7681da177e4SLinus Torvalds 
769*cb00ea35SCyrill Gorcunov 	if (*endnum >= (c + 1)) {
7701da177e4SLinus Torvalds 		if (!lastblock)
7711da177e4SLinus Torvalds 			return;
7721da177e4SLinus Torvalds 		else
7731da177e4SLinus Torvalds 			start = c;
774*cb00ea35SCyrill Gorcunov 	} else {
775*cb00ea35SCyrill Gorcunov 		if ((laarr[c + 1].extLength >> 30) ==
776*cb00ea35SCyrill Gorcunov 		    (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
7771da177e4SLinus Torvalds 			start = c + 1;
778*cb00ea35SCyrill Gorcunov 			length = currlength =
779*cb00ea35SCyrill Gorcunov 			    (((laarr[c + 1].
780*cb00ea35SCyrill Gorcunov 			       extLength & UDF_EXTENT_LENGTH_MASK) +
781*cb00ea35SCyrill Gorcunov 			      inode->i_sb->s_blocksize -
782*cb00ea35SCyrill Gorcunov 			      1) >> inode->i_sb->s_blocksize_bits);
783*cb00ea35SCyrill Gorcunov 		} else
7841da177e4SLinus Torvalds 			start = c;
7851da177e4SLinus Torvalds 	}
7861da177e4SLinus Torvalds 
787*cb00ea35SCyrill Gorcunov 	for (i = start + 1; i <= *endnum; i++) {
788*cb00ea35SCyrill Gorcunov 		if (i == *endnum) {
7891da177e4SLinus Torvalds 			if (lastblock)
7901da177e4SLinus Torvalds 				length += UDF_DEFAULT_PREALLOC_BLOCKS;
791*cb00ea35SCyrill Gorcunov 		} else if ((laarr[i].extLength >> 30) ==
792*cb00ea35SCyrill Gorcunov 			   (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
793*cb00ea35SCyrill Gorcunov 			length +=
794*cb00ea35SCyrill Gorcunov 			    (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
795*cb00ea35SCyrill Gorcunov 			      inode->i_sb->s_blocksize -
796*cb00ea35SCyrill Gorcunov 			      1) >> inode->i_sb->s_blocksize_bits);
7971da177e4SLinus Torvalds 		else
7981da177e4SLinus Torvalds 			break;
7991da177e4SLinus Torvalds 	}
8001da177e4SLinus Torvalds 
801*cb00ea35SCyrill Gorcunov 	if (length) {
8021da177e4SLinus Torvalds 		int next = laarr[start].extLocation.logicalBlockNum +
8031da177e4SLinus Torvalds 		    (((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
804*cb00ea35SCyrill Gorcunov 		      inode->i_sb->s_blocksize -
805*cb00ea35SCyrill Gorcunov 		      1) >> inode->i_sb->s_blocksize_bits);
8061da177e4SLinus Torvalds 		int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
807*cb00ea35SCyrill Gorcunov 						   laarr[start].extLocation.
808*cb00ea35SCyrill Gorcunov 						   partitionReferenceNum,
809*cb00ea35SCyrill Gorcunov 						   next,
810*cb00ea35SCyrill Gorcunov 						   (UDF_DEFAULT_PREALLOC_BLOCKS
811*cb00ea35SCyrill Gorcunov 						    >
812*cb00ea35SCyrill Gorcunov 						    length ? length :
813*cb00ea35SCyrill Gorcunov 						    UDF_DEFAULT_PREALLOC_BLOCKS)
814*cb00ea35SCyrill Gorcunov 						   - currlength);
8151da177e4SLinus Torvalds 
816*cb00ea35SCyrill Gorcunov 		if (numalloc) {
8171da177e4SLinus Torvalds 			if (start == (c + 1))
8181da177e4SLinus Torvalds 				laarr[start].extLength +=
8191da177e4SLinus Torvalds 				    (numalloc << inode->i_sb->s_blocksize_bits);
820*cb00ea35SCyrill Gorcunov 			else {
8211da177e4SLinus Torvalds 				memmove(&laarr[c + 2], &laarr[c + 1],
8221da177e4SLinus Torvalds 					sizeof(long_ad) * (*endnum - (c + 1)));
8231da177e4SLinus Torvalds 				(*endnum)++;
8241da177e4SLinus Torvalds 				laarr[c + 1].extLocation.logicalBlockNum = next;
8251da177e4SLinus Torvalds 				laarr[c + 1].extLocation.partitionReferenceNum =
8261da177e4SLinus Torvalds 				    laarr[c].extLocation.partitionReferenceNum;
827*cb00ea35SCyrill Gorcunov 				laarr[c + 1].extLength =
828*cb00ea35SCyrill Gorcunov 				    EXT_NOT_RECORDED_ALLOCATED | (numalloc <<
829*cb00ea35SCyrill Gorcunov 								  inode->i_sb->
830*cb00ea35SCyrill Gorcunov 								  s_blocksize_bits);
8311da177e4SLinus Torvalds 				start = c + 1;
8321da177e4SLinus Torvalds 			}
8331da177e4SLinus Torvalds 
834*cb00ea35SCyrill Gorcunov 			for (i = start + 1; numalloc && i < *endnum; i++) {
835*cb00ea35SCyrill Gorcunov 				int elen =
836*cb00ea35SCyrill Gorcunov 				    ((laarr[i].
837*cb00ea35SCyrill Gorcunov 				      extLength & UDF_EXTENT_LENGTH_MASK) +
838*cb00ea35SCyrill Gorcunov 				     inode->i_sb->s_blocksize -
839*cb00ea35SCyrill Gorcunov 				     1) >> inode->i_sb->s_blocksize_bits;
8401da177e4SLinus Torvalds 
841*cb00ea35SCyrill Gorcunov 				if (elen > numalloc) {
8421da177e4SLinus Torvalds 					laarr[i].extLength -=
843*cb00ea35SCyrill Gorcunov 					    (numalloc << inode->i_sb->
844*cb00ea35SCyrill Gorcunov 					     s_blocksize_bits);
8451da177e4SLinus Torvalds 					numalloc = 0;
846*cb00ea35SCyrill Gorcunov 				} else {
8471da177e4SLinus Torvalds 					numalloc -= elen;
8481da177e4SLinus Torvalds 					if (*endnum > (i + 1))
849*cb00ea35SCyrill Gorcunov 						memmove(&laarr[i],
850*cb00ea35SCyrill Gorcunov 							&laarr[i + 1],
851*cb00ea35SCyrill Gorcunov 							sizeof(long_ad) *
852*cb00ea35SCyrill Gorcunov 							(*endnum - (i + 1)));
8531da177e4SLinus Torvalds 					i--;
8541da177e4SLinus Torvalds 					(*endnum)--;
8551da177e4SLinus Torvalds 				}
8561da177e4SLinus Torvalds 			}
857*cb00ea35SCyrill Gorcunov 			UDF_I_LENEXTENTS(inode) +=
858*cb00ea35SCyrill Gorcunov 			    numalloc << inode->i_sb->s_blocksize_bits;
8591da177e4SLinus Torvalds 		}
8601da177e4SLinus Torvalds 	}
8611da177e4SLinus Torvalds }
8621da177e4SLinus Torvalds 
8631da177e4SLinus Torvalds static void udf_merge_extents(struct inode *inode,
864*cb00ea35SCyrill Gorcunov 			      kernel_long_ad laarr[EXTENT_MERGE_SIZE],
865*cb00ea35SCyrill Gorcunov 			      int *endnum)
8661da177e4SLinus Torvalds {
8671da177e4SLinus Torvalds 	int i;
8681da177e4SLinus Torvalds 
869*cb00ea35SCyrill Gorcunov 	for (i = 0; i < (*endnum - 1); i++) {
870*cb00ea35SCyrill Gorcunov 		if ((laarr[i].extLength >> 30) ==
871*cb00ea35SCyrill Gorcunov 		    (laarr[i + 1].extLength >> 30)) {
872*cb00ea35SCyrill Gorcunov 			if (((laarr[i].extLength >> 30) ==
873*cb00ea35SCyrill Gorcunov 			     (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
874*cb00ea35SCyrill Gorcunov 			    ||
875*cb00ea35SCyrill Gorcunov 			    ((laarr[i + 1].extLocation.logicalBlockNum -
876*cb00ea35SCyrill Gorcunov 			      laarr[i].extLocation.logicalBlockNum) ==
8771da177e4SLinus Torvalds 			     (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
878*cb00ea35SCyrill Gorcunov 			       inode->i_sb->s_blocksize -
879*cb00ea35SCyrill Gorcunov 			       1) >> inode->i_sb->s_blocksize_bits))) {
880*cb00ea35SCyrill Gorcunov 				if (((laarr[i].
881*cb00ea35SCyrill Gorcunov 				      extLength & UDF_EXTENT_LENGTH_MASK) +
882*cb00ea35SCyrill Gorcunov 				     (laarr[i + 1].
883*cb00ea35SCyrill Gorcunov 				      extLength & UDF_EXTENT_LENGTH_MASK) +
884*cb00ea35SCyrill Gorcunov 				     inode->i_sb->s_blocksize -
885*cb00ea35SCyrill Gorcunov 				     1) & ~UDF_EXTENT_LENGTH_MASK) {
886*cb00ea35SCyrill Gorcunov 					laarr[i + 1].extLength =
887*cb00ea35SCyrill Gorcunov 					    (laarr[i + 1].extLength -
888*cb00ea35SCyrill Gorcunov 					     (laarr[i].
889*cb00ea35SCyrill Gorcunov 					      extLength &
890*cb00ea35SCyrill Gorcunov 					      UDF_EXTENT_LENGTH_MASK) +
891*cb00ea35SCyrill Gorcunov 					     UDF_EXTENT_LENGTH_MASK) & ~(inode->
892*cb00ea35SCyrill Gorcunov 									 i_sb->
893*cb00ea35SCyrill Gorcunov 									 s_blocksize
894*cb00ea35SCyrill Gorcunov 									 - 1);
895*cb00ea35SCyrill Gorcunov 					laarr[i].extLength =
896*cb00ea35SCyrill Gorcunov 					    (laarr[i].
897*cb00ea35SCyrill Gorcunov 					     extLength & UDF_EXTENT_FLAG_MASK) +
898*cb00ea35SCyrill Gorcunov 					    (UDF_EXTENT_LENGTH_MASK + 1) -
899*cb00ea35SCyrill Gorcunov 					    inode->i_sb->s_blocksize;
900*cb00ea35SCyrill Gorcunov 					laarr[i +
901*cb00ea35SCyrill Gorcunov 					      1].extLocation.logicalBlockNum =
902*cb00ea35SCyrill Gorcunov 					    laarr[i].extLocation.
903*cb00ea35SCyrill Gorcunov 					    logicalBlockNum +
904*cb00ea35SCyrill Gorcunov 					    ((laarr[i].
905*cb00ea35SCyrill Gorcunov 					      extLength &
906*cb00ea35SCyrill Gorcunov 					      UDF_EXTENT_LENGTH_MASK) >> inode->
907*cb00ea35SCyrill Gorcunov 					     i_sb->s_blocksize_bits);
908*cb00ea35SCyrill Gorcunov 				} else {
909*cb00ea35SCyrill Gorcunov 					laarr[i].extLength =
910*cb00ea35SCyrill Gorcunov 					    laarr[i + 1].extLength +
911*cb00ea35SCyrill Gorcunov 					    (((laarr[i].
912*cb00ea35SCyrill Gorcunov 					       extLength &
913*cb00ea35SCyrill Gorcunov 					       UDF_EXTENT_LENGTH_MASK) +
914*cb00ea35SCyrill Gorcunov 					      inode->i_sb->s_blocksize -
915*cb00ea35SCyrill Gorcunov 					      1) & ~(inode->i_sb->s_blocksize -
916*cb00ea35SCyrill Gorcunov 						     1));
9171da177e4SLinus Torvalds 					if (*endnum > (i + 2))
918*cb00ea35SCyrill Gorcunov 						memmove(&laarr[i + 1],
919*cb00ea35SCyrill Gorcunov 							&laarr[i + 2],
920*cb00ea35SCyrill Gorcunov 							sizeof(long_ad) *
921*cb00ea35SCyrill Gorcunov 							(*endnum - (i + 2)));
9221da177e4SLinus Torvalds 					i--;
9231da177e4SLinus Torvalds 					(*endnum)--;
9241da177e4SLinus Torvalds 				}
9251da177e4SLinus Torvalds 			}
926*cb00ea35SCyrill Gorcunov 		} else
927*cb00ea35SCyrill Gorcunov 		    if (((laarr[i].extLength >> 30) ==
928*cb00ea35SCyrill Gorcunov 			 (EXT_NOT_RECORDED_ALLOCATED >> 30))
929*cb00ea35SCyrill Gorcunov 			&& ((laarr[i + 1].extLength >> 30) ==
930*cb00ea35SCyrill Gorcunov 			    (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) {
931*cb00ea35SCyrill Gorcunov 			udf_free_blocks(inode->i_sb, inode,
932*cb00ea35SCyrill Gorcunov 					laarr[i].extLocation, 0,
933*cb00ea35SCyrill Gorcunov 					((laarr[i].
934*cb00ea35SCyrill Gorcunov 					  extLength & UDF_EXTENT_LENGTH_MASK) +
935*cb00ea35SCyrill Gorcunov 					 inode->i_sb->s_blocksize -
936*cb00ea35SCyrill Gorcunov 					 1) >> inode->i_sb->s_blocksize_bits);
9371da177e4SLinus Torvalds 			laarr[i].extLocation.logicalBlockNum = 0;
9381da177e4SLinus Torvalds 			laarr[i].extLocation.partitionReferenceNum = 0;
9391da177e4SLinus Torvalds 
9401da177e4SLinus Torvalds 			if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
9411da177e4SLinus Torvalds 			     (laarr[i + 1].extLength & UDF_EXTENT_LENGTH_MASK) +
942*cb00ea35SCyrill Gorcunov 			     inode->i_sb->s_blocksize -
943*cb00ea35SCyrill Gorcunov 			     1) & ~UDF_EXTENT_LENGTH_MASK) {
944*cb00ea35SCyrill Gorcunov 				laarr[i + 1].extLength =
945*cb00ea35SCyrill Gorcunov 				    (laarr[i + 1].extLength -
946*cb00ea35SCyrill Gorcunov 				     (laarr[i].
947*cb00ea35SCyrill Gorcunov 				      extLength & UDF_EXTENT_LENGTH_MASK) +
948*cb00ea35SCyrill Gorcunov 				     UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->
949*cb00ea35SCyrill Gorcunov 								 s_blocksize -
950*cb00ea35SCyrill Gorcunov 								 1);
951*cb00ea35SCyrill Gorcunov 				laarr[i].extLength =
952*cb00ea35SCyrill Gorcunov 				    (laarr[i].
953*cb00ea35SCyrill Gorcunov 				     extLength & UDF_EXTENT_FLAG_MASK) +
954*cb00ea35SCyrill Gorcunov 				    (UDF_EXTENT_LENGTH_MASK + 1) -
955*cb00ea35SCyrill Gorcunov 				    inode->i_sb->s_blocksize;
956*cb00ea35SCyrill Gorcunov 			} else {
9571da177e4SLinus Torvalds 				laarr[i].extLength = laarr[i + 1].extLength +
958*cb00ea35SCyrill Gorcunov 				    (((laarr[i].
959*cb00ea35SCyrill Gorcunov 				       extLength & UDF_EXTENT_LENGTH_MASK) +
960*cb00ea35SCyrill Gorcunov 				      inode->i_sb->s_blocksize -
961*cb00ea35SCyrill Gorcunov 				      1) & ~(inode->i_sb->s_blocksize - 1));
9621da177e4SLinus Torvalds 				if (*endnum > (i + 2))
9631da177e4SLinus Torvalds 					memmove(&laarr[i + 1], &laarr[i + 2],
964*cb00ea35SCyrill Gorcunov 						sizeof(long_ad) * (*endnum -
965*cb00ea35SCyrill Gorcunov 								   (i + 2)));
9661da177e4SLinus Torvalds 				i--;
9671da177e4SLinus Torvalds 				(*endnum)--;
9681da177e4SLinus Torvalds 			}
969*cb00ea35SCyrill Gorcunov 		} else if ((laarr[i].extLength >> 30) ==
970*cb00ea35SCyrill Gorcunov 			   (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
971*cb00ea35SCyrill Gorcunov 			udf_free_blocks(inode->i_sb, inode,
972*cb00ea35SCyrill Gorcunov 					laarr[i].extLocation, 0,
973*cb00ea35SCyrill Gorcunov 					((laarr[i].
974*cb00ea35SCyrill Gorcunov 					  extLength & UDF_EXTENT_LENGTH_MASK) +
975*cb00ea35SCyrill Gorcunov 					 inode->i_sb->s_blocksize -
976*cb00ea35SCyrill Gorcunov 					 1) >> inode->i_sb->s_blocksize_bits);
9771da177e4SLinus Torvalds 			laarr[i].extLocation.logicalBlockNum = 0;
9781da177e4SLinus Torvalds 			laarr[i].extLocation.partitionReferenceNum = 0;
979*cb00ea35SCyrill Gorcunov 			laarr[i].extLength =
980*cb00ea35SCyrill Gorcunov 			    (laarr[i].
981*cb00ea35SCyrill Gorcunov 			     extLength & UDF_EXTENT_LENGTH_MASK) |
9821da177e4SLinus Torvalds 			    EXT_NOT_RECORDED_NOT_ALLOCATED;
9831da177e4SLinus Torvalds 		}
9841da177e4SLinus Torvalds 	}
9851da177e4SLinus Torvalds }
9861da177e4SLinus Torvalds 
9871da177e4SLinus Torvalds static void udf_update_extents(struct inode *inode,
988*cb00ea35SCyrill Gorcunov 			       kernel_long_ad laarr[EXTENT_MERGE_SIZE],
989*cb00ea35SCyrill Gorcunov 			       int startnum, int endnum,
990ff116fc8SJan Kara 			       struct extent_position *epos)
9911da177e4SLinus Torvalds {
9921da177e4SLinus Torvalds 	int start = 0, i;
9931da177e4SLinus Torvalds 	kernel_lb_addr tmploc;
9941da177e4SLinus Torvalds 	uint32_t tmplen;
9951da177e4SLinus Torvalds 
996*cb00ea35SCyrill Gorcunov 	if (startnum > endnum) {
9971da177e4SLinus Torvalds 		for (i = 0; i < (startnum - endnum); i++)
998ff116fc8SJan Kara 			udf_delete_aext(inode, *epos, laarr[i].extLocation,
999ff116fc8SJan Kara 					laarr[i].extLength);
1000*cb00ea35SCyrill Gorcunov 	} else if (startnum < endnum) {
1001*cb00ea35SCyrill Gorcunov 		for (i = 0; i < (endnum - startnum); i++) {
1002ff116fc8SJan Kara 			udf_insert_aext(inode, *epos, laarr[i].extLocation,
1003ff116fc8SJan Kara 					laarr[i].extLength);
1004ff116fc8SJan Kara 			udf_next_aext(inode, epos, &laarr[i].extLocation,
1005ff116fc8SJan Kara 				      &laarr[i].extLength, 1);
10061da177e4SLinus Torvalds 			start++;
10071da177e4SLinus Torvalds 		}
10081da177e4SLinus Torvalds 	}
10091da177e4SLinus Torvalds 
1010*cb00ea35SCyrill Gorcunov 	for (i = start; i < endnum; i++) {
1011ff116fc8SJan Kara 		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
1012ff116fc8SJan Kara 		udf_write_aext(inode, epos, laarr[i].extLocation,
1013ff116fc8SJan Kara 			       laarr[i].extLength, 1);
10141da177e4SLinus Torvalds 	}
10151da177e4SLinus Torvalds }
10161da177e4SLinus Torvalds 
10171da177e4SLinus Torvalds struct buffer_head *udf_bread(struct inode *inode, int block,
10181da177e4SLinus Torvalds 			      int create, int *err)
10191da177e4SLinus Torvalds {
10201da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
10211da177e4SLinus Torvalds 
10221da177e4SLinus Torvalds 	bh = udf_getblk(inode, block, create, err);
10231da177e4SLinus Torvalds 	if (!bh)
10241da177e4SLinus Torvalds 		return NULL;
10251da177e4SLinus Torvalds 
10261da177e4SLinus Torvalds 	if (buffer_uptodate(bh))
10271da177e4SLinus Torvalds 		return bh;
10281da177e4SLinus Torvalds 	ll_rw_block(READ, 1, &bh);
10291da177e4SLinus Torvalds 	wait_on_buffer(bh);
10301da177e4SLinus Torvalds 	if (buffer_uptodate(bh))
10311da177e4SLinus Torvalds 		return bh;
10321da177e4SLinus Torvalds 	brelse(bh);
10331da177e4SLinus Torvalds 	*err = -EIO;
10341da177e4SLinus Torvalds 	return NULL;
10351da177e4SLinus Torvalds }
10361da177e4SLinus Torvalds 
10371da177e4SLinus Torvalds void udf_truncate(struct inode *inode)
10381da177e4SLinus Torvalds {
10391da177e4SLinus Torvalds 	int offset;
10401da177e4SLinus Torvalds 	int err;
10411da177e4SLinus Torvalds 
10421da177e4SLinus Torvalds 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
10431da177e4SLinus Torvalds 	      S_ISLNK(inode->i_mode)))
10441da177e4SLinus Torvalds 		return;
10451da177e4SLinus Torvalds 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
10461da177e4SLinus Torvalds 		return;
10471da177e4SLinus Torvalds 
10481da177e4SLinus Torvalds 	lock_kernel();
1049*cb00ea35SCyrill Gorcunov 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
1050*cb00ea35SCyrill Gorcunov 		if (inode->i_sb->s_blocksize <
1051*cb00ea35SCyrill Gorcunov 		    (udf_file_entry_alloc_offset(inode) + inode->i_size)) {
10521da177e4SLinus Torvalds 			udf_expand_file_adinicb(inode, inode->i_size, &err);
1053*cb00ea35SCyrill Gorcunov 			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
10541da177e4SLinus Torvalds 				inode->i_size = UDF_I_LENALLOC(inode);
10551da177e4SLinus Torvalds 				unlock_kernel();
10561da177e4SLinus Torvalds 				return;
1057*cb00ea35SCyrill Gorcunov 			} else
10581da177e4SLinus Torvalds 				udf_truncate_extents(inode);
1059*cb00ea35SCyrill Gorcunov 		} else {
10601da177e4SLinus Torvalds 			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
1061*cb00ea35SCyrill Gorcunov 			memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) +
1062*cb00ea35SCyrill Gorcunov 			       offset, 0x00,
1063*cb00ea35SCyrill Gorcunov 			       inode->i_sb->s_blocksize - offset -
1064*cb00ea35SCyrill Gorcunov 			       udf_file_entry_alloc_offset(inode));
10651da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) = inode->i_size;
10661da177e4SLinus Torvalds 		}
1067*cb00ea35SCyrill Gorcunov 	} else {
1068*cb00ea35SCyrill Gorcunov 		block_truncate_page(inode->i_mapping, inode->i_size,
1069*cb00ea35SCyrill Gorcunov 				    udf_get_block);
10701da177e4SLinus Torvalds 		udf_truncate_extents(inode);
10711da177e4SLinus Torvalds 	}
10721da177e4SLinus Torvalds 
10731da177e4SLinus Torvalds 	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
10741da177e4SLinus Torvalds 	if (IS_SYNC(inode))
10751da177e4SLinus Torvalds 		udf_sync_inode(inode);
10761da177e4SLinus Torvalds 	else
10771da177e4SLinus Torvalds 		mark_inode_dirty(inode);
10781da177e4SLinus Torvalds 	unlock_kernel();
10791da177e4SLinus Torvalds }
10801da177e4SLinus Torvalds 
1081*cb00ea35SCyrill Gorcunov static void __udf_read_inode(struct inode *inode)
10821da177e4SLinus Torvalds {
10831da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
10841da177e4SLinus Torvalds 	struct fileEntry *fe;
10851da177e4SLinus Torvalds 	uint16_t ident;
10861da177e4SLinus Torvalds 
10871da177e4SLinus Torvalds 	/*
10881da177e4SLinus Torvalds 	 * Set defaults, but the inode is still incomplete!
10891da177e4SLinus Torvalds 	 * Note: get_new_inode() sets the following on a new inode:
10901da177e4SLinus Torvalds 	 *      i_sb = sb
10911da177e4SLinus Torvalds 	 *      i_no = ino
10921da177e4SLinus Torvalds 	 *      i_flags = sb->s_flags
10931da177e4SLinus Torvalds 	 *      i_state = 0
10941da177e4SLinus Torvalds 	 * clean_inode(): zero fills and sets
10951da177e4SLinus Torvalds 	 *      i_count = 1
10961da177e4SLinus Torvalds 	 *      i_nlink = 1
10971da177e4SLinus Torvalds 	 *      i_op = NULL;
10981da177e4SLinus Torvalds 	 */
10991da177e4SLinus Torvalds 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
11001da177e4SLinus Torvalds 
1101*cb00ea35SCyrill Gorcunov 	if (!bh) {
11021da177e4SLinus Torvalds 		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
11031da177e4SLinus Torvalds 		       inode->i_ino);
11041da177e4SLinus Torvalds 		make_bad_inode(inode);
11051da177e4SLinus Torvalds 		return;
11061da177e4SLinus Torvalds 	}
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
1109*cb00ea35SCyrill Gorcunov 	    ident != TAG_IDENT_USE) {
1110*cb00ea35SCyrill Gorcunov 		printk(KERN_ERR
1111*cb00ea35SCyrill Gorcunov 		       "udf: udf_read_inode(ino %ld) failed ident=%d\n",
11121da177e4SLinus Torvalds 		       inode->i_ino, ident);
11133bf25cb4SJan Kara 		brelse(bh);
11141da177e4SLinus Torvalds 		make_bad_inode(inode);
11151da177e4SLinus Torvalds 		return;
11161da177e4SLinus Torvalds 	}
11171da177e4SLinus Torvalds 
11181da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
11191da177e4SLinus Torvalds 
1120*cb00ea35SCyrill Gorcunov 	if (le16_to_cpu(fe->icbTag.strategyType) == 4096) {
11211da177e4SLinus Torvalds 		struct buffer_head *ibh = NULL, *nbh = NULL;
11221da177e4SLinus Torvalds 		struct indirectEntry *ie;
11231da177e4SLinus Torvalds 
1124*cb00ea35SCyrill Gorcunov 		ibh =
1125*cb00ea35SCyrill Gorcunov 		    udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1,
1126*cb00ea35SCyrill Gorcunov 				     &ident);
1127*cb00ea35SCyrill Gorcunov 		if (ident == TAG_IDENT_IE) {
1128*cb00ea35SCyrill Gorcunov 			if (ibh) {
11291da177e4SLinus Torvalds 				kernel_lb_addr loc;
11301da177e4SLinus Torvalds 				ie = (struct indirectEntry *)ibh->b_data;
11311da177e4SLinus Torvalds 
11321da177e4SLinus Torvalds 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
11331da177e4SLinus Torvalds 
11341da177e4SLinus Torvalds 				if (ie->indirectICB.extLength &&
1135*cb00ea35SCyrill Gorcunov 				    (nbh =
1136*cb00ea35SCyrill Gorcunov 				     udf_read_ptagged(inode->i_sb, loc, 0,
1137*cb00ea35SCyrill Gorcunov 						      &ident))) {
1138*cb00ea35SCyrill Gorcunov 					if (ident == TAG_IDENT_FE
1139*cb00ea35SCyrill Gorcunov 					    || ident == TAG_IDENT_EFE) {
1140*cb00ea35SCyrill Gorcunov 						memcpy(&UDF_I_LOCATION(inode),
1141*cb00ea35SCyrill Gorcunov 						       &loc,
1142*cb00ea35SCyrill Gorcunov 						       sizeof(kernel_lb_addr));
11433bf25cb4SJan Kara 						brelse(bh);
11443bf25cb4SJan Kara 						brelse(ibh);
11453bf25cb4SJan Kara 						brelse(nbh);
11461da177e4SLinus Torvalds 						__udf_read_inode(inode);
11471da177e4SLinus Torvalds 						return;
1148*cb00ea35SCyrill Gorcunov 					} else {
11493bf25cb4SJan Kara 						brelse(nbh);
11503bf25cb4SJan Kara 						brelse(ibh);
11511da177e4SLinus Torvalds 					}
1152*cb00ea35SCyrill Gorcunov 				} else
11533bf25cb4SJan Kara 					brelse(ibh);
11541da177e4SLinus Torvalds 			}
1155*cb00ea35SCyrill Gorcunov 		} else
11563bf25cb4SJan Kara 			brelse(ibh);
1157*cb00ea35SCyrill Gorcunov 	} else if (le16_to_cpu(fe->icbTag.strategyType) != 4) {
11581da177e4SLinus Torvalds 		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
11591da177e4SLinus Torvalds 		       le16_to_cpu(fe->icbTag.strategyType));
11603bf25cb4SJan Kara 		brelse(bh);
11611da177e4SLinus Torvalds 		make_bad_inode(inode);
11621da177e4SLinus Torvalds 		return;
11631da177e4SLinus Torvalds 	}
11641da177e4SLinus Torvalds 	udf_fill_inode(inode, bh);
116531170b6aSJan Kara 
11663bf25cb4SJan Kara 	brelse(bh);
11671da177e4SLinus Torvalds }
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
11701da177e4SLinus Torvalds {
11711da177e4SLinus Torvalds 	struct fileEntry *fe;
11721da177e4SLinus Torvalds 	struct extendedFileEntry *efe;
11731da177e4SLinus Torvalds 	time_t convtime;
11741da177e4SLinus Torvalds 	long convtime_usec;
11751da177e4SLinus Torvalds 	int offset;
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
11781da177e4SLinus Torvalds 	efe = (struct extendedFileEntry *)bh->b_data;
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 	if (le16_to_cpu(fe->icbTag.strategyType) == 4)
11811da177e4SLinus Torvalds 		UDF_I_STRAT4096(inode) = 0;
11821da177e4SLinus Torvalds 	else			/* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */
11831da177e4SLinus Torvalds 		UDF_I_STRAT4096(inode) = 1;
11841da177e4SLinus Torvalds 
1185*cb00ea35SCyrill Gorcunov 	UDF_I_ALLOCTYPE(inode) =
1186*cb00ea35SCyrill Gorcunov 	    le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK;
11871da177e4SLinus Torvalds 	UDF_I_UNIQUE(inode) = 0;
11881da177e4SLinus Torvalds 	UDF_I_LENEATTR(inode) = 0;
11891da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = 0;
11901da177e4SLinus Torvalds 	UDF_I_LENALLOC(inode) = 0;
11911da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
11921da177e4SLinus Torvalds 	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
1193*cb00ea35SCyrill Gorcunov 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE) {
11941da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 1;
11951da177e4SLinus Torvalds 		UDF_I_USE(inode) = 0;
1196*cb00ea35SCyrill Gorcunov 		if (udf_alloc_i_data
1197*cb00ea35SCyrill Gorcunov 		    (inode,
1198*cb00ea35SCyrill Gorcunov 		     inode->i_sb->s_blocksize -
1199*cb00ea35SCyrill Gorcunov 		     sizeof(struct extendedFileEntry))) {
1200647bd61aSCyrill Gorcunov 			make_bad_inode(inode);
1201647bd61aSCyrill Gorcunov 			return;
1202647bd61aSCyrill Gorcunov 		}
1203*cb00ea35SCyrill Gorcunov 		memcpy(UDF_I_DATA(inode),
1204*cb00ea35SCyrill Gorcunov 		       bh->b_data + sizeof(struct extendedFileEntry),
1205*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize -
1206*cb00ea35SCyrill Gorcunov 		       sizeof(struct extendedFileEntry));
1207*cb00ea35SCyrill Gorcunov 	} else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) {
12081da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 0;
12091da177e4SLinus Torvalds 		UDF_I_USE(inode) = 0;
1210*cb00ea35SCyrill Gorcunov 		if (udf_alloc_i_data
1211*cb00ea35SCyrill Gorcunov 		    (inode,
1212*cb00ea35SCyrill Gorcunov 		     inode->i_sb->s_blocksize - sizeof(struct fileEntry))) {
1213647bd61aSCyrill Gorcunov 			make_bad_inode(inode);
1214647bd61aSCyrill Gorcunov 			return;
1215647bd61aSCyrill Gorcunov 		}
1216*cb00ea35SCyrill Gorcunov 		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry),
1217*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
1218*cb00ea35SCyrill Gorcunov 	} else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) {
12191da177e4SLinus Torvalds 		UDF_I_EFE(inode) = 0;
12201da177e4SLinus Torvalds 		UDF_I_USE(inode) = 1;
12211da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) =
1222*cb00ea35SCyrill Gorcunov 		    le32_to_cpu(((struct unallocSpaceEntry *)bh->b_data)->
1223*cb00ea35SCyrill Gorcunov 				lengthAllocDescs);
1224*cb00ea35SCyrill Gorcunov 		if (udf_alloc_i_data
1225*cb00ea35SCyrill Gorcunov 		    (inode,
1226*cb00ea35SCyrill Gorcunov 		     inode->i_sb->s_blocksize -
1227*cb00ea35SCyrill Gorcunov 		     sizeof(struct unallocSpaceEntry))) {
1228647bd61aSCyrill Gorcunov 			make_bad_inode(inode);
1229647bd61aSCyrill Gorcunov 			return;
1230647bd61aSCyrill Gorcunov 		}
1231*cb00ea35SCyrill Gorcunov 		memcpy(UDF_I_DATA(inode),
1232*cb00ea35SCyrill Gorcunov 		       bh->b_data + sizeof(struct unallocSpaceEntry),
1233*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize -
1234*cb00ea35SCyrill Gorcunov 		       sizeof(struct unallocSpaceEntry));
12351da177e4SLinus Torvalds 		return;
12361da177e4SLinus Torvalds 	}
12371da177e4SLinus Torvalds 
12381da177e4SLinus Torvalds 	inode->i_uid = le32_to_cpu(fe->uid);
12394d6660ebSPhillip Susi 	if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb,
12404d6660ebSPhillip Susi 						 UDF_FLAG_UID_IGNORE))
12414d6660ebSPhillip Susi 		inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 	inode->i_gid = le32_to_cpu(fe->gid);
12444d6660ebSPhillip Susi 	if (inode->i_gid == -1 || UDF_QUERY_FLAG(inode->i_sb,
12454d6660ebSPhillip Susi 						 UDF_FLAG_GID_IGNORE))
12464d6660ebSPhillip Susi 		inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
12491da177e4SLinus Torvalds 	if (!inode->i_nlink)
12501da177e4SLinus Torvalds 		inode->i_nlink = 1;
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	inode->i_size = le64_to_cpu(fe->informationLength);
12531da177e4SLinus Torvalds 	UDF_I_LENEXTENTS(inode) = inode->i_size;
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 	inode->i_mode = udf_convert_permissions(fe);
12561da177e4SLinus Torvalds 	inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
12571da177e4SLinus Torvalds 
1258*cb00ea35SCyrill Gorcunov 	if (UDF_I_EFE(inode) == 0) {
12591da177e4SLinus Torvalds 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
12601da177e4SLinus Torvalds 		    (inode->i_sb->s_blocksize_bits - 9);
12611da177e4SLinus Torvalds 
12621da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1263*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(fe->accessTime))) {
12641da177e4SLinus Torvalds 			inode->i_atime.tv_sec = convtime;
12651da177e4SLinus Torvalds 			inode->i_atime.tv_nsec = convtime_usec * 1000;
1266*cb00ea35SCyrill Gorcunov 		} else {
12671da177e4SLinus Torvalds 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
12681da177e4SLinus Torvalds 		}
12691da177e4SLinus Torvalds 
12701da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1271*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(fe->modificationTime))) {
12721da177e4SLinus Torvalds 			inode->i_mtime.tv_sec = convtime;
12731da177e4SLinus Torvalds 			inode->i_mtime.tv_nsec = convtime_usec * 1000;
1274*cb00ea35SCyrill Gorcunov 		} else {
12751da177e4SLinus Torvalds 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
12761da177e4SLinus Torvalds 		}
12771da177e4SLinus Torvalds 
12781da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1279*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(fe->attrTime))) {
12801da177e4SLinus Torvalds 			inode->i_ctime.tv_sec = convtime;
12811da177e4SLinus Torvalds 			inode->i_ctime.tv_nsec = convtime_usec * 1000;
1282*cb00ea35SCyrill Gorcunov 		} else {
12831da177e4SLinus Torvalds 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
12841da177e4SLinus Torvalds 		}
12851da177e4SLinus Torvalds 
12861da177e4SLinus Torvalds 		UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
12871da177e4SLinus Torvalds 		UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
12881da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
12891da177e4SLinus Torvalds 		offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
1290*cb00ea35SCyrill Gorcunov 	} else {
12911da177e4SLinus Torvalds 		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
12921da177e4SLinus Torvalds 		    (inode->i_sb->s_blocksize_bits - 9);
12931da177e4SLinus Torvalds 
12941da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1295*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(efe->accessTime))) {
12961da177e4SLinus Torvalds 			inode->i_atime.tv_sec = convtime;
12971da177e4SLinus Torvalds 			inode->i_atime.tv_nsec = convtime_usec * 1000;
1298*cb00ea35SCyrill Gorcunov 		} else {
12991da177e4SLinus Torvalds 			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
13001da177e4SLinus Torvalds 		}
13011da177e4SLinus Torvalds 
13021da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1303*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(efe->modificationTime))) {
13041da177e4SLinus Torvalds 			inode->i_mtime.tv_sec = convtime;
13051da177e4SLinus Torvalds 			inode->i_mtime.tv_nsec = convtime_usec * 1000;
1306*cb00ea35SCyrill Gorcunov 		} else {
13071da177e4SLinus Torvalds 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
13081da177e4SLinus Torvalds 		}
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1311*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(efe->createTime))) {
13121da177e4SLinus Torvalds 			UDF_I_CRTIME(inode).tv_sec = convtime;
13131da177e4SLinus Torvalds 			UDF_I_CRTIME(inode).tv_nsec = convtime_usec * 1000;
1314*cb00ea35SCyrill Gorcunov 		} else {
13151da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb);
13161da177e4SLinus Torvalds 		}
13171da177e4SLinus Torvalds 
13181da177e4SLinus Torvalds 		if (udf_stamp_to_time(&convtime, &convtime_usec,
1319*cb00ea35SCyrill Gorcunov 				      lets_to_cpu(efe->attrTime))) {
13201da177e4SLinus Torvalds 			inode->i_ctime.tv_sec = convtime;
13211da177e4SLinus Torvalds 			inode->i_ctime.tv_nsec = convtime_usec * 1000;
1322*cb00ea35SCyrill Gorcunov 		} else {
13231da177e4SLinus Torvalds 			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
13241da177e4SLinus Torvalds 		}
13251da177e4SLinus Torvalds 
13261da177e4SLinus Torvalds 		UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);
13271da177e4SLinus Torvalds 		UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
13281da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
1329*cb00ea35SCyrill Gorcunov 		offset =
1330*cb00ea35SCyrill Gorcunov 		    sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
13311da177e4SLinus Torvalds 	}
13321da177e4SLinus Torvalds 
1333*cb00ea35SCyrill Gorcunov 	switch (fe->icbTag.fileType) {
13341da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_DIRECTORY:
13351da177e4SLinus Torvalds 		{
13361da177e4SLinus Torvalds 			inode->i_op = &udf_dir_inode_operations;
13371da177e4SLinus Torvalds 			inode->i_fop = &udf_dir_operations;
13381da177e4SLinus Torvalds 			inode->i_mode |= S_IFDIR;
1339d8c76e6fSDave Hansen 			inc_nlink(inode);
13401da177e4SLinus Torvalds 			break;
13411da177e4SLinus Torvalds 		}
13421da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_REALTIME:
13431da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_REGULAR:
13441da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_UNDEF:
13451da177e4SLinus Torvalds 		{
13461da177e4SLinus Torvalds 			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
13471da177e4SLinus Torvalds 				inode->i_data.a_ops = &udf_adinicb_aops;
13481da177e4SLinus Torvalds 			else
13491da177e4SLinus Torvalds 				inode->i_data.a_ops = &udf_aops;
13501da177e4SLinus Torvalds 			inode->i_op = &udf_file_inode_operations;
13511da177e4SLinus Torvalds 			inode->i_fop = &udf_file_operations;
13521da177e4SLinus Torvalds 			inode->i_mode |= S_IFREG;
13531da177e4SLinus Torvalds 			break;
13541da177e4SLinus Torvalds 		}
13551da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_BLOCK:
13561da177e4SLinus Torvalds 		{
13571da177e4SLinus Torvalds 			inode->i_mode |= S_IFBLK;
13581da177e4SLinus Torvalds 			break;
13591da177e4SLinus Torvalds 		}
13601da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_CHAR:
13611da177e4SLinus Torvalds 		{
13621da177e4SLinus Torvalds 			inode->i_mode |= S_IFCHR;
13631da177e4SLinus Torvalds 			break;
13641da177e4SLinus Torvalds 		}
13651da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_FIFO:
13661da177e4SLinus Torvalds 		{
13671da177e4SLinus Torvalds 			init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
13681da177e4SLinus Torvalds 			break;
13691da177e4SLinus Torvalds 		}
13701da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_SOCKET:
13711da177e4SLinus Torvalds 		{
13721da177e4SLinus Torvalds 			init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
13731da177e4SLinus Torvalds 			break;
13741da177e4SLinus Torvalds 		}
13751da177e4SLinus Torvalds 	case ICBTAG_FILE_TYPE_SYMLINK:
13761da177e4SLinus Torvalds 		{
13771da177e4SLinus Torvalds 			inode->i_data.a_ops = &udf_symlink_aops;
13781da177e4SLinus Torvalds 			inode->i_op = &page_symlink_inode_operations;
13791da177e4SLinus Torvalds 			inode->i_mode = S_IFLNK | S_IRWXUGO;
13801da177e4SLinus Torvalds 			break;
13811da177e4SLinus Torvalds 		}
13821da177e4SLinus Torvalds 	default:
13831da177e4SLinus Torvalds 		{
1384*cb00ea35SCyrill Gorcunov 			printk(KERN_ERR
1385*cb00ea35SCyrill Gorcunov 			       "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n",
13861da177e4SLinus Torvalds 			       inode->i_ino, fe->icbTag.fileType);
13871da177e4SLinus Torvalds 			make_bad_inode(inode);
13881da177e4SLinus Torvalds 			return;
13891da177e4SLinus Torvalds 		}
13901da177e4SLinus Torvalds 	}
1391*cb00ea35SCyrill Gorcunov 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
1392*cb00ea35SCyrill Gorcunov 		struct deviceSpec *dsea = (struct deviceSpec *)
13931da177e4SLinus Torvalds 		    udf_get_extendedattr(inode, 12, 1);
13941da177e4SLinus Torvalds 
1395*cb00ea35SCyrill Gorcunov 		if (dsea) {
1396*cb00ea35SCyrill Gorcunov 			init_special_inode(inode, inode->i_mode,
1397*cb00ea35SCyrill Gorcunov 					   MKDEV(le32_to_cpu
1398*cb00ea35SCyrill Gorcunov 						 (dsea->majorDeviceIdent),
1399*cb00ea35SCyrill Gorcunov 						 le32_to_cpu(dsea->
1400*cb00ea35SCyrill Gorcunov 							     minorDeviceIdent)));
14011da177e4SLinus Torvalds 			/* Developer ID ??? */
1402*cb00ea35SCyrill Gorcunov 		} else {
14031da177e4SLinus Torvalds 			make_bad_inode(inode);
14041da177e4SLinus Torvalds 		}
14051da177e4SLinus Torvalds 	}
14061da177e4SLinus Torvalds }
14071da177e4SLinus Torvalds 
1408647bd61aSCyrill Gorcunov static int udf_alloc_i_data(struct inode *inode, size_t size)
1409647bd61aSCyrill Gorcunov {
1410647bd61aSCyrill Gorcunov 	UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);
1411647bd61aSCyrill Gorcunov 
1412*cb00ea35SCyrill Gorcunov 	if (!UDF_I_DATA(inode)) {
1413*cb00ea35SCyrill Gorcunov 		printk(KERN_ERR
1414*cb00ea35SCyrill Gorcunov 		       "udf:udf_alloc_i_data (ino %ld) no free memory\n",
1415647bd61aSCyrill Gorcunov 		       inode->i_ino);
1416647bd61aSCyrill Gorcunov 		return -ENOMEM;
1417647bd61aSCyrill Gorcunov 	}
1418647bd61aSCyrill Gorcunov 
1419647bd61aSCyrill Gorcunov 	return 0;
1420647bd61aSCyrill Gorcunov }
1421647bd61aSCyrill Gorcunov 
1422*cb00ea35SCyrill Gorcunov static mode_t udf_convert_permissions(struct fileEntry *fe)
14231da177e4SLinus Torvalds {
14241da177e4SLinus Torvalds 	mode_t mode;
14251da177e4SLinus Torvalds 	uint32_t permissions;
14261da177e4SLinus Torvalds 	uint32_t flags;
14271da177e4SLinus Torvalds 
14281da177e4SLinus Torvalds 	permissions = le32_to_cpu(fe->permissions);
14291da177e4SLinus Torvalds 	flags = le16_to_cpu(fe->icbTag.flags);
14301da177e4SLinus Torvalds 
14311da177e4SLinus Torvalds 	mode = ((permissions) & S_IRWXO) |
14321da177e4SLinus Torvalds 	    ((permissions >> 2) & S_IRWXG) |
14331da177e4SLinus Torvalds 	    ((permissions >> 4) & S_IRWXU) |
14341da177e4SLinus Torvalds 	    ((flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) |
14351da177e4SLinus Torvalds 	    ((flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) |
14361da177e4SLinus Torvalds 	    ((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0);
14371da177e4SLinus Torvalds 
14381da177e4SLinus Torvalds 	return mode;
14391da177e4SLinus Torvalds }
14401da177e4SLinus Torvalds 
14411da177e4SLinus Torvalds /*
14421da177e4SLinus Torvalds  * udf_write_inode
14431da177e4SLinus Torvalds  *
14441da177e4SLinus Torvalds  * PURPOSE
14451da177e4SLinus Torvalds  *	Write out the specified inode.
14461da177e4SLinus Torvalds  *
14471da177e4SLinus Torvalds  * DESCRIPTION
14481da177e4SLinus Torvalds  *	This routine is called whenever an inode is synced.
14491da177e4SLinus Torvalds  *	Currently this routine is just a placeholder.
14501da177e4SLinus Torvalds  *
14511da177e4SLinus Torvalds  * HISTORY
14521da177e4SLinus Torvalds  *	July 1, 1997 - Andrew E. Mileski
14531da177e4SLinus Torvalds  *	Written, tested, and released.
14541da177e4SLinus Torvalds  */
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds int udf_write_inode(struct inode *inode, int sync)
14571da177e4SLinus Torvalds {
14581da177e4SLinus Torvalds 	int ret;
14591da177e4SLinus Torvalds 	lock_kernel();
14601da177e4SLinus Torvalds 	ret = udf_update_inode(inode, sync);
14611da177e4SLinus Torvalds 	unlock_kernel();
14621da177e4SLinus Torvalds 	return ret;
14631da177e4SLinus Torvalds }
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds int udf_sync_inode(struct inode *inode)
14661da177e4SLinus Torvalds {
14671da177e4SLinus Torvalds 	return udf_update_inode(inode, 1);
14681da177e4SLinus Torvalds }
14691da177e4SLinus Torvalds 
1470*cb00ea35SCyrill Gorcunov static int udf_update_inode(struct inode *inode, int do_sync)
14711da177e4SLinus Torvalds {
14721da177e4SLinus Torvalds 	struct buffer_head *bh = NULL;
14731da177e4SLinus Torvalds 	struct fileEntry *fe;
14741da177e4SLinus Torvalds 	struct extendedFileEntry *efe;
14751da177e4SLinus Torvalds 	uint32_t udfperms;
14761da177e4SLinus Torvalds 	uint16_t icbflags;
14771da177e4SLinus Torvalds 	uint16_t crclen;
14781da177e4SLinus Torvalds 	int i;
14791da177e4SLinus Torvalds 	kernel_timestamp cpu_time;
14801da177e4SLinus Torvalds 	int err = 0;
14811da177e4SLinus Torvalds 
14821da177e4SLinus Torvalds 	bh = udf_tread(inode->i_sb,
1483*cb00ea35SCyrill Gorcunov 		       udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode),
1484*cb00ea35SCyrill Gorcunov 					 0));
14851da177e4SLinus Torvalds 
1486*cb00ea35SCyrill Gorcunov 	if (!bh) {
14871da177e4SLinus Torvalds 		udf_debug("bread failure\n");
14881da177e4SLinus Torvalds 		return -EIO;
14891da177e4SLinus Torvalds 	}
14901da177e4SLinus Torvalds 
14911da177e4SLinus Torvalds 	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
14921da177e4SLinus Torvalds 
14931da177e4SLinus Torvalds 	fe = (struct fileEntry *)bh->b_data;
14941da177e4SLinus Torvalds 	efe = (struct extendedFileEntry *)bh->b_data;
14951da177e4SLinus Torvalds 
1496*cb00ea35SCyrill Gorcunov 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) {
14971da177e4SLinus Torvalds 		struct unallocSpaceEntry *use =
14981da177e4SLinus Torvalds 		    (struct unallocSpaceEntry *)bh->b_data;
14991da177e4SLinus Torvalds 
15001da177e4SLinus Torvalds 		use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
1501*cb00ea35SCyrill Gorcunov 		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
1502*cb00ea35SCyrill Gorcunov 		       UDF_I_DATA(inode),
1503*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize -
1504*cb00ea35SCyrill Gorcunov 		       sizeof(struct unallocSpaceEntry));
1505*cb00ea35SCyrill Gorcunov 		crclen =
1506*cb00ea35SCyrill Gorcunov 		    sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
15071da177e4SLinus Torvalds 		    sizeof(tag);
1508*cb00ea35SCyrill Gorcunov 		use->descTag.tagLocation =
1509*cb00ea35SCyrill Gorcunov 		    cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
15101da177e4SLinus Torvalds 		use->descTag.descCRCLength = cpu_to_le16(crclen);
1511*cb00ea35SCyrill Gorcunov 		use->descTag.descCRC =
1512*cb00ea35SCyrill Gorcunov 		    cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));
15131da177e4SLinus Torvalds 
15141da177e4SLinus Torvalds 		use->descTag.tagChecksum = 0;
15151da177e4SLinus Torvalds 		for (i = 0; i < 16; i++)
15161da177e4SLinus Torvalds 			if (i != 4)
1517*cb00ea35SCyrill Gorcunov 				use->descTag.tagChecksum +=
1518*cb00ea35SCyrill Gorcunov 				    ((uint8_t *) & (use->descTag))[i];
15191da177e4SLinus Torvalds 
15201da177e4SLinus Torvalds 		mark_buffer_dirty(bh);
15213bf25cb4SJan Kara 		brelse(bh);
15221da177e4SLinus Torvalds 		return err;
15231da177e4SLinus Torvalds 	}
15241da177e4SLinus Torvalds 
15254d6660ebSPhillip Susi 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
15264d6660ebSPhillip Susi 		fe->uid = cpu_to_le32(-1);
1527*cb00ea35SCyrill Gorcunov 	else
1528*cb00ea35SCyrill Gorcunov 		fe->uid = cpu_to_le32(inode->i_uid);
15291da177e4SLinus Torvalds 
15304d6660ebSPhillip Susi 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
15314d6660ebSPhillip Susi 		fe->gid = cpu_to_le32(-1);
1532*cb00ea35SCyrill Gorcunov 	else
1533*cb00ea35SCyrill Gorcunov 		fe->gid = cpu_to_le32(inode->i_gid);
15341da177e4SLinus Torvalds 
15351da177e4SLinus Torvalds 	udfperms = ((inode->i_mode & S_IRWXO)) |
1536*cb00ea35SCyrill Gorcunov 	    ((inode->i_mode & S_IRWXG) << 2) | ((inode->i_mode & S_IRWXU) << 4);
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 	udfperms |= (le32_to_cpu(fe->permissions) &
15391da177e4SLinus Torvalds 		     (FE_PERM_O_DELETE | FE_PERM_O_CHATTR |
15401da177e4SLinus Torvalds 		      FE_PERM_G_DELETE | FE_PERM_G_CHATTR |
15411da177e4SLinus Torvalds 		      FE_PERM_U_DELETE | FE_PERM_U_CHATTR));
15421da177e4SLinus Torvalds 	fe->permissions = cpu_to_le32(udfperms);
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds 	if (S_ISDIR(inode->i_mode))
15451da177e4SLinus Torvalds 		fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
15461da177e4SLinus Torvalds 	else
15471da177e4SLinus Torvalds 		fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 	fe->informationLength = cpu_to_le64(inode->i_size);
15501da177e4SLinus Torvalds 
1551*cb00ea35SCyrill Gorcunov 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
15521da177e4SLinus Torvalds 		regid *eid;
1553*cb00ea35SCyrill Gorcunov 		struct deviceSpec *dsea = (struct deviceSpec *)
15541da177e4SLinus Torvalds 		    udf_get_extendedattr(inode, 12, 1);
15551da177e4SLinus Torvalds 
1556*cb00ea35SCyrill Gorcunov 		if (!dsea) {
15571da177e4SLinus Torvalds 			dsea = (struct deviceSpec *)
15581da177e4SLinus Torvalds 			    udf_add_extendedattr(inode,
15591da177e4SLinus Torvalds 						 sizeof(struct deviceSpec) +
15601da177e4SLinus Torvalds 						 sizeof(regid), 12, 0x3);
15611da177e4SLinus Torvalds 			dsea->attrType = cpu_to_le32(12);
15621da177e4SLinus Torvalds 			dsea->attrSubtype = 1;
1563*cb00ea35SCyrill Gorcunov 			dsea->attrLength =
1564*cb00ea35SCyrill Gorcunov 			    cpu_to_le32(sizeof(struct deviceSpec) +
15651da177e4SLinus Torvalds 					sizeof(regid));
15661da177e4SLinus Torvalds 			dsea->impUseLength = cpu_to_le32(sizeof(regid));
15671da177e4SLinus Torvalds 		}
15681da177e4SLinus Torvalds 		eid = (regid *) dsea->impUse;
15691da177e4SLinus Torvalds 		memset(eid, 0, sizeof(regid));
15701da177e4SLinus Torvalds 		strcpy(eid->ident, UDF_ID_DEVELOPER);
15711da177e4SLinus Torvalds 		eid->identSuffix[0] = UDF_OS_CLASS_UNIX;
15721da177e4SLinus Torvalds 		eid->identSuffix[1] = UDF_OS_ID_LINUX;
15731da177e4SLinus Torvalds 		dsea->majorDeviceIdent = cpu_to_le32(imajor(inode));
15741da177e4SLinus Torvalds 		dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));
15751da177e4SLinus Torvalds 	}
15761da177e4SLinus Torvalds 
1577*cb00ea35SCyrill Gorcunov 	if (UDF_I_EFE(inode) == 0) {
1578*cb00ea35SCyrill Gorcunov 		memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode),
1579*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
1580*cb00ea35SCyrill Gorcunov 		fe->logicalBlocksRecorded =
1581*cb00ea35SCyrill Gorcunov 		    cpu_to_le64((inode->i_blocks +
1582*cb00ea35SCyrill Gorcunov 				 (1 << (inode->i_sb->s_blocksize_bits - 9)) -
1583*cb00ea35SCyrill Gorcunov 				 1) >> (inode->i_sb->s_blocksize_bits - 9));
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
15861da177e4SLinus Torvalds 			fe->accessTime = cpu_to_lets(cpu_time);
15871da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
15881da177e4SLinus Torvalds 			fe->modificationTime = cpu_to_lets(cpu_time);
15891da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
15901da177e4SLinus Torvalds 			fe->attrTime = cpu_to_lets(cpu_time);
15911da177e4SLinus Torvalds 		memset(&(fe->impIdent), 0, sizeof(regid));
15921da177e4SLinus Torvalds 		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
15931da177e4SLinus Torvalds 		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
15941da177e4SLinus Torvalds 		fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
15951da177e4SLinus Torvalds 		fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
15961da177e4SLinus Torvalds 		fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
15971da177e4SLinus Torvalds 		fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
15981da177e4SLinus Torvalds 		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
15991da177e4SLinus Torvalds 		crclen = sizeof(struct fileEntry);
1600*cb00ea35SCyrill Gorcunov 	} else {
1601*cb00ea35SCyrill Gorcunov 		memcpy(bh->b_data + sizeof(struct extendedFileEntry),
1602*cb00ea35SCyrill Gorcunov 		       UDF_I_DATA(inode),
1603*cb00ea35SCyrill Gorcunov 		       inode->i_sb->s_blocksize -
1604*cb00ea35SCyrill Gorcunov 		       sizeof(struct extendedFileEntry));
16051da177e4SLinus Torvalds 		efe->objectSize = cpu_to_le64(inode->i_size);
1606*cb00ea35SCyrill Gorcunov 		efe->logicalBlocksRecorded = cpu_to_le64((inode->i_blocks +
1607*cb00ea35SCyrill Gorcunov 							  (1 <<
1608*cb00ea35SCyrill Gorcunov 							   (inode->i_sb->
1609*cb00ea35SCyrill Gorcunov 							    s_blocksize_bits -
1610*cb00ea35SCyrill Gorcunov 							    9)) -
1611*cb00ea35SCyrill Gorcunov 							  1) >> (inode->i_sb->
1612*cb00ea35SCyrill Gorcunov 								 s_blocksize_bits
1613*cb00ea35SCyrill Gorcunov 								 - 9));
16141da177e4SLinus Torvalds 
16151da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_atime.tv_sec ||
16161da177e4SLinus Torvalds 		    (UDF_I_CRTIME(inode).tv_sec == inode->i_atime.tv_sec &&
1617*cb00ea35SCyrill Gorcunov 		     UDF_I_CRTIME(inode).tv_nsec > inode->i_atime.tv_nsec)) {
16181da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_atime;
16191da177e4SLinus Torvalds 		}
16201da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_mtime.tv_sec ||
16211da177e4SLinus Torvalds 		    (UDF_I_CRTIME(inode).tv_sec == inode->i_mtime.tv_sec &&
1622*cb00ea35SCyrill Gorcunov 		     UDF_I_CRTIME(inode).tv_nsec > inode->i_mtime.tv_nsec)) {
16231da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_mtime;
16241da177e4SLinus Torvalds 		}
16251da177e4SLinus Torvalds 		if (UDF_I_CRTIME(inode).tv_sec > inode->i_ctime.tv_sec ||
16261da177e4SLinus Torvalds 		    (UDF_I_CRTIME(inode).tv_sec == inode->i_ctime.tv_sec &&
1627*cb00ea35SCyrill Gorcunov 		     UDF_I_CRTIME(inode).tv_nsec > inode->i_ctime.tv_nsec)) {
16281da177e4SLinus Torvalds 			UDF_I_CRTIME(inode) = inode->i_ctime;
16291da177e4SLinus Torvalds 		}
16301da177e4SLinus Torvalds 
16311da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
16321da177e4SLinus Torvalds 			efe->accessTime = cpu_to_lets(cpu_time);
16331da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
16341da177e4SLinus Torvalds 			efe->modificationTime = cpu_to_lets(cpu_time);
16351da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode)))
16361da177e4SLinus Torvalds 			efe->createTime = cpu_to_lets(cpu_time);
16371da177e4SLinus Torvalds 		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
16381da177e4SLinus Torvalds 			efe->attrTime = cpu_to_lets(cpu_time);
16391da177e4SLinus Torvalds 
16401da177e4SLinus Torvalds 		memset(&(efe->impIdent), 0, sizeof(regid));
16411da177e4SLinus Torvalds 		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
16421da177e4SLinus Torvalds 		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
16431da177e4SLinus Torvalds 		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
16441da177e4SLinus Torvalds 		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
16451da177e4SLinus Torvalds 		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
16461da177e4SLinus Torvalds 		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
16471da177e4SLinus Torvalds 		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
16481da177e4SLinus Torvalds 		crclen = sizeof(struct extendedFileEntry);
16491da177e4SLinus Torvalds 	}
1650*cb00ea35SCyrill Gorcunov 	if (UDF_I_STRAT4096(inode)) {
16511da177e4SLinus Torvalds 		fe->icbTag.strategyType = cpu_to_le16(4096);
16521da177e4SLinus Torvalds 		fe->icbTag.strategyParameter = cpu_to_le16(1);
16531da177e4SLinus Torvalds 		fe->icbTag.numEntries = cpu_to_le16(2);
1654*cb00ea35SCyrill Gorcunov 	} else {
16551da177e4SLinus Torvalds 		fe->icbTag.strategyType = cpu_to_le16(4);
16561da177e4SLinus Torvalds 		fe->icbTag.numEntries = cpu_to_le16(1);
16571da177e4SLinus Torvalds 	}
16581da177e4SLinus Torvalds 
16591da177e4SLinus Torvalds 	if (S_ISDIR(inode->i_mode))
16601da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY;
16611da177e4SLinus Torvalds 	else if (S_ISREG(inode->i_mode))
16621da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;
16631da177e4SLinus Torvalds 	else if (S_ISLNK(inode->i_mode))
16641da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK;
16651da177e4SLinus Torvalds 	else if (S_ISBLK(inode->i_mode))
16661da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK;
16671da177e4SLinus Torvalds 	else if (S_ISCHR(inode->i_mode))
16681da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
16691da177e4SLinus Torvalds 	else if (S_ISFIFO(inode->i_mode))
16701da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;
16711da177e4SLinus Torvalds 	else if (S_ISSOCK(inode->i_mode))
16721da177e4SLinus Torvalds 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;
16731da177e4SLinus Torvalds 
16741da177e4SLinus Torvalds 	icbflags = UDF_I_ALLOCTYPE(inode) |
16751da177e4SLinus Torvalds 	    ((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |
16761da177e4SLinus Torvalds 	    ((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) |
16771da177e4SLinus Torvalds 	    ((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) |
16781da177e4SLinus Torvalds 	    (le16_to_cpu(fe->icbTag.flags) &
16791da177e4SLinus Torvalds 	     ~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID |
16801da177e4SLinus Torvalds 	       ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY));
16811da177e4SLinus Torvalds 
16821da177e4SLinus Torvalds 	fe->icbTag.flags = cpu_to_le16(icbflags);
16831da177e4SLinus Torvalds 	if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
16841da177e4SLinus Torvalds 		fe->descTag.descVersion = cpu_to_le16(3);
16851da177e4SLinus Torvalds 	else
16861da177e4SLinus Torvalds 		fe->descTag.descVersion = cpu_to_le16(2);
16871da177e4SLinus Torvalds 	fe->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
1688*cb00ea35SCyrill Gorcunov 	fe->descTag.tagLocation =
1689*cb00ea35SCyrill Gorcunov 	    cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
16901da177e4SLinus Torvalds 	crclen += UDF_I_LENEATTR(inode) + UDF_I_LENALLOC(inode) - sizeof(tag);
16911da177e4SLinus Torvalds 	fe->descTag.descCRCLength = cpu_to_le16(crclen);
1692*cb00ea35SCyrill Gorcunov 	fe->descTag.descCRC =
1693*cb00ea35SCyrill Gorcunov 	    cpu_to_le16(udf_crc((char *)fe + sizeof(tag), crclen, 0));
16941da177e4SLinus Torvalds 
16951da177e4SLinus Torvalds 	fe->descTag.tagChecksum = 0;
16961da177e4SLinus Torvalds 	for (i = 0; i < 16; i++)
16971da177e4SLinus Torvalds 		if (i != 4)
1698*cb00ea35SCyrill Gorcunov 			fe->descTag.tagChecksum +=
1699*cb00ea35SCyrill Gorcunov 			    ((uint8_t *) & (fe->descTag))[i];
17001da177e4SLinus Torvalds 
17011da177e4SLinus Torvalds 	/* write the data blocks */
17021da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
1703*cb00ea35SCyrill Gorcunov 	if (do_sync) {
17041da177e4SLinus Torvalds 		sync_dirty_buffer(bh);
1705*cb00ea35SCyrill Gorcunov 		if (buffer_req(bh) && !buffer_uptodate(bh)) {
17061da177e4SLinus Torvalds 			printk("IO error syncing udf inode [%s:%08lx]\n",
17071da177e4SLinus Torvalds 			       inode->i_sb->s_id, inode->i_ino);
17081da177e4SLinus Torvalds 			err = -EIO;
17091da177e4SLinus Torvalds 		}
17101da177e4SLinus Torvalds 	}
17113bf25cb4SJan Kara 	brelse(bh);
17121da177e4SLinus Torvalds 	return err;
17131da177e4SLinus Torvalds }
17141da177e4SLinus Torvalds 
1715*cb00ea35SCyrill Gorcunov struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino)
17161da177e4SLinus Torvalds {
17171da177e4SLinus Torvalds 	unsigned long block = udf_get_lb_pblock(sb, ino, 0);
17181da177e4SLinus Torvalds 	struct inode *inode = iget_locked(sb, block);
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds 	if (!inode)
17211da177e4SLinus Torvalds 		return NULL;
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds 	if (inode->i_state & I_NEW) {
17241da177e4SLinus Torvalds 		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));
17251da177e4SLinus Torvalds 		__udf_read_inode(inode);
17261da177e4SLinus Torvalds 		unlock_new_inode(inode);
17271da177e4SLinus Torvalds 	}
17281da177e4SLinus Torvalds 
17291da177e4SLinus Torvalds 	if (is_bad_inode(inode))
17301da177e4SLinus Torvalds 		goto out_iput;
17311da177e4SLinus Torvalds 
1732*cb00ea35SCyrill Gorcunov 	if (ino.logicalBlockNum >=
1733*cb00ea35SCyrill Gorcunov 	    UDF_SB_PARTLEN(sb, ino.partitionReferenceNum)) {
17341da177e4SLinus Torvalds 		udf_debug("block=%d, partition=%d out of range\n",
17351da177e4SLinus Torvalds 			  ino.logicalBlockNum, ino.partitionReferenceNum);
17361da177e4SLinus Torvalds 		make_bad_inode(inode);
17371da177e4SLinus Torvalds 		goto out_iput;
17381da177e4SLinus Torvalds 	}
17391da177e4SLinus Torvalds 
17401da177e4SLinus Torvalds 	return inode;
17411da177e4SLinus Torvalds 
17421da177e4SLinus Torvalds       out_iput:
17431da177e4SLinus Torvalds 	iput(inode);
17441da177e4SLinus Torvalds 	return NULL;
17451da177e4SLinus Torvalds }
17461da177e4SLinus Torvalds 
1747ff116fc8SJan Kara int8_t udf_add_aext(struct inode * inode, struct extent_position * epos,
1748ff116fc8SJan Kara 		    kernel_lb_addr eloc, uint32_t elen, int inc)
17491da177e4SLinus Torvalds {
17501da177e4SLinus Torvalds 	int adsize;
17511da177e4SLinus Torvalds 	short_ad *sad = NULL;
17521da177e4SLinus Torvalds 	long_ad *lad = NULL;
17531da177e4SLinus Torvalds 	struct allocExtDesc *aed;
17541da177e4SLinus Torvalds 	int8_t etype;
17551da177e4SLinus Torvalds 	uint8_t *ptr;
17561da177e4SLinus Torvalds 
1757ff116fc8SJan Kara 	if (!epos->bh)
1758*cb00ea35SCyrill Gorcunov 		ptr =
1759*cb00ea35SCyrill Gorcunov 		    UDF_I_DATA(inode) + epos->offset -
1760*cb00ea35SCyrill Gorcunov 		    udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
17611da177e4SLinus Torvalds 	else
1762ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
17651da177e4SLinus Torvalds 		adsize = sizeof(short_ad);
17661da177e4SLinus Torvalds 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
17671da177e4SLinus Torvalds 		adsize = sizeof(long_ad);
17681da177e4SLinus Torvalds 	else
17691da177e4SLinus Torvalds 		return -1;
17701da177e4SLinus Torvalds 
1771*cb00ea35SCyrill Gorcunov 	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
17721da177e4SLinus Torvalds 		char *sptr, *dptr;
17731da177e4SLinus Torvalds 		struct buffer_head *nbh;
17741da177e4SLinus Torvalds 		int err, loffset;
1775ff116fc8SJan Kara 		kernel_lb_addr obloc = epos->block;
17761da177e4SLinus Torvalds 
1777*cb00ea35SCyrill Gorcunov 		if (!
1778*cb00ea35SCyrill Gorcunov 		    (epos->block.logicalBlockNum =
1779*cb00ea35SCyrill Gorcunov 		     udf_new_block(inode->i_sb, NULL,
1780*cb00ea35SCyrill Gorcunov 				   obloc.partitionReferenceNum,
1781*cb00ea35SCyrill Gorcunov 				   obloc.logicalBlockNum, &err))) {
17821da177e4SLinus Torvalds 			return -1;
17831da177e4SLinus Torvalds 		}
1784*cb00ea35SCyrill Gorcunov 		if (!
1785*cb00ea35SCyrill Gorcunov 		    (nbh =
1786*cb00ea35SCyrill Gorcunov 		     udf_tgetblk(inode->i_sb,
1787*cb00ea35SCyrill Gorcunov 				 udf_get_lb_pblock(inode->i_sb, epos->block,
1788*cb00ea35SCyrill Gorcunov 						   0)))) {
17891da177e4SLinus Torvalds 			return -1;
17901da177e4SLinus Torvalds 		}
17911da177e4SLinus Torvalds 		lock_buffer(nbh);
17921da177e4SLinus Torvalds 		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
17931da177e4SLinus Torvalds 		set_buffer_uptodate(nbh);
17941da177e4SLinus Torvalds 		unlock_buffer(nbh);
17951da177e4SLinus Torvalds 		mark_buffer_dirty_inode(nbh, inode);
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds 		aed = (struct allocExtDesc *)(nbh->b_data);
17981da177e4SLinus Torvalds 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
1799*cb00ea35SCyrill Gorcunov 			aed->previousAllocExtLocation =
1800*cb00ea35SCyrill Gorcunov 			    cpu_to_le32(obloc.logicalBlockNum);
1801*cb00ea35SCyrill Gorcunov 		if (epos->offset + adsize > inode->i_sb->s_blocksize) {
1802ff116fc8SJan Kara 			loffset = epos->offset;
18031da177e4SLinus Torvalds 			aed->lengthAllocDescs = cpu_to_le32(adsize);
18041da177e4SLinus Torvalds 			sptr = ptr - adsize;
18051da177e4SLinus Torvalds 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
18061da177e4SLinus Torvalds 			memcpy(dptr, sptr, adsize);
1807ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc) + adsize;
1808*cb00ea35SCyrill Gorcunov 		} else {
1809ff116fc8SJan Kara 			loffset = epos->offset + adsize;
18101da177e4SLinus Torvalds 			aed->lengthAllocDescs = cpu_to_le32(0);
18111da177e4SLinus Torvalds 			sptr = ptr;
1812ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc);
18131da177e4SLinus Torvalds 
1814*cb00ea35SCyrill Gorcunov 			if (epos->bh) {
1815ff116fc8SJan Kara 				aed = (struct allocExtDesc *)epos->bh->b_data;
18161da177e4SLinus Torvalds 				aed->lengthAllocDescs =
1817*cb00ea35SCyrill Gorcunov 				    cpu_to_le32(le32_to_cpu
1818*cb00ea35SCyrill Gorcunov 						(aed->lengthAllocDescs) +
1819*cb00ea35SCyrill Gorcunov 						adsize);
1820*cb00ea35SCyrill Gorcunov 			} else {
18211da177e4SLinus Torvalds 				UDF_I_LENALLOC(inode) += adsize;
18221da177e4SLinus Torvalds 				mark_inode_dirty(inode);
18231da177e4SLinus Torvalds 			}
18241da177e4SLinus Torvalds 		}
18251da177e4SLinus Torvalds 		if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
18261da177e4SLinus Torvalds 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
1827ff116fc8SJan Kara 				    epos->block.logicalBlockNum, sizeof(tag));
18281da177e4SLinus Torvalds 		else
18291da177e4SLinus Torvalds 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
1830ff116fc8SJan Kara 				    epos->block.logicalBlockNum, sizeof(tag));
1831*cb00ea35SCyrill Gorcunov 		switch (UDF_I_ALLOCTYPE(inode)) {
18321da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_SHORT:
18331da177e4SLinus Torvalds 			{
18341da177e4SLinus Torvalds 				sad = (short_ad *) sptr;
1835*cb00ea35SCyrill Gorcunov 				sad->extLength =
1836*cb00ea35SCyrill Gorcunov 				    cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
18371da177e4SLinus Torvalds 						inode->i_sb->s_blocksize);
1838*cb00ea35SCyrill Gorcunov 				sad->extPosition =
1839*cb00ea35SCyrill Gorcunov 				    cpu_to_le32(epos->block.logicalBlockNum);
18401da177e4SLinus Torvalds 				break;
18411da177e4SLinus Torvalds 			}
18421da177e4SLinus Torvalds 		case ICBTAG_FLAG_AD_LONG:
18431da177e4SLinus Torvalds 			{
18441da177e4SLinus Torvalds 				lad = (long_ad *) sptr;
1845*cb00ea35SCyrill Gorcunov 				lad->extLength =
1846*cb00ea35SCyrill Gorcunov 				    cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
18471da177e4SLinus Torvalds 						inode->i_sb->s_blocksize);
1848ff116fc8SJan Kara 				lad->extLocation = cpu_to_lelb(epos->block);
18491da177e4SLinus Torvalds 				memset(lad->impUse, 0x00, sizeof(lad->impUse));
18501da177e4SLinus Torvalds 				break;
18511da177e4SLinus Torvalds 			}
18521da177e4SLinus Torvalds 		}
1853*cb00ea35SCyrill Gorcunov 		if (epos->bh) {
1854*cb00ea35SCyrill Gorcunov 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
1855*cb00ea35SCyrill Gorcunov 			    || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1856ff116fc8SJan Kara 				udf_update_tag(epos->bh->b_data, loffset);
18571da177e4SLinus Torvalds 			else
1858*cb00ea35SCyrill Gorcunov 				udf_update_tag(epos->bh->b_data,
1859*cb00ea35SCyrill Gorcunov 					       sizeof(struct allocExtDesc));
1860ff116fc8SJan Kara 			mark_buffer_dirty_inode(epos->bh, inode);
18613bf25cb4SJan Kara 			brelse(epos->bh);
1862*cb00ea35SCyrill Gorcunov 		} else
18631da177e4SLinus Torvalds 			mark_inode_dirty(inode);
1864ff116fc8SJan Kara 		epos->bh = nbh;
18651da177e4SLinus Torvalds 	}
18661da177e4SLinus Torvalds 
1867ff116fc8SJan Kara 	etype = udf_write_aext(inode, epos, eloc, elen, inc);
18681da177e4SLinus Torvalds 
1869*cb00ea35SCyrill Gorcunov 	if (!epos->bh) {
18701da177e4SLinus Torvalds 		UDF_I_LENALLOC(inode) += adsize;
18711da177e4SLinus Torvalds 		mark_inode_dirty(inode);
1872*cb00ea35SCyrill Gorcunov 	} else {
1873ff116fc8SJan Kara 		aed = (struct allocExtDesc *)epos->bh->b_data;
18741da177e4SLinus Torvalds 		aed->lengthAllocDescs =
18751da177e4SLinus Torvalds 		    cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
1876*cb00ea35SCyrill Gorcunov 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
1877*cb00ea35SCyrill Gorcunov 		    || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
1878*cb00ea35SCyrill Gorcunov 			udf_update_tag(epos->bh->b_data,
1879*cb00ea35SCyrill Gorcunov 				       epos->offset + (inc ? 0 : adsize));
18801da177e4SLinus Torvalds 		else
1881*cb00ea35SCyrill Gorcunov 			udf_update_tag(epos->bh->b_data,
1882*cb00ea35SCyrill Gorcunov 				       sizeof(struct allocExtDesc));
1883ff116fc8SJan Kara 		mark_buffer_dirty_inode(epos->bh, inode);
18841da177e4SLinus Torvalds 	}
18851da177e4SLinus Torvalds 
18861da177e4SLinus Torvalds 	return etype;
18871da177e4SLinus Torvalds }
18881da177e4SLinus Torvalds 
1889ff116fc8SJan Kara int8_t udf_write_aext(struct inode * inode, struct extent_position * epos,
1890ff116fc8SJan Kara 		      kernel_lb_addr eloc, uint32_t elen, int inc)
18911da177e4SLinus Torvalds {
18921da177e4SLinus Torvalds 	int adsize;
18931da177e4SLinus Torvalds 	uint8_t *ptr;
18941da177e4SLinus Torvalds 
1895ff116fc8SJan Kara 	if (!epos->bh)
1896*cb00ea35SCyrill Gorcunov 		ptr =
1897*cb00ea35SCyrill Gorcunov 		    UDF_I_DATA(inode) + epos->offset -
1898*cb00ea35SCyrill Gorcunov 		    udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
18991da177e4SLinus Torvalds 	else
1900ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
19011da177e4SLinus Torvalds 
1902*cb00ea35SCyrill Gorcunov 	switch (UDF_I_ALLOCTYPE(inode)) {
19031da177e4SLinus Torvalds 	case ICBTAG_FLAG_AD_SHORT:
19041da177e4SLinus Torvalds 		{
19051da177e4SLinus Torvalds 			short_ad *sad = (short_ad *) ptr;
19061da177e4SLinus Torvalds 			sad->extLength = cpu_to_le32(elen);
19071da177e4SLinus Torvalds 			sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
19081da177e4SLinus Torvalds 			adsize = sizeof(short_ad);
19091da177e4SLinus Torvalds 			break;
19101da177e4SLinus Torvalds 		}
19111da177e4SLinus Torvalds 	case ICBTAG_FLAG_AD_LONG:
19121da177e4SLinus Torvalds 		{
19131da177e4SLinus Torvalds 			long_ad *lad = (long_ad *) ptr;
19141da177e4SLinus Torvalds 			lad->extLength = cpu_to_le32(elen);
19151da177e4SLinus Torvalds 			lad->extLocation = cpu_to_lelb(eloc);
19161da177e4SLinus Torvalds 			memset(lad->impUse, 0x00, sizeof(lad->impUse));
19171da177e4SLinus Torvalds 			adsize = sizeof(long_ad);
19181da177e4SLinus Torvalds 			break;
19191da177e4SLinus Torvalds 		}
19201da177e4SLinus Torvalds 	default:
19211da177e4SLinus Torvalds 		return -1;
19221da177e4SLinus Torvalds 	}
19231da177e4SLinus Torvalds 
1924*cb00ea35SCyrill Gorcunov 	if (epos->bh) {
1925*cb00ea35SCyrill Gorcunov 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
1926*cb00ea35SCyrill Gorcunov 		    || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) {
1927*cb00ea35SCyrill Gorcunov 			struct allocExtDesc *aed =
1928*cb00ea35SCyrill Gorcunov 			    (struct allocExtDesc *)epos->bh->b_data;
1929ff116fc8SJan Kara 			udf_update_tag(epos->bh->b_data,
1930*cb00ea35SCyrill Gorcunov 				       le32_to_cpu(aed->lengthAllocDescs) +
1931*cb00ea35SCyrill Gorcunov 				       sizeof(struct allocExtDesc));
19321da177e4SLinus Torvalds 		}
1933ff116fc8SJan Kara 		mark_buffer_dirty_inode(epos->bh, inode);
1934*cb00ea35SCyrill Gorcunov 	} else
19351da177e4SLinus Torvalds 		mark_inode_dirty(inode);
19361da177e4SLinus Torvalds 
19371da177e4SLinus Torvalds 	if (inc)
1938ff116fc8SJan Kara 		epos->offset += adsize;
19391da177e4SLinus Torvalds 	return (elen >> 30);
19401da177e4SLinus Torvalds }
19411da177e4SLinus Torvalds 
1942ff116fc8SJan Kara int8_t udf_next_aext(struct inode * inode, struct extent_position * epos,
1943ff116fc8SJan Kara 		     kernel_lb_addr * eloc, uint32_t * elen, int inc)
19441da177e4SLinus Torvalds {
19451da177e4SLinus Torvalds 	int8_t etype;
19461da177e4SLinus Torvalds 
1947ff116fc8SJan Kara 	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
1948*cb00ea35SCyrill Gorcunov 	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
1949ff116fc8SJan Kara 		epos->block = *eloc;
1950ff116fc8SJan Kara 		epos->offset = sizeof(struct allocExtDesc);
19513bf25cb4SJan Kara 		brelse(epos->bh);
1952*cb00ea35SCyrill Gorcunov 		if (!
1953*cb00ea35SCyrill Gorcunov 		    (epos->bh =
1954*cb00ea35SCyrill Gorcunov 		     udf_tread(inode->i_sb,
1955*cb00ea35SCyrill Gorcunov 			       udf_get_lb_pblock(inode->i_sb, epos->block,
1956*cb00ea35SCyrill Gorcunov 						 0)))) {
19571da177e4SLinus Torvalds 			udf_debug("reading block %d failed!\n",
1958*cb00ea35SCyrill Gorcunov 				  udf_get_lb_pblock(inode->i_sb, epos->block,
1959*cb00ea35SCyrill Gorcunov 						    0));
19601da177e4SLinus Torvalds 			return -1;
19611da177e4SLinus Torvalds 		}
19621da177e4SLinus Torvalds 	}
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds 	return etype;
19651da177e4SLinus Torvalds }
19661da177e4SLinus Torvalds 
1967ff116fc8SJan Kara int8_t udf_current_aext(struct inode * inode, struct extent_position * epos,
1968ff116fc8SJan Kara 			kernel_lb_addr * eloc, uint32_t * elen, int inc)
19691da177e4SLinus Torvalds {
19701da177e4SLinus Torvalds 	int alen;
19711da177e4SLinus Torvalds 	int8_t etype;
19721da177e4SLinus Torvalds 	uint8_t *ptr;
19731da177e4SLinus Torvalds 
1974*cb00ea35SCyrill Gorcunov 	if (!epos->bh) {
1975ff116fc8SJan Kara 		if (!epos->offset)
1976ff116fc8SJan Kara 			epos->offset = udf_file_entry_alloc_offset(inode);
1977*cb00ea35SCyrill Gorcunov 		ptr =
1978*cb00ea35SCyrill Gorcunov 		    UDF_I_DATA(inode) + epos->offset -
1979*cb00ea35SCyrill Gorcunov 		    udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
1980*cb00ea35SCyrill Gorcunov 		alen =
1981*cb00ea35SCyrill Gorcunov 		    udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
1982*cb00ea35SCyrill Gorcunov 	} else {
1983ff116fc8SJan Kara 		if (!epos->offset)
1984ff116fc8SJan Kara 			epos->offset = sizeof(struct allocExtDesc);
1985ff116fc8SJan Kara 		ptr = epos->bh->b_data + epos->offset;
1986*cb00ea35SCyrill Gorcunov 		alen =
1987*cb00ea35SCyrill Gorcunov 		    sizeof(struct allocExtDesc) +
1988*cb00ea35SCyrill Gorcunov 		    le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->
1989*cb00ea35SCyrill Gorcunov 				lengthAllocDescs);
19901da177e4SLinus Torvalds 	}
19911da177e4SLinus Torvalds 
1992*cb00ea35SCyrill Gorcunov 	switch (UDF_I_ALLOCTYPE(inode)) {
19931da177e4SLinus Torvalds 	case ICBTAG_FLAG_AD_SHORT:
19941da177e4SLinus Torvalds 		{
19951da177e4SLinus Torvalds 			short_ad *sad;
19961da177e4SLinus Torvalds 
1997*cb00ea35SCyrill Gorcunov 			if (!
1998*cb00ea35SCyrill Gorcunov 			    (sad =
1999*cb00ea35SCyrill Gorcunov 			     udf_get_fileshortad(ptr, alen, &epos->offset,
2000*cb00ea35SCyrill Gorcunov 						 inc)))
20011da177e4SLinus Torvalds 				return -1;
20021da177e4SLinus Torvalds 
20031da177e4SLinus Torvalds 			etype = le32_to_cpu(sad->extLength) >> 30;
20041da177e4SLinus Torvalds 			eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
2005*cb00ea35SCyrill Gorcunov 			eloc->partitionReferenceNum =
2006*cb00ea35SCyrill Gorcunov 			    UDF_I_LOCATION(inode).partitionReferenceNum;
2007*cb00ea35SCyrill Gorcunov 			*elen =
2008*cb00ea35SCyrill Gorcunov 			    le32_to_cpu(sad->
2009*cb00ea35SCyrill Gorcunov 					extLength) & UDF_EXTENT_LENGTH_MASK;
20101da177e4SLinus Torvalds 			break;
20111da177e4SLinus Torvalds 		}
20121da177e4SLinus Torvalds 	case ICBTAG_FLAG_AD_LONG:
20131da177e4SLinus Torvalds 		{
20141da177e4SLinus Torvalds 			long_ad *lad;
20151da177e4SLinus Torvalds 
2016*cb00ea35SCyrill Gorcunov 			if (!
2017*cb00ea35SCyrill Gorcunov 			    (lad =
2018*cb00ea35SCyrill Gorcunov 			     udf_get_filelongad(ptr, alen, &epos->offset, inc)))
20191da177e4SLinus Torvalds 				return -1;
20201da177e4SLinus Torvalds 
20211da177e4SLinus Torvalds 			etype = le32_to_cpu(lad->extLength) >> 30;
20221da177e4SLinus Torvalds 			*eloc = lelb_to_cpu(lad->extLocation);
2023*cb00ea35SCyrill Gorcunov 			*elen =
2024*cb00ea35SCyrill Gorcunov 			    le32_to_cpu(lad->
2025*cb00ea35SCyrill Gorcunov 					extLength) & UDF_EXTENT_LENGTH_MASK;
20261da177e4SLinus Torvalds 			break;
20271da177e4SLinus Torvalds 		}
20281da177e4SLinus Torvalds 	default:
20291da177e4SLinus Torvalds 		{
2030*cb00ea35SCyrill Gorcunov 			udf_debug("alloc_type = %d unsupported\n",
2031*cb00ea35SCyrill Gorcunov 				  UDF_I_ALLOCTYPE(inode));
20321da177e4SLinus Torvalds 			return -1;
20331da177e4SLinus Torvalds 		}
20341da177e4SLinus Torvalds 	}
20351da177e4SLinus Torvalds 
20361da177e4SLinus Torvalds 	return etype;
20371da177e4SLinus Torvalds }
20381da177e4SLinus Torvalds 
20391da177e4SLinus Torvalds static int8_t
2040ff116fc8SJan Kara udf_insert_aext(struct inode *inode, struct extent_position epos,
2041ff116fc8SJan Kara 		kernel_lb_addr neloc, uint32_t nelen)
20421da177e4SLinus Torvalds {
20431da177e4SLinus Torvalds 	kernel_lb_addr oeloc;
20441da177e4SLinus Torvalds 	uint32_t oelen;
20451da177e4SLinus Torvalds 	int8_t etype;
20461da177e4SLinus Torvalds 
2047ff116fc8SJan Kara 	if (epos.bh)
20483bf25cb4SJan Kara 		get_bh(epos.bh);
20491da177e4SLinus Torvalds 
2050*cb00ea35SCyrill Gorcunov 	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {
2051ff116fc8SJan Kara 		udf_write_aext(inode, &epos, neloc, nelen, 1);
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds 		neloc = oeloc;
20541da177e4SLinus Torvalds 		nelen = (etype << 30) | oelen;
20551da177e4SLinus Torvalds 	}
2056ff116fc8SJan Kara 	udf_add_aext(inode, &epos, neloc, nelen, 1);
20573bf25cb4SJan Kara 	brelse(epos.bh);
20581da177e4SLinus Torvalds 	return (nelen >> 30);
20591da177e4SLinus Torvalds }
20601da177e4SLinus Torvalds 
2061ff116fc8SJan Kara int8_t udf_delete_aext(struct inode * inode, struct extent_position epos,
2062ff116fc8SJan Kara 		       kernel_lb_addr eloc, uint32_t elen)
20631da177e4SLinus Torvalds {
2064ff116fc8SJan Kara 	struct extent_position oepos;
2065ff116fc8SJan Kara 	int adsize;
20661da177e4SLinus Torvalds 	int8_t etype;
20671da177e4SLinus Torvalds 	struct allocExtDesc *aed;
20681da177e4SLinus Torvalds 
2069*cb00ea35SCyrill Gorcunov 	if (epos.bh) {
20703bf25cb4SJan Kara 		get_bh(epos.bh);
20713bf25cb4SJan Kara 		get_bh(epos.bh);
20721da177e4SLinus Torvalds 	}
20731da177e4SLinus Torvalds 
20741da177e4SLinus Torvalds 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
20751da177e4SLinus Torvalds 		adsize = sizeof(short_ad);
20761da177e4SLinus Torvalds 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
20771da177e4SLinus Torvalds 		adsize = sizeof(long_ad);
20781da177e4SLinus Torvalds 	else
20791da177e4SLinus Torvalds 		adsize = 0;
20801da177e4SLinus Torvalds 
2081ff116fc8SJan Kara 	oepos = epos;
2082ff116fc8SJan Kara 	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
20831da177e4SLinus Torvalds 		return -1;
20841da177e4SLinus Torvalds 
2085*cb00ea35SCyrill Gorcunov 	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
2086ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);
2087*cb00ea35SCyrill Gorcunov 		if (oepos.bh != epos.bh) {
2088ff116fc8SJan Kara 			oepos.block = epos.block;
20893bf25cb4SJan Kara 			brelse(oepos.bh);
20903bf25cb4SJan Kara 			get_bh(epos.bh);
2091ff116fc8SJan Kara 			oepos.bh = epos.bh;
2092ff116fc8SJan Kara 			oepos.offset = epos.offset - adsize;
20931da177e4SLinus Torvalds 		}
20941da177e4SLinus Torvalds 	}
20951da177e4SLinus Torvalds 	memset(&eloc, 0x00, sizeof(kernel_lb_addr));
20961da177e4SLinus Torvalds 	elen = 0;
20971da177e4SLinus Torvalds 
2098*cb00ea35SCyrill Gorcunov 	if (epos.bh != oepos.bh) {
2099ff116fc8SJan Kara 		udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);
2100ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
2101ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
2102*cb00ea35SCyrill Gorcunov 		if (!oepos.bh) {
21031da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) -= (adsize * 2);
21041da177e4SLinus Torvalds 			mark_inode_dirty(inode);
2105*cb00ea35SCyrill Gorcunov 		} else {
2106ff116fc8SJan Kara 			aed = (struct allocExtDesc *)oepos.bh->b_data;
21071da177e4SLinus Torvalds 			aed->lengthAllocDescs =
2108*cb00ea35SCyrill Gorcunov 			    cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
2109*cb00ea35SCyrill Gorcunov 					(2 * adsize));
2110*cb00ea35SCyrill Gorcunov 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
2111*cb00ea35SCyrill Gorcunov 			    || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
2112*cb00ea35SCyrill Gorcunov 				udf_update_tag(oepos.bh->b_data,
2113*cb00ea35SCyrill Gorcunov 					       oepos.offset - (2 * adsize));
21141da177e4SLinus Torvalds 			else
2115*cb00ea35SCyrill Gorcunov 				udf_update_tag(oepos.bh->b_data,
2116*cb00ea35SCyrill Gorcunov 					       sizeof(struct allocExtDesc));
2117ff116fc8SJan Kara 			mark_buffer_dirty_inode(oepos.bh, inode);
21181da177e4SLinus Torvalds 		}
2119*cb00ea35SCyrill Gorcunov 	} else {
2120ff116fc8SJan Kara 		udf_write_aext(inode, &oepos, eloc, elen, 1);
2121*cb00ea35SCyrill Gorcunov 		if (!oepos.bh) {
21221da177e4SLinus Torvalds 			UDF_I_LENALLOC(inode) -= adsize;
21231da177e4SLinus Torvalds 			mark_inode_dirty(inode);
2124*cb00ea35SCyrill Gorcunov 		} else {
2125ff116fc8SJan Kara 			aed = (struct allocExtDesc *)oepos.bh->b_data;
21261da177e4SLinus Torvalds 			aed->lengthAllocDescs =
2127*cb00ea35SCyrill Gorcunov 			    cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
2128*cb00ea35SCyrill Gorcunov 					adsize);
2129*cb00ea35SCyrill Gorcunov 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
2130*cb00ea35SCyrill Gorcunov 			    || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
2131*cb00ea35SCyrill Gorcunov 				udf_update_tag(oepos.bh->b_data,
2132*cb00ea35SCyrill Gorcunov 					       epos.offset - adsize);
21331da177e4SLinus Torvalds 			else
2134*cb00ea35SCyrill Gorcunov 				udf_update_tag(oepos.bh->b_data,
2135*cb00ea35SCyrill Gorcunov 					       sizeof(struct allocExtDesc));
2136ff116fc8SJan Kara 			mark_buffer_dirty_inode(oepos.bh, inode);
21371da177e4SLinus Torvalds 		}
21381da177e4SLinus Torvalds 	}
21391da177e4SLinus Torvalds 
21403bf25cb4SJan Kara 	brelse(epos.bh);
21413bf25cb4SJan Kara 	brelse(oepos.bh);
21421da177e4SLinus Torvalds 	return (elen >> 30);
21431da177e4SLinus Torvalds }
21441da177e4SLinus Torvalds 
2145*cb00ea35SCyrill Gorcunov int8_t inode_bmap(struct inode * inode, sector_t block,
2146*cb00ea35SCyrill Gorcunov 		  struct extent_position * pos, kernel_lb_addr * eloc,
2147*cb00ea35SCyrill Gorcunov 		  uint32_t * elen, sector_t * offset)
21481da177e4SLinus Torvalds {
2149*cb00ea35SCyrill Gorcunov 	loff_t lbcount = 0, bcount =
2150*cb00ea35SCyrill Gorcunov 	    (loff_t) block << inode->i_sb->s_blocksize_bits;
21511da177e4SLinus Torvalds 	int8_t etype;
21521da177e4SLinus Torvalds 
2153*cb00ea35SCyrill Gorcunov 	if (block < 0) {
21541da177e4SLinus Torvalds 		printk(KERN_ERR "udf: inode_bmap: block < 0\n");
21551da177e4SLinus Torvalds 		return -1;
21561da177e4SLinus Torvalds 	}
21571da177e4SLinus Torvalds 
2158ff116fc8SJan Kara 	pos->offset = 0;
2159ff116fc8SJan Kara 	pos->block = UDF_I_LOCATION(inode);
2160ff116fc8SJan Kara 	pos->bh = NULL;
21611da177e4SLinus Torvalds 	*elen = 0;
21621da177e4SLinus Torvalds 
2163*cb00ea35SCyrill Gorcunov 	do {
2164*cb00ea35SCyrill Gorcunov 		if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1) {
2165*cb00ea35SCyrill Gorcunov 			*offset =
2166*cb00ea35SCyrill Gorcunov 			    (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
21671da177e4SLinus Torvalds 			UDF_I_LENEXTENTS(inode) = lbcount;
21681da177e4SLinus Torvalds 			return -1;
21691da177e4SLinus Torvalds 		}
21701da177e4SLinus Torvalds 		lbcount += *elen;
21711da177e4SLinus Torvalds 	} while (lbcount <= bcount);
21721da177e4SLinus Torvalds 
217360448b1dSJan Kara 	*offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits;
21741da177e4SLinus Torvalds 
21751da177e4SLinus Torvalds 	return etype;
21761da177e4SLinus Torvalds }
21771da177e4SLinus Torvalds 
217860448b1dSJan Kara long udf_block_map(struct inode *inode, sector_t block)
21791da177e4SLinus Torvalds {
2180ff116fc8SJan Kara 	kernel_lb_addr eloc;
2181ff116fc8SJan Kara 	uint32_t elen;
218260448b1dSJan Kara 	sector_t offset;
2183ff116fc8SJan Kara 	struct extent_position epos = { NULL, 0, {0, 0} };
21841da177e4SLinus Torvalds 	int ret;
21851da177e4SLinus Torvalds 
21861da177e4SLinus Torvalds 	lock_kernel();
21871da177e4SLinus Torvalds 
2188*cb00ea35SCyrill Gorcunov 	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==
2189*cb00ea35SCyrill Gorcunov 	    (EXT_RECORDED_ALLOCATED >> 30))
219060448b1dSJan Kara 		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
21911da177e4SLinus Torvalds 	else
21921da177e4SLinus Torvalds 		ret = 0;
21931da177e4SLinus Torvalds 
21941da177e4SLinus Torvalds 	unlock_kernel();
21953bf25cb4SJan Kara 	brelse(epos.bh);
21961da177e4SLinus Torvalds 
21971da177e4SLinus Torvalds 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
21981da177e4SLinus Torvalds 		return udf_fixed_to_variable(ret);
21991da177e4SLinus Torvalds 	else
22001da177e4SLinus Torvalds 		return ret;
22011da177e4SLinus Torvalds }
2202