diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 0c5a575b513e..69317435faa7 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) | |||
638 | */ | 638 | */ |
639 | void gfs2_rs_delete(struct gfs2_inode *ip) | 639 | void gfs2_rs_delete(struct gfs2_inode *ip) |
640 | { | 640 | { |
641 | struct inode *inode = &ip->i_inode; | ||
642 | |||
641 | down_write(&ip->i_rw_mutex); | 643 | down_write(&ip->i_rw_mutex); |
642 | if (ip->i_res) { | 644 | if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) { |
643 | gfs2_rs_deltree(ip->i_res); | 645 | gfs2_rs_deltree(ip->i_res); |
644 | BUG_ON(ip->i_res->rs_free); | 646 | BUG_ON(ip->i_res->rs_free); |
645 | kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); | 647 | kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); |
@@ -1286,13 +1288,15 @@ int gfs2_fitrim(struct file *filp, void __user *argp) | |||
1286 | minlen = max_t(u64, r.minlen, | 1288 | minlen = max_t(u64, r.minlen, |
1287 | q->limits.discard_granularity) >> bs_shift; | 1289 | q->limits.discard_granularity) >> bs_shift; |
1288 | 1290 | ||
1291 | if (end <= start || minlen > sdp->sd_max_rg_data) | ||
1292 | return -EINVAL; | ||
1293 | |||
1289 | rgd = gfs2_blk2rgrpd(sdp, start, 0); | 1294 | rgd = gfs2_blk2rgrpd(sdp, start, 0); |
1290 | rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); | 1295 | rgd_end = gfs2_blk2rgrpd(sdp, end, 0); |
1291 | 1296 | ||
1292 | if (end <= start || | 1297 | if ((gfs2_rgrpd_get_first(sdp) == gfs2_rgrpd_get_next(rgd_end)) |
1293 | minlen > sdp->sd_max_rg_data || | 1298 | && (start > rgd_end->rd_data0 + rgd_end->rd_data)) |
1294 | start > rgd_end->rd_data0 + rgd_end->rd_data) | 1299 | return -EINVAL; /* start is beyond the end of the fs */ |
1295 | return -EINVAL; | ||
1296 | 1300 | ||
1297 | while (1) { | 1301 | while (1) { |
1298 | 1302 | ||
@@ -1334,7 +1338,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) | |||
1334 | } | 1338 | } |
1335 | 1339 | ||
1336 | out: | 1340 | out: |
1337 | r.len = trimmed << 9; | 1341 | r.len = trimmed << bs_shift; |
1338 | if (copy_to_user(argp, &r, sizeof(r))) | 1342 | if (copy_to_user(argp, &r, sizeof(r))) |
1339 | return -EFAULT; | 1343 | return -EFAULT; |
1340 | 1344 | ||
@@ -1401,9 +1405,14 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, | |||
1401 | u32 extlen; | 1405 | u32 extlen; |
1402 | u32 free_blocks = rgd->rd_free_clone - rgd->rd_reserved; | 1406 | u32 free_blocks = rgd->rd_free_clone - rgd->rd_reserved; |
1403 | int ret; | 1407 | int ret; |
1408 | struct inode *inode = &ip->i_inode; | ||
1404 | 1409 | ||
1405 | extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested); | 1410 | if (S_ISDIR(inode->i_mode)) |
1406 | extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks); | 1411 | extlen = 1; |
1412 | else { | ||
1413 | extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested); | ||
1414 | extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks); | ||
1415 | } | ||
1407 | if ((rgd->rd_free_clone < rgd->rd_reserved) || (free_blocks < extlen)) | 1416 | if ((rgd->rd_free_clone < rgd->rd_reserved) || (free_blocks < extlen)) |
1408 | return; | 1417 | return; |
1409 | 1418 | ||