Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ufs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ufs fixes from Al Viro:
"Fix assorted ufs bugs: a couple of deadlocks, fs corruption in
truncate(), oopsen on tail unpacking and truncate when racing with
vmscan, mild fs corruption (free blocks stats summary buggered, *BSD
fsck would complain and fix), several instances of broken logics
around reserved blocks (starting with "check almost never triggers
when it should" and then there are issues with sufficiently large
UFS2)"

[ Note: ufs hasn't gotten any loving in a long time, because nobody
really seems to use it. These ufs fixes are triggered by people
actually caring now, not some sudden influx of new bugs. - Linus ]

* 'ufs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
ufs_truncate_blocks(): fix the case when size is in the last direct block
ufs: more deadlock prevention on tail unpacking
ufs: avoid grabbing ->truncate_mutex if possible
ufs_get_locked_page(): make sure we have buffer_heads
ufs: fix s_size/s_dsize users
ufs: fix reserved blocks check
ufs: make ufs_freespace() return signed
ufs: fix logics in "ufs: make fsck -f happy"

+98 -68
+13 -9
fs/ufs/balloc.c
··· 400 400 /* 401 401 * There is not enough space for user on the device 402 402 */ 403 - if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { 404 - mutex_unlock(&UFS_SB(sb)->s_lock); 405 - UFSD("EXIT (FAILED)\n"); 406 - return 0; 403 + if (unlikely(ufs_freefrags(uspi) <= uspi->s_root_blocks)) { 404 + if (!capable(CAP_SYS_RESOURCE)) { 405 + mutex_unlock(&UFS_SB(sb)->s_lock); 406 + UFSD("EXIT (FAILED)\n"); 407 + return 0; 408 + } 407 409 } 408 410 409 411 if (goal >= uspi->s_size) ··· 423 421 if (result) { 424 422 ufs_clear_frags(inode, result + oldcount, 425 423 newcount - oldcount, locked_page != NULL); 424 + *err = 0; 426 425 write_seqlock(&UFS_I(inode)->meta_lock); 427 426 ufs_cpu_to_data_ptr(sb, p, result); 428 - write_sequnlock(&UFS_I(inode)->meta_lock); 429 - *err = 0; 430 427 UFS_I(inode)->i_lastfrag = 431 428 max(UFS_I(inode)->i_lastfrag, fragment + count); 429 + write_sequnlock(&UFS_I(inode)->meta_lock); 432 430 } 433 431 mutex_unlock(&UFS_SB(sb)->s_lock); 434 432 UFSD("EXIT, result %llu\n", (unsigned long long)result); ··· 441 439 result = ufs_add_fragments(inode, tmp, oldcount, newcount); 442 440 if (result) { 443 441 *err = 0; 442 + read_seqlock_excl(&UFS_I(inode)->meta_lock); 444 443 UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, 445 444 fragment + count); 445 + read_sequnlock_excl(&UFS_I(inode)->meta_lock); 446 446 ufs_clear_frags(inode, result + oldcount, newcount - oldcount, 447 447 locked_page != NULL); 448 448 mutex_unlock(&UFS_SB(sb)->s_lock); ··· 478 474 if (result) { 479 475 ufs_clear_frags(inode, result + oldcount, newcount - oldcount, 480 476 locked_page != NULL); 477 + mutex_unlock(&UFS_SB(sb)->s_lock); 481 478 ufs_change_blocknr(inode, fragment - oldcount, oldcount, 482 479 uspi->s_sbbase + tmp, 483 480 uspi->s_sbbase + result, locked_page); 481 + *err = 0; 484 482 write_seqlock(&UFS_I(inode)->meta_lock); 485 483 ufs_cpu_to_data_ptr(sb, p, result); 486 - write_sequnlock(&UFS_I(inode)->meta_lock); 487 - *err = 0; 488 484 UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, 489 485 fragment + count); 490 - mutex_unlock(&UFS_SB(sb)->s_lock); 486 + write_sequnlock(&UFS_I(inode)->meta_lock); 491 487 if (newcount < request) 492 488 ufs_free_fragments (inode, result + newcount, request - newcount); 493 489 ufs_free_fragments (inode, tmp, oldcount);
+32 -15
fs/ufs/inode.c
··· 401 401 u64 phys64 = 0; 402 402 unsigned frag = fragment & uspi->s_fpbmask; 403 403 404 - if (!create) { 405 - phys64 = ufs_frag_map(inode, offsets, depth); 406 - if (phys64) 407 - map_bh(bh_result, sb, phys64 + frag); 408 - return 0; 409 - } 404 + phys64 = ufs_frag_map(inode, offsets, depth); 405 + if (!create) 406 + goto done; 410 407 408 + if (phys64) { 409 + if (fragment >= UFS_NDIR_FRAGMENT) 410 + goto done; 411 + read_seqlock_excl(&UFS_I(inode)->meta_lock); 412 + if (fragment < UFS_I(inode)->i_lastfrag) { 413 + read_sequnlock_excl(&UFS_I(inode)->meta_lock); 414 + goto done; 415 + } 416 + read_sequnlock_excl(&UFS_I(inode)->meta_lock); 417 + } 411 418 /* This code entered only while writing ....? */ 412 419 413 420 mutex_lock(&UFS_I(inode)->truncate_mutex); ··· 458 451 } 459 452 mutex_unlock(&UFS_I(inode)->truncate_mutex); 460 453 return err; 454 + 455 + done: 456 + if (phys64) 457 + map_bh(bh_result, sb, phys64 + frag); 458 + return 0; 461 459 } 462 460 463 461 static int ufs_writepage(struct page *page, struct writeback_control *wbc) ··· 886 874 ctx->to = from + count; 887 875 } 888 876 889 - #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) 890 877 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) 891 878 892 879 static void ufs_trunc_direct(struct inode *inode) ··· 1123 1112 struct super_block *sb = inode->i_sb; 1124 1113 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 1125 1114 unsigned offsets[4]; 1126 - int depth = ufs_block_to_path(inode, DIRECT_BLOCK, offsets); 1115 + int depth; 1127 1116 int depth2; 1128 1117 unsigned i; 1129 1118 struct ufs_buffer_head *ubh[3]; 1130 1119 void *p; 1131 1120 u64 block; 1132 1121 1133 - if (!depth) 1134 - return; 1122 + if (inode->i_size) { 1123 + sector_t last = (inode->i_size - 1) >> uspi->s_bshift; 1124 + depth = ufs_block_to_path(inode, last, offsets); 1125 + if (!depth) 1126 + return; 1127 + } else { 1128 + depth = 1; 1129 + } 1135 1130 1136 - /* find the last non-zero in offsets[] */ 1137 1131 for (depth2 = depth - 1; depth2; depth2--) 1138 - if (offsets[depth2]) 1132 + if (offsets[depth2] != uspi->s_apb - 1) 1139 1133 break; 1140 1134 1141 1135 mutex_lock(&ufsi->truncate_mutex); ··· 1149 1133 offsets[0] = UFS_IND_BLOCK; 1150 1134 } else { 1151 1135 /* get the blocks that should be partially emptied */ 1152 - p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]); 1136 + p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]++); 1153 1137 for (i = 0; i < depth2; i++) { 1154 - offsets[i]++; /* next branch is fully freed */ 1155 1138 block = ufs_data_ptr_to_cpu(sb, p); 1156 1139 if (!block) 1157 1140 break; ··· 1161 1146 write_sequnlock(&ufsi->meta_lock); 1162 1147 break; 1163 1148 } 1164 - p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]); 1149 + p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]++); 1165 1150 } 1166 1151 while (i--) 1167 1152 free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1); ··· 1176 1161 free_full_branch(inode, block, i - UFS_IND_BLOCK + 1); 1177 1162 } 1178 1163 } 1164 + read_seqlock_excl(&ufsi->meta_lock); 1179 1165 ufsi->i_lastfrag = DIRECT_FRAGMENT; 1166 + read_sequnlock_excl(&ufsi->meta_lock); 1180 1167 mark_inode_dirty(inode); 1181 1168 mutex_unlock(&ufsi->truncate_mutex); 1182 1169 }
+40 -24
fs/ufs/super.c
··· 480 480 usb3 = ubh_get_usb_third(uspi); 481 481 482 482 if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && 483 - (usb1->fs_flags & UFS_FLAGS_UPDATED)) || 483 + (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) || 484 484 mtype == UFS_MOUNT_UFSTYPE_UFS2) { 485 485 /*we have statistic in different place, then usual*/ 486 486 uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); ··· 596 596 usb2 = ubh_get_usb_second(uspi); 597 597 usb3 = ubh_get_usb_third(uspi); 598 598 599 - if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && 600 - (usb1->fs_flags & UFS_FLAGS_UPDATED)) || 601 - mtype == UFS_MOUNT_UFSTYPE_UFS2) { 599 + if (mtype == UFS_MOUNT_UFSTYPE_UFS2) { 602 600 /*we have statistic in different place, then usual*/ 603 601 usb2->fs_un.fs_u2.cs_ndir = 604 602 cpu_to_fs64(sb, uspi->cs_total.cs_ndir); ··· 606 608 cpu_to_fs64(sb, uspi->cs_total.cs_nifree); 607 609 usb3->fs_un1.fs_u2.cs_nffree = 608 610 cpu_to_fs64(sb, uspi->cs_total.cs_nffree); 609 - } else { 610 - usb1->fs_cstotal.cs_ndir = 611 - cpu_to_fs32(sb, uspi->cs_total.cs_ndir); 612 - usb1->fs_cstotal.cs_nbfree = 613 - cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); 614 - usb1->fs_cstotal.cs_nifree = 615 - cpu_to_fs32(sb, uspi->cs_total.cs_nifree); 616 - usb1->fs_cstotal.cs_nffree = 617 - cpu_to_fs32(sb, uspi->cs_total.cs_nffree); 611 + goto out; 618 612 } 613 + 614 + if (mtype == UFS_MOUNT_UFSTYPE_44BSD && 615 + (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) { 616 + /* store stats in both old and new places */ 617 + usb2->fs_un.fs_u2.cs_ndir = 618 + cpu_to_fs64(sb, uspi->cs_total.cs_ndir); 619 + usb2->fs_un.fs_u2.cs_nbfree = 620 + cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); 621 + usb3->fs_un1.fs_u2.cs_nifree = 622 + cpu_to_fs64(sb, uspi->cs_total.cs_nifree); 623 + usb3->fs_un1.fs_u2.cs_nffree = 624 + cpu_to_fs64(sb, uspi->cs_total.cs_nffree); 625 + } 626 + usb1->fs_cstotal.cs_ndir = cpu_to_fs32(sb, uspi->cs_total.cs_ndir); 627 + usb1->fs_cstotal.cs_nbfree = cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); 628 + usb1->fs_cstotal.cs_nifree = cpu_to_fs32(sb, uspi->cs_total.cs_nifree); 629 + usb1->fs_cstotal.cs_nffree = cpu_to_fs32(sb, uspi->cs_total.cs_nffree); 630 + out: 619 631 ubh_mark_buffer_dirty(USPI_UBH(uspi)); 620 632 ufs_print_super_stuff(sb, usb1, usb2, usb3); 621 633 UFSD("EXIT\n"); ··· 1004 996 flags |= UFS_ST_SUN; 1005 997 } 1006 998 999 + if ((flags & UFS_ST_MASK) == UFS_ST_44BSD && 1000 + uspi->s_postblformat == UFS_42POSTBLFMT) { 1001 + if (!silent) 1002 + pr_err("this is not a 44bsd filesystem"); 1003 + goto failed; 1004 + } 1005 + 1007 1006 /* 1008 1007 * Check ufs magic number 1009 1008 */ ··· 1158 1143 uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask); 1159 1144 1160 1145 if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 1161 - uspi->s_u2_size = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size); 1162 - uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); 1146 + uspi->s_size = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size); 1147 + uspi->s_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); 1163 1148 } else { 1164 1149 uspi->s_size = fs32_to_cpu(sb, usb1->fs_size); 1165 1150 uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize); ··· 1207 1192 uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos); 1208 1193 uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff); 1209 1194 uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff); 1195 + 1196 + uspi->s_root_blocks = mul_u64_u32_div(uspi->s_dsize, 1197 + uspi->s_minfree, 100); 1210 1198 1211 1199 /* 1212 1200 * Compute another frequently used values ··· 1400 1382 mutex_lock(&UFS_SB(sb)->s_lock); 1401 1383 usb3 = ubh_get_usb_third(uspi); 1402 1384 1403 - if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { 1385 + if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 1404 1386 buf->f_type = UFS2_MAGIC; 1405 - buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); 1406 - } else { 1387 + else 1407 1388 buf->f_type = UFS_MAGIC; 1408 - buf->f_blocks = uspi->s_dsize; 1409 - } 1410 - buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) + 1411 - uspi->cs_total.cs_nffree; 1389 + 1390 + buf->f_blocks = uspi->s_dsize; 1391 + buf->f_bfree = ufs_freefrags(uspi); 1412 1392 buf->f_ffree = uspi->cs_total.cs_nifree; 1413 1393 buf->f_bsize = sb->s_blocksize; 1414 - buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree)) 1415 - ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; 1394 + buf->f_bavail = (buf->f_bfree > uspi->s_root_blocks) 1395 + ? (buf->f_bfree - uspi->s_root_blocks) : 0; 1416 1396 buf->f_files = uspi->s_ncg * uspi->s_ipg; 1417 1397 buf->f_namelen = UFS_MAXNAMLEN; 1418 1398 buf->f_fsid.val[0] = (u32)id;
+3 -4
fs/ufs/ufs_fs.h
··· 733 733 __u32 s_dblkno; /* offset of first data after cg */ 734 734 __u32 s_cgoffset; /* cylinder group offset in cylinder */ 735 735 __u32 s_cgmask; /* used to calc mod fs_ntrak */ 736 - __u32 s_size; /* number of blocks (fragments) in fs */ 737 - __u32 s_dsize; /* number of data blocks in fs */ 738 - __u64 s_u2_size; /* ufs2: number of blocks (fragments) in fs */ 739 - __u64 s_u2_dsize; /*ufs2: number of data blocks in fs */ 736 + __u64 s_size; /* number of blocks (fragments) in fs */ 737 + __u64 s_dsize; /* number of data blocks in fs */ 740 738 __u32 s_ncg; /* number of cylinder groups */ 741 739 __u32 s_bsize; /* size of basic blocks */ 742 740 __u32 s_fsize; /* size of fragments */ ··· 791 793 __u32 s_maxsymlinklen;/* upper limit on fast symlinks' size */ 792 794 __s32 fs_magic; /* filesystem magic */ 793 795 unsigned int s_dirblksize; 796 + __u64 s_root_blocks; 794 797 }; 795 798 796 799 /*
+8 -9
fs/ufs/util.c
··· 243 243 struct page *ufs_get_locked_page(struct address_space *mapping, 244 244 pgoff_t index) 245 245 { 246 - struct page *page; 247 - 248 - page = find_lock_page(mapping, index); 246 + struct inode *inode = mapping->host; 247 + struct page *page = find_lock_page(mapping, index); 249 248 if (!page) { 250 249 page = read_mapping_page(mapping, index, NULL); 251 250 ··· 252 253 printk(KERN_ERR "ufs_change_blocknr: " 253 254 "read_mapping_page error: ino %lu, index: %lu\n", 254 255 mapping->host->i_ino, index); 255 - goto out; 256 + return page; 256 257 } 257 258 258 259 lock_page(page); ··· 261 262 /* Truncate got there first */ 262 263 unlock_page(page); 263 264 put_page(page); 264 - page = NULL; 265 - goto out; 265 + return NULL; 266 266 } 267 267 268 268 if (!PageUptodate(page) || PageError(page)) { ··· 270 272 271 273 printk(KERN_ERR "ufs_change_blocknr: " 272 274 "can not read page: ino %lu, index: %lu\n", 273 - mapping->host->i_ino, index); 275 + inode->i_ino, index); 274 276 275 - page = ERR_PTR(-EIO); 277 + return ERR_PTR(-EIO); 276 278 } 277 279 } 278 - out: 280 + if (!page_has_buffers(page)) 281 + create_empty_buffers(page, 1 << inode->i_blkbits, 0); 279 282 return page; 280 283 }
+2 -7
fs/ufs/util.h
··· 350 350 #define ubh_blkmap(ubh,begin,bit) \ 351 351 ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) 352 352 353 - /* 354 - * Determine the number of available frags given a 355 - * percentage to hold in reserve. 356 - */ 357 353 static inline u64 358 - ufs_freespace(struct ufs_sb_private_info *uspi, int percentreserved) 354 + ufs_freefrags(struct ufs_sb_private_info *uspi) 359 355 { 360 356 return ufs_blkstofrags(uspi->cs_total.cs_nbfree) + 361 - uspi->cs_total.cs_nffree - 362 - (uspi->s_dsize * (percentreserved) / 100); 357 + uspi->cs_total.cs_nffree; 363 358 } 364 359 365 360 /*