diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/file.c | 31 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 8 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 66 |
3 files changed, 61 insertions, 44 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index d1d791ef38de..382000ffac1f 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -323,6 +323,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
323 | } | 323 | } |
324 | 324 | ||
325 | /** | 325 | /** |
326 | * gfs2_size_hint - Give a hint to the size of a write request | ||
327 | * @file: The struct file | ||
328 | * @offset: The file offset of the write | ||
329 | * @size: The length of the write | ||
330 | * | ||
331 | * When we are about to do a write, this function records the total | ||
332 | * write size in order to provide a suitable hint to the lower layers | ||
333 | * about how many blocks will be required. | ||
334 | * | ||
335 | */ | ||
336 | |||
337 | static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) | ||
338 | { | ||
339 | struct inode *inode = filep->f_dentry->d_inode; | ||
340 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
341 | struct gfs2_inode *ip = GFS2_I(inode); | ||
342 | size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; | ||
343 | int hint = min_t(size_t, INT_MAX, blks); | ||
344 | |||
345 | atomic_set(&ip->i_res->rs_sizehint, hint); | ||
346 | } | ||
347 | |||
348 | /** | ||
326 | * gfs2_allocate_page_backing - Use bmap to allocate blocks | 349 | * gfs2_allocate_page_backing - Use bmap to allocate blocks |
327 | * @page: The (locked) page to allocate backing for | 350 | * @page: The (locked) page to allocate backing for |
328 | * | 351 | * |
@@ -382,8 +405,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
382 | if (ret) | 405 | if (ret) |
383 | return ret; | 406 | return ret; |
384 | 407 | ||
385 | atomic_set(&ip->i_res->rs_sizehint, | 408 | gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE); |
386 | PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift); | ||
387 | 409 | ||
388 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 410 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
389 | ret = gfs2_glock_nq(&gh); | 411 | ret = gfs2_glock_nq(&gh); |
@@ -663,7 +685,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
663 | if (ret) | 685 | if (ret) |
664 | return ret; | 686 | return ret; |
665 | 687 | ||
666 | atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift); | 688 | gfs2_size_hint(file, pos, writesize); |
689 | |||
667 | if (file->f_flags & O_APPEND) { | 690 | if (file->f_flags & O_APPEND) { |
668 | struct gfs2_holder gh; | 691 | struct gfs2_holder gh; |
669 | 692 | ||
@@ -789,7 +812,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
789 | if (unlikely(error)) | 812 | if (unlikely(error)) |
790 | goto out_uninit; | 813 | goto out_uninit; |
791 | 814 | ||
792 | atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift); | 815 | gfs2_size_hint(file, offset, len); |
793 | 816 | ||
794 | while (len > 0) { | 817 | while (len > 0) { |
795 | if (len < bytes) | 818 | if (len < bytes) |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 4ce22e547308..753af3d86bbc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1722,7 +1722,9 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name, | |||
1722 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1722 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
1723 | ret = gfs2_glock_nq(&gh); | 1723 | ret = gfs2_glock_nq(&gh); |
1724 | if (ret == 0) { | 1724 | if (ret == 0) { |
1725 | ret = generic_setxattr(dentry, name, data, size, flags); | 1725 | ret = gfs2_rs_alloc(ip); |
1726 | if (ret == 0) | ||
1727 | ret = generic_setxattr(dentry, name, data, size, flags); | ||
1726 | gfs2_glock_dq(&gh); | 1728 | gfs2_glock_dq(&gh); |
1727 | } | 1729 | } |
1728 | gfs2_holder_uninit(&gh); | 1730 | gfs2_holder_uninit(&gh); |
@@ -1757,7 +1759,9 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) | |||
1757 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1759 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
1758 | ret = gfs2_glock_nq(&gh); | 1760 | ret = gfs2_glock_nq(&gh); |
1759 | if (ret == 0) { | 1761 | if (ret == 0) { |
1760 | ret = generic_removexattr(dentry, name); | 1762 | ret = gfs2_rs_alloc(ip); |
1763 | if (ret == 0) | ||
1764 | ret = generic_removexattr(dentry, name); | ||
1761 | gfs2_glock_dq(&gh); | 1765 | gfs2_glock_dq(&gh); |
1762 | } | 1766 | } |
1763 | gfs2_holder_uninit(&gh); | 1767 | gfs2_holder_uninit(&gh); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 4d34887a601d..c9ed814eeb6f 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1961,7 +1961,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) | |||
1961 | * @dinode: 1 if this block is a dinode block, otherwise data block | 1961 | * @dinode: 1 if this block is a dinode block, otherwise data block |
1962 | * @nblocks: desired extent length | 1962 | * @nblocks: desired extent length |
1963 | * | 1963 | * |
1964 | * Lay claim to previously allocated block reservation blocks. | 1964 | * Lay claim to previously reserved blocks. |
1965 | * Returns: Starting block number of the blocks claimed. | 1965 | * Returns: Starting block number of the blocks claimed. |
1966 | * Sets *nblocks to the actual extent length allocated. | 1966 | * Sets *nblocks to the actual extent length allocated. |
1967 | */ | 1967 | */ |
@@ -1970,19 +1970,17 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode, | |||
1970 | { | 1970 | { |
1971 | struct gfs2_blkreserv *rs = ip->i_res; | 1971 | struct gfs2_blkreserv *rs = ip->i_res; |
1972 | struct gfs2_rgrpd *rgd = rs->rs_rgd; | 1972 | struct gfs2_rgrpd *rgd = rs->rs_rgd; |
1973 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1974 | struct gfs2_bitmap *bi; | 1973 | struct gfs2_bitmap *bi; |
1975 | u64 start_block = gfs2_rs_startblk(rs); | 1974 | u64 start_block = gfs2_rs_startblk(rs); |
1976 | const unsigned int elen = *nblocks; | 1975 | const unsigned int elen = *nblocks; |
1977 | 1976 | ||
1978 | /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/ | ||
1979 | gfs2_assert_withdraw(sdp, rgd); | ||
1980 | /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/ | ||
1981 | bi = rs->rs_bi; | 1977 | bi = rs->rs_bi; |
1982 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1978 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1983 | 1979 | ||
1984 | for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) { | 1980 | for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) { |
1985 | /* Make sure the bitmap hasn't changed */ | 1981 | if (gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset, |
1982 | bi->bi_len, rs->rs_biblk) != GFS2_BLKST_FREE) | ||
1983 | break; | ||
1986 | gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk, | 1984 | gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk, |
1987 | dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); | 1985 | dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); |
1988 | rs->rs_biblk++; | 1986 | rs->rs_biblk++; |
@@ -1991,20 +1989,12 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode, | |||
1991 | BUG_ON(!rgd->rd_reserved); | 1989 | BUG_ON(!rgd->rd_reserved); |
1992 | rgd->rd_reserved--; | 1990 | rgd->rd_reserved--; |
1993 | dinode = false; | 1991 | dinode = false; |
1994 | trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); | ||
1995 | } | 1992 | } |
1996 | 1993 | ||
1997 | if (!rs->rs_free) { | 1994 | trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); |
1998 | struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd; | 1995 | if (!rs->rs_free || *nblocks != elen) |
1999 | |||
2000 | gfs2_rs_deltree(rs); | 1996 | gfs2_rs_deltree(rs); |
2001 | /* -nblocks because we haven't returned to do the math yet. | 1997 | |
2002 | I'm doing the math backwards to prevent negative numbers, | ||
2003 | but think of it as: | ||
2004 | if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */ | ||
2005 | if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks) | ||
2006 | rg_mblk_search(rgd, ip); | ||
2007 | } | ||
2008 | return start_block; | 1998 | return start_block; |
2009 | } | 1999 | } |
2010 | 2000 | ||
@@ -2037,34 +2027,34 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, | |||
2037 | if (ip->i_res->rs_requested == 0) | 2027 | if (ip->i_res->rs_requested == 0) |
2038 | return -ECANCELED; | 2028 | return -ECANCELED; |
2039 | 2029 | ||
2040 | /* Check if we have a multi-block reservation, and if so, claim the | 2030 | /* If we have a reservation, claim blocks from it. */ |
2041 | next free block from it. */ | ||
2042 | if (gfs2_rs_active(ip->i_res)) { | 2031 | if (gfs2_rs_active(ip->i_res)) { |
2043 | BUG_ON(!ip->i_res->rs_free); | 2032 | BUG_ON(!ip->i_res->rs_free); |
2044 | rgd = ip->i_res->rs_rgd; | 2033 | rgd = ip->i_res->rs_rgd; |
2045 | block = claim_reserved_blks(ip, dinode, nblocks); | 2034 | block = claim_reserved_blks(ip, dinode, nblocks); |
2046 | } else { | 2035 | if (*nblocks) |
2047 | rgd = ip->i_rgd; | 2036 | goto found_blocks; |
2037 | } | ||
2048 | 2038 | ||
2049 | if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) | 2039 | rgd = ip->i_rgd; |
2050 | goal = ip->i_goal - rgd->rd_data0; | ||
2051 | else | ||
2052 | goal = rgd->rd_last_alloc; | ||
2053 | |||
2054 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); | ||
2055 | |||
2056 | /* Since all blocks are reserved in advance, this shouldn't | ||
2057 | happen */ | ||
2058 | if (blk == BFITNOENT) { | ||
2059 | printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", | ||
2060 | *nblocks); | ||
2061 | printk(KERN_WARNING "FULL=%d\n", | ||
2062 | test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); | ||
2063 | goto rgrp_error; | ||
2064 | } | ||
2065 | 2040 | ||
2066 | block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); | 2041 | if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) |
2042 | goal = ip->i_goal - rgd->rd_data0; | ||
2043 | else | ||
2044 | goal = rgd->rd_last_alloc; | ||
2045 | |||
2046 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); | ||
2047 | |||
2048 | /* Since all blocks are reserved in advance, this shouldn't happen */ | ||
2049 | if (blk == BFITNOENT) { | ||
2050 | printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", *nblocks); | ||
2051 | printk(KERN_WARNING "FULL=%d\n", | ||
2052 | test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); | ||
2053 | goto rgrp_error; | ||
2067 | } | 2054 | } |
2055 | |||
2056 | block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); | ||
2057 | found_blocks: | ||
2068 | ndata = *nblocks; | 2058 | ndata = *nblocks; |
2069 | if (dinode) | 2059 | if (dinode) |
2070 | ndata--; | 2060 | ndata--; |