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