#include "swab.h"
#include "util.h"
-#undef UFS_BALLOC_DEBUG
-
-#ifdef UFS_BALLOC_DEBUG
-#define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first(uspi);
- UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
+ UFSD("ENTER, fragment %u, count %u\n", fragment, count);
if (ufs_fragnum(fragment) + count > uspi->s_fpg)
ufs_error (sb, "ufs_free_fragments", "internal error");
fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
- fs32_add(sb, &usb1->fs_cstotal.cs_nffree, count);
+ uspi->cs_total.cs_nffree += count;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
blkno = ufs_fragstoblks (bbase);
if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
- fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, uspi->s_fpb);
+ uspi->cs_total.cs_nffree -= uspi->s_fpb;
fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
ufs_clusteracct (sb, ucpi, blkno, 1);
fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
- fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+ uspi->cs_total.cs_nbfree++;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
cylno = ufs_cbtocylno (bbase);
fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
ubh_mark_buffer_dirty (USPI_UBH(uspi));
ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
ubh_wait_on_buffer (UCPI_UBH(ucpi));
}
sb->s_dirt = 1;
unlock_super (sb);
- UFSD(("EXIT\n"))
+ UFSD("EXIT\n");
return;
failed:
unlock_super (sb);
- UFSD(("EXIT (FAILED)\n"))
+ UFSD("EXIT (FAILED)\n");
return;
}
uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first(uspi);
- UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
+ UFSD("ENTER, fragment %u, count %u\n", fragment, count);
if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
ufs_error (sb, "ufs_free_blocks", "internal error, "
bit = ufs_dtogd (fragment);
if (cgno >= uspi->s_ncg) {
ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
- goto failed;
+ goto failed_unlock;
}
end_bit = bit + count;
if (end_bit > uspi->s_fpg) {
ucpi = ufs_load_cylinder (sb, cgno);
if (!ucpi)
- goto failed;
+ goto failed_unlock;
ucg = ubh_get_ucg (UCPI_UBH(ucpi));
if (!ufs_cg_chkmagic(sb, ucg)) {
ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
- goto failed;
+ goto failed_unlock;
}
for (i = bit; i < end_bit; i += uspi->s_fpb) {
DQUOT_FREE_BLOCK(inode, uspi->s_fpb);
fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
- fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+ uspi->cs_total.cs_nbfree++;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
cylno = ufs_cbtocylno(i);
fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
ubh_mark_buffer_dirty (USPI_UBH(uspi));
ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
ubh_wait_on_buffer (UCPI_UBH(ucpi));
}
sb->s_dirt = 1;
unlock_super (sb);
- UFSD(("EXIT\n"))
+ UFSD("EXIT\n");
return;
-failed:
+failed_unlock:
unlock_super (sb);
- UFSD(("EXIT (FAILED)\n"))
+failed:
+ UFSD("EXIT (FAILED)\n");
return;
}
-static struct page *ufs_get_locked_page(struct address_space *mapping,
- unsigned long index)
-{
- struct page *page;
-
-try_again:
- page = find_lock_page(mapping, index);
- if (!page) {
- page = read_cache_page(mapping, index,
- (filler_t*)mapping->a_ops->readpage,
- NULL);
- if (IS_ERR(page)) {
- printk(KERN_ERR "ufs_change_blocknr: "
- "read_cache_page error: ino %lu, index: %lu\n",
- mapping->host->i_ino, index);
- goto out;
- }
-
- lock_page(page);
-
- if (!PageUptodate(page) || PageError(page)) {
- unlock_page(page);
- page_cache_release(page);
-
- printk(KERN_ERR "ufs_change_blocknr: "
- "can not read page: ino %lu, index: %lu\n",
- mapping->host->i_ino, index);
-
- page = ERR_PTR(-EIO);
- goto out;
- }
- }
-
- if (unlikely(!page->mapping || !page_has_buffers(page))) {
- unlock_page(page);
- page_cache_release(page);
- goto try_again;/*we really need these buffers*/
- }
-out:
- return page;
-}
-
/*
* Modify inode page cache in such way:
* have - blocks with b_blocknr equal to oldb...oldb+count-1
* We can come here from ufs_writepage or ufs_prepare_write,
* locked_page is argument of these functions, so we already lock it.
*/
-static void ufs_change_blocknr(struct inode *inode, unsigned int count,
- unsigned int oldb, unsigned int newb,
- struct page *locked_page)
+static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
+ unsigned int count, unsigned int oldb,
+ unsigned int newb, struct page *locked_page)
{
unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- sector_t baseblk;
struct address_space *mapping = inode->i_mapping;
pgoff_t index, cur_index = locked_page->index;
unsigned int i, j;
struct page *page;
struct buffer_head *head, *bh;
- baseblk = ((i_size_read(inode) - 1) >> inode->i_blkbits) + 1 - count;
-
- UFSD(("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
- inode->i_ino, count, oldb, newb));
+ UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
+ inode->i_ino, count, oldb, newb);
BUG_ON(!PageLocked(locked_page));
if (likely(cur_index != index)) {
page = ufs_get_locked_page(mapping, index);
- if (IS_ERR(page))
+ if (!page || IS_ERR(page)) /* it was truncated or EIO */
continue;
} else
page = locked_page;
set_page_dirty(page);
- if (likely(cur_index != index)) {
- unlock_page(page);
- page_cache_release(page);
- }
+ if (likely(cur_index != index))
+ ufs_put_locked_page(page);
}
- UFSD(("EXIT\n"));
+ UFSD("EXIT\n");
}
unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
struct ufs_super_block_first * usb1;
unsigned cgno, oldcount, newcount, tmp, request, result;
- UFSD(("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count))
+ UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
return (unsigned)-1;
}
if (fragment < UFS_I(inode)->i_lastfrag) {
- UFSD(("EXIT (ALREADY ALLOCATED)\n"))
+ UFSD("EXIT (ALREADY ALLOCATED)\n");
unlock_super (sb);
return 0;
}
}
else {
if (tmp) {
- UFSD(("EXIT (ALREADY ALLOCATED)\n"))
+ UFSD("EXIT (ALREADY ALLOCATED)\n");
unlock_super(sb);
return 0;
}
/*
* There is not enough space for user on the device
*/
- if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(usb1, UFS_MINFREE) <= 0) {
+ if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
unlock_super (sb);
- UFSD(("EXIT (FAILED)\n"))
+ UFSD("EXIT (FAILED)\n");
return 0;
}
if (result) {
*p = cpu_to_fs32(sb, result);
*err = 0;
- inode->i_blocks += count << uspi->s_nspfshift;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
}
unlock_super(sb);
- UFSD(("EXIT, result %u\n", result))
+ UFSD("EXIT, result %u\n", result);
return result;
}
result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);
if (result) {
*err = 0;
- inode->i_blocks += count << uspi->s_nspfshift;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
unlock_super(sb);
- UFSD(("EXIT, result %u\n", result))
+ UFSD("EXIT, result %u\n", result);
return result;
}
switch (fs32_to_cpu(sb, usb1->fs_optim)) {
case UFS_OPTSPACE:
request = newcount;
- if (uspi->s_minfree < 5 || fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)
- > uspi->s_dsize * uspi->s_minfree / (2 * 100) )
+ if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
+ > uspi->s_dsize * uspi->s_minfree / (2 * 100))
break;
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
break;
case UFS_OPTTIME:
request = uspi->s_fpb;
- if (fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) < uspi->s_dsize *
+ if (uspi->cs_total.cs_nffree < uspi->s_dsize *
(uspi->s_minfree - 2) / 100)
break;
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
}
result = ufs_alloc_fragments (inode, cgno, goal, request, err);
if (result) {
- ufs_change_blocknr(inode, oldcount, tmp, result, locked_page);
+ ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
+ result, locked_page);
*p = cpu_to_fs32(sb, result);
*err = 0;
- inode->i_blocks += count << uspi->s_nspfshift;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
unlock_super(sb);
if (newcount < request)
ufs_free_fragments (inode, result + newcount, request - newcount);
ufs_free_fragments (inode, tmp, oldcount);
- UFSD(("EXIT, result %u\n", result))
+ UFSD("EXIT, result %u\n", result);
return result;
}
unlock_super(sb);
- UFSD(("EXIT (FAILED)\n"))
+ UFSD("EXIT (FAILED)\n");
return 0;
}
struct ufs_cylinder_group * ucg;
unsigned cgno, fragno, fragoff, count, fragsize, i;
- UFSD(("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount))
+ UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
- fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
+ uspi->cs_total.cs_nffree -= count;
ubh_mark_buffer_dirty (USPI_UBH(uspi));
ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
ubh_wait_on_buffer (UCPI_UBH(ucpi));
}
sb->s_dirt = 1;
- UFSD(("EXIT, fragment %u\n", fragment))
+ UFSD("EXIT, fragment %u\n", fragment);
return fragment;
}
struct ufs_cylinder_group * ucg;
unsigned oldcg, i, j, k, result, allocsize;
- UFSD(("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count))
+ UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
UFS_TEST_FREE_SPACE_CG
}
- UFSD(("EXIT (FAILED)\n"))
+ UFSD("EXIT (FAILED)\n");
return 0;
cg_found:
DQUOT_FREE_BLOCK(inode, i);
fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
- fs32_add(sb, &usb1->fs_cstotal.cs_nffree, i);
+ uspi->cs_total.cs_nffree += i;
fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
fs32_add(sb, &ucg->cg_frsum[i], 1);
goto succed;
ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
- fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
+ uspi->cs_total.cs_nffree -= count;
fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
ubh_mark_buffer_dirty (USPI_UBH(uspi));
ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
if (sb->s_flags & MS_SYNCHRONOUS) {
- ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
+ ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
ubh_wait_on_buffer (UCPI_UBH(ucpi));
}
sb->s_dirt = 1;
result += cgno * uspi->s_fpg;
- UFSD(("EXIT3, result %u\n", result))
+ UFSD("EXIT3, result %u\n", result);
return result;
}
struct ufs_cylinder_group * ucg;
unsigned result, cylno, blkno;
- UFSD(("ENTER, goal %u\n", goal))
+ UFSD("ENTER, goal %u\n", goal);
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
}
fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
- fs32_sub(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+ uspi->cs_total.cs_nbfree--;
fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
cylno = ufs_cbtocylno(result);
fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
- UFSD(("EXIT, result %u\n", result))
+ UFSD("EXIT, result %u\n", result);
return result;
}
unsigned start, length, loc, result;
unsigned pos, want, blockmap, mask, end;
- UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count));
+ UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
usb1 = ubh_get_usb_first (uspi);
ucg = ubh_get_ucg(UCPI_UBH(ucpi));
want = want_arr[count];
for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
if ((blockmap & mask) == want) {
- UFSD(("EXIT, result %u\n", result));
+ UFSD("EXIT, result %u\n", result);
return result + pos;
}
mask <<= 1;
ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
ucpi->c_cgx);
- UFSD(("EXIT (FAILED)\n"));
+ UFSD("EXIT (FAILED)\n");
return (unsigned)-1;
}