aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2015-12-23 08:21:13 -0500
committerJan Kara <jack@suse.cz>2015-12-23 12:04:52 -0500
commitfcea62babc8100aee79c716c81203c6d105b2da0 (patch)
tree326aded5e99730a5f12b403339b36534f06fc28e /fs/udf
parentb0918d9f476a8434b055e362b83fa4fd1d462c3f (diff)
udf: Factor out code for creating indirect extent
Factor out code for creating indirect extent from udf_add_aext(). It was mostly duplicated in two places. Also remove some opencoded versions of udf_write_aext(). Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/balloc.c98
-rw-r--r--fs/udf/inode.c217
-rw-r--r--fs/udf/udfdecl.h4
3 files changed, 130 insertions, 189 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 6d6a96b4e73f..e0fd65fe73e8 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -447,9 +447,6 @@ static void udf_table_free_blocks(struct super_block *sb,
447 */ 447 */
448 448
449 int adsize; 449 int adsize;
450 struct short_ad *sad = NULL;
451 struct long_ad *lad = NULL;
452 struct allocExtDesc *aed;
453 450
454 eloc.logicalBlockNum = start; 451 eloc.logicalBlockNum = start;
455 elen = EXT_RECORDED_ALLOCATED | 452 elen = EXT_RECORDED_ALLOCATED |
@@ -466,102 +463,17 @@ static void udf_table_free_blocks(struct super_block *sb,
466 } 463 }
467 464
468 if (epos.offset + (2 * adsize) > sb->s_blocksize) { 465 if (epos.offset + (2 * adsize) > sb->s_blocksize) {
469 unsigned char *sptr, *dptr;
470 int loffset;
471
472 brelse(oepos.bh);
473 oepos = epos;
474
475 /* Steal a block from the extent being free'd */ 466 /* Steal a block from the extent being free'd */
476 epos.block.logicalBlockNum = eloc.logicalBlockNum; 467 udf_setup_indirect_aext(table, eloc.logicalBlockNum,
468 &epos);
469
477 eloc.logicalBlockNum++; 470 eloc.logicalBlockNum++;
478 elen -= sb->s_blocksize; 471 elen -= sb->s_blocksize;
479
480 epos.bh = udf_tread(sb,
481 udf_get_lb_pblock(sb, &epos.block, 0));
482 if (!epos.bh) {
483 brelse(oepos.bh);
484 goto error_return;
485 }
486 aed = (struct allocExtDesc *)(epos.bh->b_data);
487 aed->previousAllocExtLocation =
488 cpu_to_le32(oepos.block.logicalBlockNum);
489 if (epos.offset + adsize > sb->s_blocksize) {
490 loffset = epos.offset;
491 aed->lengthAllocDescs = cpu_to_le32(adsize);
492 sptr = iinfo->i_ext.i_data + epos.offset
493 - adsize;
494 dptr = epos.bh->b_data +
495 sizeof(struct allocExtDesc);
496 memcpy(dptr, sptr, adsize);
497 epos.offset = sizeof(struct allocExtDesc) +
498 adsize;
499 } else {
500 loffset = epos.offset + adsize;
501 aed->lengthAllocDescs = cpu_to_le32(0);
502 if (oepos.bh) {
503 sptr = oepos.bh->b_data + epos.offset;
504 aed = (struct allocExtDesc *)
505 oepos.bh->b_data;
506 le32_add_cpu(&aed->lengthAllocDescs,
507 adsize);
508 } else {
509 sptr = iinfo->i_ext.i_data +
510 epos.offset;
511 iinfo->i_lenAlloc += adsize;
512 mark_inode_dirty(table);
513 }
514 epos.offset = sizeof(struct allocExtDesc);
515 }
516 if (sbi->s_udfrev >= 0x0200)
517 udf_new_tag(epos.bh->b_data, TAG_IDENT_AED,
518 3, 1, epos.block.logicalBlockNum,
519 sizeof(struct tag));
520 else
521 udf_new_tag(epos.bh->b_data, TAG_IDENT_AED,
522 2, 1, epos.block.logicalBlockNum,
523 sizeof(struct tag));
524
525 switch (iinfo->i_alloc_type) {
526 case ICBTAG_FLAG_AD_SHORT:
527 sad = (struct short_ad *)sptr;
528 sad->extLength = cpu_to_le32(
529 EXT_NEXT_EXTENT_ALLOCDECS |
530 sb->s_blocksize);
531 sad->extPosition =
532 cpu_to_le32(epos.block.logicalBlockNum);
533 break;
534 case ICBTAG_FLAG_AD_LONG:
535 lad = (struct long_ad *)sptr;
536 lad->extLength = cpu_to_le32(
537 EXT_NEXT_EXTENT_ALLOCDECS |
538 sb->s_blocksize);
539 lad->extLocation =
540 cpu_to_lelb(epos.block);
541 break;
542 }
543 if (oepos.bh) {
544 udf_update_tag(oepos.bh->b_data, loffset);
545 mark_buffer_dirty(oepos.bh);
546 } else {
547 mark_inode_dirty(table);
548 }
549 } 472 }
550 473
551 /* It's possible that stealing the block emptied the extent */ 474 /* It's possible that stealing the block emptied the extent */
552 if (elen) { 475 if (elen)
553 udf_write_aext(table, &epos, &eloc, elen, 1); 476 __udf_add_aext(table, &epos, &eloc, elen, 1);
554
555 if (!epos.bh) {
556 iinfo->i_lenAlloc += adsize;
557 mark_inode_dirty(table);
558 } else {
559 aed = (struct allocExtDesc *)epos.bh->b_data;
560 le32_add_cpu(&aed->lengthAllocDescs, adsize);
561 udf_update_tag(epos.bh->b_data, epos.offset);
562 mark_buffer_dirty(epos.bh);
563 }
564 }
565 } 477 }
566 478
567 brelse(epos.bh); 479 brelse(epos.bh);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 566df9b5a6cb..34c2d2b79594 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1866,112 +1866,102 @@ struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
1866 return inode; 1866 return inode;
1867} 1867}
1868 1868
1869int udf_add_aext(struct inode *inode, struct extent_position *epos, 1869int udf_setup_indirect_aext(struct inode *inode, int block,
1870 struct kernel_lb_addr *eloc, uint32_t elen, int inc) 1870 struct extent_position *epos)
1871{ 1871{
1872 int adsize; 1872 struct super_block *sb = inode->i_sb;
1873 struct short_ad *sad = NULL; 1873 struct buffer_head *bh;
1874 struct long_ad *lad = NULL;
1875 struct allocExtDesc *aed; 1874 struct allocExtDesc *aed;
1876 uint8_t *ptr; 1875 struct extent_position nepos;
1877 struct udf_inode_info *iinfo = UDF_I(inode); 1876 struct kernel_lb_addr neloc;
1877 int ver, adsize;
1878 1878
1879 if (!epos->bh) 1879 if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
1880 ptr = iinfo->i_ext.i_data + epos->offset - 1880 adsize = sizeof(struct short_ad);
1881 udf_file_entry_alloc_offset(inode) + 1881 else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
1882 iinfo->i_lenEAttr; 1882 adsize = sizeof(struct long_ad);
1883
1884 neloc.logicalBlockNum = block;
1885 neloc.partitionReferenceNum = epos->block.partitionReferenceNum;
1886
1887 bh = udf_tgetblk(sb, udf_get_lb_pblock(sb, &neloc, 0));
1888 if (!bh)
1889 return -EIO;
1890 lock_buffer(bh);
1891 memset(bh->b_data, 0x00, sb->s_blocksize);
1892 set_buffer_uptodate(bh);
1893 unlock_buffer(bh);
1894 mark_buffer_dirty_inode(bh, inode);
1895
1896 aed = (struct allocExtDesc *)(bh->b_data);
1897 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) {
1898 aed->previousAllocExtLocation =
1899 cpu_to_le32(epos->block.logicalBlockNum);
1900 }
1901 aed->lengthAllocDescs = cpu_to_le32(0);
1902 if (UDF_SB(sb)->s_udfrev >= 0x0200)
1903 ver = 3;
1883 else 1904 else
1884 ptr = epos->bh->b_data + epos->offset; 1905 ver = 2;
1906 udf_new_tag(bh->b_data, TAG_IDENT_AED, ver, 1, block,
1907 sizeof(struct tag));
1908
1909 nepos.block = neloc;
1910 nepos.offset = sizeof(struct allocExtDesc);
1911 nepos.bh = bh;
1912
1913 /*
1914 * Do we have to copy current last extent to make space for indirect
1915 * one?
1916 */
1917 if (epos->offset + adsize > sb->s_blocksize) {
1918 struct kernel_lb_addr cp_loc;
1919 uint32_t cp_len;
1920 int cp_type;
1921
1922 epos->offset -= adsize;
1923 cp_type = udf_current_aext(inode, epos, &cp_loc, &cp_len, 0);
1924 cp_len |= ((uint32_t)cp_type) << 30;
1925
1926 __udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1);
1927 udf_write_aext(inode, epos, &nepos.block,
1928 sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0);
1929 } else {
1930 __udf_add_aext(inode, epos, &nepos.block,
1931 sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0);
1932 }
1933
1934 brelse(epos->bh);
1935 *epos = nepos;
1936
1937 return 0;
1938}
1939
1940/*
1941 * Append extent at the given position - should be the first free one in inode
1942 * / indirect extent. This function assumes there is enough space in the inode
1943 * or indirect extent. Use udf_add_aext() if you didn't check for this before.
1944 */
1945int __udf_add_aext(struct inode *inode, struct extent_position *epos,
1946 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
1947{
1948 struct udf_inode_info *iinfo = UDF_I(inode);
1949 struct allocExtDesc *aed;
1950 int adsize;
1885 1951
1886 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 1952 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
1887 adsize = sizeof(struct short_ad); 1953 adsize = sizeof(struct short_ad);
1888 else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) 1954 else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
1889 adsize = sizeof(struct long_ad); 1955 adsize = sizeof(struct long_ad);
1890 else
1891 return -EIO;
1892
1893 if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
1894 unsigned char *sptr, *dptr;
1895 struct buffer_head *nbh;
1896 int err, loffset;
1897 struct kernel_lb_addr obloc = epos->block;
1898 1956
1899 epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, 1957 if (!epos->bh) {
1900 obloc.partitionReferenceNum, 1958 WARN_ON(iinfo->i_lenAlloc !=
1901 obloc.logicalBlockNum, &err); 1959 epos->offset - udf_file_entry_alloc_offset(inode));
1902 if (!epos->block.logicalBlockNum) 1960 } else {
1903 return -ENOSPC; 1961 aed = (struct allocExtDesc *)epos->bh->b_data;
1904 nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, 1962 WARN_ON(le32_to_cpu(aed->lengthAllocDescs) !=
1905 &epos->block, 1963 epos->offset - sizeof(struct allocExtDesc));
1906 0)); 1964 WARN_ON(epos->offset + adsize > inode->i_sb->s_blocksize);
1907 if (!nbh)
1908 return -EIO;
1909 lock_buffer(nbh);
1910 memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
1911 set_buffer_uptodate(nbh);
1912 unlock_buffer(nbh);
1913 mark_buffer_dirty_inode(nbh, inode);
1914
1915 aed = (struct allocExtDesc *)(nbh->b_data);
1916 if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
1917 aed->previousAllocExtLocation =
1918 cpu_to_le32(obloc.logicalBlockNum);
1919 if (epos->offset + adsize > inode->i_sb->s_blocksize) {
1920 loffset = epos->offset;
1921 aed->lengthAllocDescs = cpu_to_le32(adsize);
1922 sptr = ptr - adsize;
1923 dptr = nbh->b_data + sizeof(struct allocExtDesc);
1924 memcpy(dptr, sptr, adsize);
1925 epos->offset = sizeof(struct allocExtDesc) + adsize;
1926 } else {
1927 loffset = epos->offset + adsize;
1928 aed->lengthAllocDescs = cpu_to_le32(0);
1929 sptr = ptr;
1930 epos->offset = sizeof(struct allocExtDesc);
1931
1932 if (epos->bh) {
1933 aed = (struct allocExtDesc *)epos->bh->b_data;
1934 le32_add_cpu(&aed->lengthAllocDescs, adsize);
1935 } else {
1936 iinfo->i_lenAlloc += adsize;
1937 mark_inode_dirty(inode);
1938 }
1939 }
1940 if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200)
1941 udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
1942 epos->block.logicalBlockNum, sizeof(struct tag));
1943 else
1944 udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
1945 epos->block.logicalBlockNum, sizeof(struct tag));
1946 switch (iinfo->i_alloc_type) {
1947 case ICBTAG_FLAG_AD_SHORT:
1948 sad = (struct short_ad *)sptr;
1949 sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
1950 inode->i_sb->s_blocksize);
1951 sad->extPosition =
1952 cpu_to_le32(epos->block.logicalBlockNum);
1953 break;
1954 case ICBTAG_FLAG_AD_LONG:
1955 lad = (struct long_ad *)sptr;
1956 lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS |
1957 inode->i_sb->s_blocksize);
1958 lad->extLocation = cpu_to_lelb(epos->block);
1959 memset(lad->impUse, 0x00, sizeof(lad->impUse));
1960 break;
1961 }
1962 if (epos->bh) {
1963 if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
1964 UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
1965 udf_update_tag(epos->bh->b_data, loffset);
1966 else
1967 udf_update_tag(epos->bh->b_data,
1968 sizeof(struct allocExtDesc));
1969 mark_buffer_dirty_inode(epos->bh, inode);
1970 brelse(epos->bh);
1971 } else {
1972 mark_inode_dirty(inode);
1973 }
1974 epos->bh = nbh;
1975 } 1965 }
1976 1966
1977 udf_write_aext(inode, epos, eloc, elen, inc); 1967 udf_write_aext(inode, epos, eloc, elen, inc);
@@ -1995,6 +1985,41 @@ int udf_add_aext(struct inode *inode, struct extent_position *epos,
1995 return 0; 1985 return 0;
1996} 1986}
1997 1987
1988/*
1989 * Append extent at given position - should be the first free one in inode
1990 * / indirect extent. Takes care of allocating and linking indirect blocks.
1991 */
1992int udf_add_aext(struct inode *inode, struct extent_position *epos,
1993 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
1994{
1995 int adsize;
1996 struct super_block *sb = inode->i_sb;
1997
1998 if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
1999 adsize = sizeof(struct short_ad);
2000 else if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_LONG)
2001 adsize = sizeof(struct long_ad);
2002 else
2003 return -EIO;
2004
2005 if (epos->offset + (2 * adsize) > sb->s_blocksize) {
2006 int err;
2007 int new_block;
2008
2009 new_block = udf_new_block(sb, NULL,
2010 epos->block.partitionReferenceNum,
2011 epos->block.logicalBlockNum, &err);
2012 if (!new_block)
2013 return -ENOSPC;
2014
2015 err = udf_setup_indirect_aext(inode, new_block, epos);
2016 if (err)
2017 return err;
2018 }
2019
2020 return __udf_add_aext(inode, epos, eloc, elen, inc);
2021}
2022
1998void udf_write_aext(struct inode *inode, struct extent_position *epos, 2023void udf_write_aext(struct inode *inode, struct extent_position *epos,
1999 struct kernel_lb_addr *eloc, uint32_t elen, int inc) 2024 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
2000{ 2025{
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 47bb3f5ca360..269ad3fb2fab 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -159,6 +159,10 @@ extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
159extern long udf_block_map(struct inode *, sector_t); 159extern long udf_block_map(struct inode *, sector_t);
160extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, 160extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *,
161 struct kernel_lb_addr *, uint32_t *, sector_t *); 161 struct kernel_lb_addr *, uint32_t *, sector_t *);
162extern int udf_setup_indirect_aext(struct inode *inode, int block,
163 struct extent_position *epos);
164extern int __udf_add_aext(struct inode *inode, struct extent_position *epos,
165 struct kernel_lb_addr *eloc, uint32_t elen, int inc);
162extern int udf_add_aext(struct inode *, struct extent_position *, 166extern int udf_add_aext(struct inode *, struct extent_position *,
163 struct kernel_lb_addr *, uint32_t, int); 167 struct kernel_lb_addr *, uint32_t, int);
164extern void udf_write_aext(struct inode *, struct extent_position *, 168extern void udf_write_aext(struct inode *, struct extent_position *,