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