diff options
-rw-r--r-- | fs/stat.c | 1 | ||||
-rw-r--r-- | fs/ufs/balloc.c | 26 | ||||
-rw-r--r-- | fs/ufs/inode.c | 28 | ||||
-rw-r--r-- | fs/ufs/super.c | 18 | ||||
-rw-r--r-- | fs/ufs/util.h | 10 |
5 files changed, 63 insertions, 20 deletions
@@ -672,6 +672,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes) | |||
672 | inode->i_bytes -= 512; | 672 | inode->i_bytes -= 512; |
673 | } | 673 | } |
674 | } | 674 | } |
675 | EXPORT_SYMBOL(__inode_add_bytes); | ||
675 | 676 | ||
676 | void inode_add_bytes(struct inode *inode, loff_t bytes) | 677 | void inode_add_bytes(struct inode *inode, loff_t bytes) |
677 | { | 678 | { |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index a0376a2c1c29..d642cc0a8271 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | |||
82 | ufs_error (sb, "ufs_free_fragments", | 82 | ufs_error (sb, "ufs_free_fragments", |
83 | "bit already cleared for fragment %u", i); | 83 | "bit already cleared for fragment %u", i); |
84 | } | 84 | } |
85 | 85 | ||
86 | inode_sub_bytes(inode, count << uspi->s_fshift); | ||
86 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); | 87 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); |
87 | uspi->cs_total.cs_nffree += count; | 88 | uspi->cs_total.cs_nffree += count; |
88 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); | 89 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); |
@@ -184,6 +185,7 @@ do_more: | |||
184 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); | 185 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); |
185 | } | 186 | } |
186 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 187 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
188 | inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); | ||
187 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 189 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
188 | ufs_clusteracct (sb, ucpi, blkno, 1); | 190 | ufs_clusteracct (sb, ucpi, blkno, 1); |
189 | 191 | ||
@@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
494 | return 0; | 496 | return 0; |
495 | } | 497 | } |
496 | 498 | ||
499 | static bool try_add_frags(struct inode *inode, unsigned frags) | ||
500 | { | ||
501 | unsigned size = frags * i_blocksize(inode); | ||
502 | spin_lock(&inode->i_lock); | ||
503 | __inode_add_bytes(inode, size); | ||
504 | if (unlikely((u32)inode->i_blocks != inode->i_blocks)) { | ||
505 | __inode_sub_bytes(inode, size); | ||
506 | spin_unlock(&inode->i_lock); | ||
507 | return false; | ||
508 | } | ||
509 | spin_unlock(&inode->i_lock); | ||
510 | return true; | ||
511 | } | ||
512 | |||
497 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | 513 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, |
498 | unsigned oldcount, unsigned newcount) | 514 | unsigned oldcount, unsigned newcount) |
499 | { | 515 | { |
@@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | |||
530 | for (i = oldcount; i < newcount; i++) | 546 | for (i = oldcount; i < newcount; i++) |
531 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) | 547 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) |
532 | return 0; | 548 | return 0; |
549 | |||
550 | if (!try_add_frags(inode, count)) | ||
551 | return 0; | ||
533 | /* | 552 | /* |
534 | * Block can be extended | 553 | * Block can be extended |
535 | */ | 554 | */ |
@@ -647,6 +666,7 @@ cg_found: | |||
647 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); | 666 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); |
648 | i = uspi->s_fpb - count; | 667 | i = uspi->s_fpb - count; |
649 | 668 | ||
669 | inode_sub_bytes(inode, i << uspi->s_fshift); | ||
650 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); | 670 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); |
651 | uspi->cs_total.cs_nffree += i; | 671 | uspi->cs_total.cs_nffree += i; |
652 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); | 672 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); |
@@ -657,6 +677,8 @@ cg_found: | |||
657 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); | 677 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); |
658 | if (result == INVBLOCK) | 678 | if (result == INVBLOCK) |
659 | return 0; | 679 | return 0; |
680 | if (!try_add_frags(inode, count)) | ||
681 | return 0; | ||
660 | for (i = 0; i < count; i++) | 682 | for (i = 0; i < count; i++) |
661 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); | 683 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); |
662 | 684 | ||
@@ -716,6 +738,8 @@ norot: | |||
716 | return INVBLOCK; | 738 | return INVBLOCK; |
717 | ucpi->c_rotor = result; | 739 | ucpi->c_rotor = result; |
718 | gotit: | 740 | gotit: |
741 | if (!try_add_frags(inode, uspi->s_fpb)) | ||
742 | return 0; | ||
719 | blkno = ufs_fragstoblks(result); | 743 | blkno = ufs_fragstoblks(result); |
720 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 744 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
721 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 745 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 7e41aee7b69a..da553ffec85b 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to, | |||
235 | 235 | ||
236 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); | 236 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); |
237 | tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), | 237 | tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), |
238 | new_size, err, locked_page); | 238 | new_size - (lastfrag & uspi->s_fpbmask), err, |
239 | locked_page); | ||
239 | return tmp != 0; | 240 | return tmp != 0; |
240 | } | 241 | } |
241 | 242 | ||
@@ -284,7 +285,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, | |||
284 | goal += uspi->s_fpb; | 285 | goal += uspi->s_fpb; |
285 | } | 286 | } |
286 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), | 287 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), |
287 | goal, uspi->s_fpb, err, locked_page); | 288 | goal, nfrags, err, locked_page); |
288 | 289 | ||
289 | if (!tmp) { | 290 | if (!tmp) { |
290 | *err = -ENOSPC; | 291 | *err = -ENOSPC; |
@@ -402,7 +403,9 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff | |||
402 | 403 | ||
403 | if (!create) { | 404 | if (!create) { |
404 | phys64 = ufs_frag_map(inode, offsets, depth); | 405 | phys64 = ufs_frag_map(inode, offsets, depth); |
405 | goto out; | 406 | if (phys64) |
407 | map_bh(bh_result, sb, phys64 + frag); | ||
408 | return 0; | ||
406 | } | 409 | } |
407 | 410 | ||
408 | /* This code entered only while writing ....? */ | 411 | /* This code entered only while writing ....? */ |
@@ -841,8 +844,11 @@ void ufs_evict_inode(struct inode * inode) | |||
841 | truncate_inode_pages_final(&inode->i_data); | 844 | truncate_inode_pages_final(&inode->i_data); |
842 | if (want_delete) { | 845 | if (want_delete) { |
843 | inode->i_size = 0; | 846 | inode->i_size = 0; |
844 | if (inode->i_blocks) | 847 | if (inode->i_blocks && |
848 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
849 | S_ISLNK(inode->i_mode))) | ||
845 | ufs_truncate_blocks(inode); | 850 | ufs_truncate_blocks(inode); |
851 | ufs_update_inode(inode, inode_needs_sync(inode)); | ||
846 | } | 852 | } |
847 | 853 | ||
848 | invalidate_inode_buffers(inode); | 854 | invalidate_inode_buffers(inode); |
@@ -1100,7 +1106,7 @@ out: | |||
1100 | return err; | 1106 | return err; |
1101 | } | 1107 | } |
1102 | 1108 | ||
1103 | static void __ufs_truncate_blocks(struct inode *inode) | 1109 | static void ufs_truncate_blocks(struct inode *inode) |
1104 | { | 1110 | { |
1105 | struct ufs_inode_info *ufsi = UFS_I(inode); | 1111 | struct ufs_inode_info *ufsi = UFS_I(inode); |
1106 | struct super_block *sb = inode->i_sb; | 1112 | struct super_block *sb = inode->i_sb; |
@@ -1183,7 +1189,7 @@ static int ufs_truncate(struct inode *inode, loff_t size) | |||
1183 | 1189 | ||
1184 | truncate_setsize(inode, size); | 1190 | truncate_setsize(inode, size); |
1185 | 1191 | ||
1186 | __ufs_truncate_blocks(inode); | 1192 | ufs_truncate_blocks(inode); |
1187 | inode->i_mtime = inode->i_ctime = current_time(inode); | 1193 | inode->i_mtime = inode->i_ctime = current_time(inode); |
1188 | mark_inode_dirty(inode); | 1194 | mark_inode_dirty(inode); |
1189 | out: | 1195 | out: |
@@ -1191,16 +1197,6 @@ out: | |||
1191 | return err; | 1197 | return err; |
1192 | } | 1198 | } |
1193 | 1199 | ||
1194 | static void ufs_truncate_blocks(struct inode *inode) | ||
1195 | { | ||
1196 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
1197 | S_ISLNK(inode->i_mode))) | ||
1198 | return; | ||
1199 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
1200 | return; | ||
1201 | __ufs_truncate_blocks(inode); | ||
1202 | } | ||
1203 | |||
1204 | int ufs_setattr(struct dentry *dentry, struct iattr *attr) | 1200 | int ufs_setattr(struct dentry *dentry, struct iattr *attr) |
1205 | { | 1201 | { |
1206 | struct inode *inode = d_inode(dentry); | 1202 | struct inode *inode = d_inode(dentry); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 29ecaf739449..878cc6264f1a 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb) | |||
746 | return; | 746 | return; |
747 | } | 747 | } |
748 | 748 | ||
749 | static u64 ufs_max_bytes(struct super_block *sb) | ||
750 | { | ||
751 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
752 | int bits = uspi->s_apbshift; | ||
753 | u64 res; | ||
754 | |||
755 | if (bits > 21) | ||
756 | res = ~0ULL; | ||
757 | else | ||
758 | res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + | ||
759 | (1LL << (3*bits)); | ||
760 | |||
761 | if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) | ||
762 | return MAX_LFS_FILESIZE; | ||
763 | return res << uspi->s_bshift; | ||
764 | } | ||
765 | |||
749 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) | 766 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) |
750 | { | 767 | { |
751 | struct ufs_sb_info * sbi; | 768 | struct ufs_sb_info * sbi; |
@@ -1211,6 +1228,7 @@ magic_found: | |||
1211 | "fast symlink size (%u)\n", uspi->s_maxsymlinklen); | 1228 | "fast symlink size (%u)\n", uspi->s_maxsymlinklen); |
1212 | uspi->s_maxsymlinklen = maxsymlen; | 1229 | uspi->s_maxsymlinklen = maxsymlen; |
1213 | } | 1230 | } |
1231 | sb->s_maxbytes = ufs_max_bytes(sb); | ||
1214 | sb->s_max_links = UFS_LINK_MAX; | 1232 | sb->s_max_links = UFS_LINK_MAX; |
1215 | 1233 | ||
1216 | inode = ufs_iget(sb, UFS_ROOTINO); | 1234 | inode = ufs_iget(sb, UFS_ROOTINO); |
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index b7fbf53dbc81..398019fb1448 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_( | |||
473 | static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, | 473 | static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, |
474 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) | 474 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) |
475 | { | 475 | { |
476 | u8 mask; | ||
476 | switch (uspi->s_fpb) { | 477 | switch (uspi->s_fpb) { |
477 | case 8: | 478 | case 8: |
478 | return (*ubh_get_addr (ubh, begin + block) == 0xff); | 479 | return (*ubh_get_addr (ubh, begin + block) == 0xff); |
479 | case 4: | 480 | case 4: |
480 | return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); | 481 | mask = 0x0f << ((block & 0x01) << 2); |
482 | return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; | ||
481 | case 2: | 483 | case 2: |
482 | return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); | 484 | mask = 0x03 << ((block & 0x03) << 1); |
485 | return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; | ||
483 | case 1: | 486 | case 1: |
484 | return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); | 487 | mask = 0x01 << (block & 0x07); |
488 | return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; | ||
485 | } | 489 | } |
486 | return 0; | 490 | return 0; |
487 | } | 491 | } |