Skip to content

Commit 5faab9e

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull UFS fixes from Al Viro: "This is just the obvious backport fodder; I'm pretty sure that there will be more - definitely so wrt performance and quite possibly correctness as well" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: ufs: we need to sync inode before freeing it excessive checks in ufs_write_failed() and ufs_evict_inode() ufs_getfrag_block(): we only grab ->truncate_mutex on block creation path ufs_extend_tail(): fix the braino in calling conventions of ufs_new_fragments() ufs: set correct ->s_maxsize ufs: restore maintaining ->i_blocks fix ufs_isblockset() ufs: restore proper tail allocation
2 parents 66cea28 + 67a7001 commit 5faab9e

File tree

5 files changed

+63
-20
lines changed

5 files changed

+63
-20
lines changed

fs/stat.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes)
672672
inode->i_bytes -= 512;
673673
}
674674
}
675+
EXPORT_SYMBOL(__inode_add_bytes);
675676

676677
void inode_add_bytes(struct inode *inode, loff_t bytes)
677678
{

fs/ufs/balloc.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
8282
ufs_error (sb, "ufs_free_fragments",
8383
"bit already cleared for fragment %u", i);
8484
}
85-
85+
86+
inode_sub_bytes(inode, count << uspi->s_fshift);
8687
fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
8788
uspi->cs_total.cs_nffree += count;
8889
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
@@ -184,6 +185,7 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
184185
ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
185186
}
186187
ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
188+
inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
187189
if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
188190
ufs_clusteracct (sb, ucpi, blkno, 1);
189191

@@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
494496
return 0;
495497
}
496498

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+
497513
static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
498514
unsigned oldcount, unsigned newcount)
499515
{
@@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
530546
for (i = oldcount; i < newcount; i++)
531547
if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
532548
return 0;
549+
550+
if (!try_add_frags(inode, count))
551+
return 0;
533552
/*
534553
* Block can be extended
535554
*/
@@ -647,6 +666,7 @@ static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
647666
ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
648667
i = uspi->s_fpb - count;
649668

669+
inode_sub_bytes(inode, i << uspi->s_fshift);
650670
fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
651671
uspi->cs_total.cs_nffree += i;
652672
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
@@ -657,6 +677,8 @@ static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
657677
result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
658678
if (result == INVBLOCK)
659679
return 0;
680+
if (!try_add_frags(inode, count))
681+
return 0;
660682
for (i = 0; i < count; i++)
661683
ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
662684

@@ -716,6 +738,8 @@ static u64 ufs_alloccg_block(struct inode *inode,
716738
return INVBLOCK;
717739
ucpi->c_rotor = result;
718740
gotit:
741+
if (!try_add_frags(inode, uspi->s_fpb))
742+
return 0;
719743
blkno = ufs_fragstoblks(result);
720744
ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
721745
if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)

fs/ufs/inode.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to,
235235

236236
p = ufs_get_direct_data_ptr(uspi, ufsi, block);
237237
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);
239240
return tmp != 0;
240241
}
241242

@@ -284,7 +285,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index,
284285
goal += uspi->s_fpb;
285286
}
286287
tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment),
287-
goal, uspi->s_fpb, err, locked_page);
288+
goal, nfrags, err, locked_page);
288289

289290
if (!tmp) {
290291
*err = -ENOSPC;
@@ -402,7 +403,9 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff
402403

403404
if (!create) {
404405
phys64 = ufs_frag_map(inode, offsets, depth);
405-
goto out;
406+
if (phys64)
407+
map_bh(bh_result, sb, phys64 + frag);
408+
return 0;
406409
}
407410

408411
/* This code entered only while writing ....? */
@@ -841,8 +844,11 @@ void ufs_evict_inode(struct inode * inode)
841844
truncate_inode_pages_final(&inode->i_data);
842845
if (want_delete) {
843846
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)))
845850
ufs_truncate_blocks(inode);
851+
ufs_update_inode(inode, inode_needs_sync(inode));
846852
}
847853

848854
invalidate_inode_buffers(inode);
@@ -1100,7 +1106,7 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
11001106
return err;
11011107
}
11021108

1103-
static void __ufs_truncate_blocks(struct inode *inode)
1109+
static void ufs_truncate_blocks(struct inode *inode)
11041110
{
11051111
struct ufs_inode_info *ufsi = UFS_I(inode);
11061112
struct super_block *sb = inode->i_sb;
@@ -1183,24 +1189,14 @@ static int ufs_truncate(struct inode *inode, loff_t size)
11831189

11841190
truncate_setsize(inode, size);
11851191

1186-
__ufs_truncate_blocks(inode);
1192+
ufs_truncate_blocks(inode);
11871193
inode->i_mtime = inode->i_ctime = current_time(inode);
11881194
mark_inode_dirty(inode);
11891195
out:
11901196
UFSD("EXIT: err %d\n", err);
11911197
return err;
11921198
}
11931199

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-
12041200
int ufs_setattr(struct dentry *dentry, struct iattr *attr)
12051201
{
12061202
struct inode *inode = d_inode(dentry);

fs/ufs/super.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb)
746746
return;
747747
}
748748

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+
749766
static int ufs_fill_super(struct super_block *sb, void *data, int silent)
750767
{
751768
struct ufs_sb_info * sbi;
@@ -1211,6 +1228,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
12111228
"fast symlink size (%u)\n", uspi->s_maxsymlinklen);
12121229
uspi->s_maxsymlinklen = maxsymlen;
12131230
}
1231+
sb->s_maxbytes = ufs_max_bytes(sb);
12141232
sb->s_max_links = UFS_LINK_MAX;
12151233

12161234
inode = ufs_iget(sb, UFS_ROOTINO);

fs/ufs/util.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_(
473473
static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi,
474474
struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
475475
{
476+
u8 mask;
476477
switch (uspi->s_fpb) {
477478
case 8:
478479
return (*ubh_get_addr (ubh, begin + block) == 0xff);
479480
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;
481483
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;
483486
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;
485489
}
486490
return 0;
487491
}

0 commit comments

Comments
 (0)