aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2012-06-06 06:17:59 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-06-06 06:17:59 -0400
commit0a305e496059a113f93bdd3ad27a5aaa917fe34d (patch)
treeb0b6ce3997fef4c4e28f598a98e2e08c939414a6
parenteea5b5510fc5545d15b69da8e485a7424ae388cf (diff)
GFS2: Extend the life of the reservations
This patch lengthens the lifespan of the reservations structure for inodes. Before, they were allocated and deallocated for every write operation. With this patch, they are allocated when the first write occurs, and deallocated when the last process closes the file. It's more efficient to do it this way because it saves GFS2 a lot of unnecessary allocates and frees. It also gives us more flexibility for the future: (1) we can now fold the qadata structure back into the structure and save those alloc/frees, (2) we can use this for multi-block reservations. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/aops.c2
-rw-r--r--fs/gfs2/file.c23
-rw-r--r--fs/gfs2/inode.c23
-rw-r--r--fs/gfs2/quota.c13
-rw-r--r--fs/gfs2/rgrp.c68
-rw-r--r--fs/gfs2/rgrp.h10
-rw-r--r--fs/gfs2/super.c2
-rw-r--r--fs/gfs2/trans.h2
8 files changed, 104 insertions, 39 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index e80a464850c8..aba77b5720bc 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -878,7 +878,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
878 brelse(dibh); 878 brelse(dibh);
879failed: 879failed:
880 gfs2_trans_end(sdp); 880 gfs2_trans_end(sdp);
881 if (ip->i_res) 881 if (gfs2_mb_reserved(ip))
882 gfs2_inplace_release(ip); 882 gfs2_inplace_release(ip);
883 if (qa) { 883 if (qa) {
884 gfs2_quota_unlock(ip); 884 gfs2_quota_unlock(ip);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 31b199f6efc1..37906174d417 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -376,6 +376,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
376 */ 376 */
377 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); 377 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
378 378
379 ret = gfs2_rs_alloc(ip);
380 if (ret)
381 return ret;
382
379 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 383 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
380 ret = gfs2_glock_nq(&gh); 384 ret = gfs2_glock_nq(&gh);
381 if (ret) 385 if (ret)
@@ -569,10 +573,15 @@ static int gfs2_release(struct inode *inode, struct file *file)
569{ 573{
570 struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; 574 struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
571 struct gfs2_file *fp; 575 struct gfs2_file *fp;
576 struct gfs2_inode *ip = GFS2_I(inode);
572 577
573 fp = file->private_data; 578 fp = file->private_data;
574 file->private_data = NULL; 579 file->private_data = NULL;
575 580
581 if ((file->f_mode & FMODE_WRITE) && ip->i_res &&
582 (atomic_read(&inode->i_writecount) == 1))
583 gfs2_rs_delete(ip);
584
576 if (gfs2_assert_warn(sdp, fp)) 585 if (gfs2_assert_warn(sdp, fp))
577 return -EIO; 586 return -EIO;
578 587
@@ -653,12 +662,16 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
653 unsigned long nr_segs, loff_t pos) 662 unsigned long nr_segs, loff_t pos)
654{ 663{
655 struct file *file = iocb->ki_filp; 664 struct file *file = iocb->ki_filp;
665 struct dentry *dentry = file->f_dentry;
666 struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
667 int ret;
668
669 ret = gfs2_rs_alloc(ip);
670 if (ret)
671 return ret;
656 672
657 if (file->f_flags & O_APPEND) { 673 if (file->f_flags & O_APPEND) {
658 struct dentry *dentry = file->f_dentry;
659 struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
660 struct gfs2_holder gh; 674 struct gfs2_holder gh;
661 int ret;
662 675
663 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); 676 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
664 if (ret) 677 if (ret)
@@ -774,6 +787,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
774 if (bytes == 0) 787 if (bytes == 0)
775 bytes = sdp->sd_sb.sb_bsize; 788 bytes = sdp->sd_sb.sb_bsize;
776 789
790 error = gfs2_rs_alloc(ip);
791 if (error)
792 return error;
793
777 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); 794 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
778 error = gfs2_glock_nq(&ip->i_gh); 795 error = gfs2_glock_nq(&ip->i_gh);
779 if (unlikely(error)) 796 if (unlikely(error))
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index a9ba2444e077..2a1b4b5a648c 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -667,6 +667,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
667 if (!name->len || name->len > GFS2_FNAMESIZE) 667 if (!name->len || name->len > GFS2_FNAMESIZE)
668 return -ENAMETOOLONG; 668 return -ENAMETOOLONG;
669 669
670 error = gfs2_rs_alloc(dip);
671 if (error)
672 return error;
673
670 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); 674 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
671 if (error) 675 if (error)
672 goto fail; 676 goto fail;
@@ -704,6 +708,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
704 if (error) 708 if (error)
705 goto fail_gunlock2; 709 goto fail_gunlock2;
706 710
711 /* the new inode needs a reservation so it can allocate xattrs. */
712 error = gfs2_rs_alloc(GFS2_I(inode));
713 if (error)
714 goto fail_gunlock2;
715
707 error = gfs2_acl_create(dip, inode); 716 error = gfs2_acl_create(dip, inode);
708 if (error) 717 if (error)
709 goto fail_gunlock2; 718 goto fail_gunlock2;
@@ -722,7 +731,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
722 gfs2_trans_end(sdp); 731 gfs2_trans_end(sdp);
723 /* Check if we reserved space in the rgrp. Function link_dinode may 732 /* Check if we reserved space in the rgrp. Function link_dinode may
724 not, depending on whether alloc is required. */ 733 not, depending on whether alloc is required. */
725 if (dip->i_res) 734 if (gfs2_mb_reserved(dip))
726 gfs2_inplace_release(dip); 735 gfs2_inplace_release(dip);
727 gfs2_quota_unlock(dip); 736 gfs2_quota_unlock(dip);
728 gfs2_qadata_put(dip); 737 gfs2_qadata_put(dip);
@@ -819,6 +828,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
819 if (S_ISDIR(inode->i_mode)) 828 if (S_ISDIR(inode->i_mode))
820 return -EPERM; 829 return -EPERM;
821 830
831 error = gfs2_rs_alloc(dip);
832 if (error)
833 return error;
834
822 gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); 835 gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
823 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); 836 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
824 837
@@ -1234,6 +1247,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1234 if (error) 1247 if (error)
1235 return error; 1248 return error;
1236 1249
1250 error = gfs2_rs_alloc(ndip);
1251 if (error)
1252 return error;
1253
1237 if (odip != ndip) { 1254 if (odip != ndip) {
1238 error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 1255 error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
1239 0, &r_gh); 1256 0, &r_gh);
@@ -1644,6 +1661,10 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
1644 struct gfs2_holder i_gh; 1661 struct gfs2_holder i_gh;
1645 int error; 1662 int error;
1646 1663
1664 error = gfs2_rs_alloc(ip);
1665 if (error)
1666 return error;
1667
1647 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); 1668 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
1648 if (error) 1669 if (error)
1649 return error; 1670 return error;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index b97178e7d397..197cc2dade7f 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -764,6 +764,10 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
764 unsigned int nalloc = 0, blocks; 764 unsigned int nalloc = 0, blocks;
765 int error; 765 int error;
766 766
767 error = gfs2_rs_alloc(ip);
768 if (error)
769 return error;
770
767 gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), 771 gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
768 &data_blocks, &ind_blocks); 772 &data_blocks, &ind_blocks);
769 773
@@ -1549,10 +1553,14 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
1549 if (error) 1553 if (error)
1550 return error; 1554 return error;
1551 1555
1556 error = gfs2_rs_alloc(ip);
1557 if (error)
1558 goto out_put;
1559
1552 mutex_lock(&ip->i_inode.i_mutex); 1560 mutex_lock(&ip->i_inode.i_mutex);
1553 error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); 1561 error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh);
1554 if (error) 1562 if (error)
1555 goto out_put; 1563 goto out_unlockput;
1556 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); 1564 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
1557 if (error) 1565 if (error)
1558 goto out_q; 1566 goto out_q;
@@ -1609,8 +1617,9 @@ out_i:
1609 gfs2_glock_dq_uninit(&i_gh); 1617 gfs2_glock_dq_uninit(&i_gh);
1610out_q: 1618out_q:
1611 gfs2_glock_dq_uninit(&q_gh); 1619 gfs2_glock_dq_uninit(&q_gh);
1612out_put: 1620out_unlockput:
1613 mutex_unlock(&ip->i_inode.i_mutex); 1621 mutex_unlock(&ip->i_inode.i_mutex);
1622out_put:
1614 qd_put(qd); 1623 qd_put(qd);
1615 return error; 1624 return error;
1616} 1625}
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index f74fb9bd1973..e944fefbc9a8 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -417,6 +417,39 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
417 } 417 }
418} 418}
419 419
420/**
421 * gfs2_rs_alloc - make sure we have a reservation assigned to the inode
422 * @ip: the inode for this reservation
423 */
424int gfs2_rs_alloc(struct gfs2_inode *ip)
425{
426 int error = 0;
427
428 down_write(&ip->i_rw_mutex);
429 if (!ip->i_res) {
430 ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
431 if (!ip->i_res)
432 error = -ENOMEM;
433 }
434 up_write(&ip->i_rw_mutex);
435 return error;
436}
437
438/**
439 * gfs2_rs_delete - delete a reservation
440 * @ip: The inode for this reservation
441 *
442 */
443void gfs2_rs_delete(struct gfs2_inode *ip)
444{
445 down_write(&ip->i_rw_mutex);
446 if (ip->i_res) {
447 kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
448 ip->i_res = NULL;
449 }
450 up_write(&ip->i_rw_mutex);
451}
452
420void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) 453void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
421{ 454{
422 struct rb_node *n; 455 struct rb_node *n;
@@ -993,22 +1026,6 @@ struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip)
993} 1026}
994 1027
995/** 1028/**
996 * gfs2_blkrsv_get - get the struct gfs2_blkreserv structure for an inode
997 * @ip: the incore GFS2 inode structure
998 *
999 * Returns: the struct gfs2_qadata
1000 */
1001
1002static int gfs2_blkrsv_get(struct gfs2_inode *ip)
1003{
1004 BUG_ON(ip->i_res != NULL);
1005 ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
1006 if (!ip->i_res)
1007 return -ENOMEM;
1008 return 0;
1009}
1010
1011/**
1012 * try_rgrp_fit - See if a given reservation will fit in a given RG 1029 * try_rgrp_fit - See if a given reservation will fit in a given RG
1013 * @rgd: the RG data 1030 * @rgd: the RG data
1014 * @ip: the inode 1031 * @ip: the inode
@@ -1162,13 +1179,6 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1162 return -ENOSPC; 1179 return -ENOSPC;
1163} 1180}
1164 1181
1165static void gfs2_blkrsv_put(struct gfs2_inode *ip)
1166{
1167 BUG_ON(ip->i_res == NULL);
1168 kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
1169 ip->i_res = NULL;
1170}
1171
1172/** 1182/**
1173 * gfs2_inplace_reserve - Reserve space in the filesystem 1183 * gfs2_inplace_reserve - Reserve space in the filesystem
1174 * @ip: the inode to reserve space for 1184 * @ip: the inode to reserve space for
@@ -1181,14 +1191,10 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
1181{ 1191{
1182 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1192 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1183 struct gfs2_blkreserv *rs; 1193 struct gfs2_blkreserv *rs;
1184 int error; 1194 int error = 0;
1185 u64 last_unlinked = NO_BLOCK; 1195 u64 last_unlinked = NO_BLOCK;
1186 int tries = 0; 1196 int tries = 0;
1187 1197
1188 error = gfs2_blkrsv_get(ip);
1189 if (error)
1190 return error;
1191
1192 rs = ip->i_res; 1198 rs = ip->i_res;
1193 rs->rs_requested = requested; 1199 rs->rs_requested = requested;
1194 if (gfs2_assert_warn(sdp, requested)) { 1200 if (gfs2_assert_warn(sdp, requested)) {
@@ -1213,7 +1219,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
1213 1219
1214out: 1220out:
1215 if (error) 1221 if (error)
1216 gfs2_blkrsv_put(ip); 1222 rs->rs_requested = 0;
1217 return error; 1223 return error;
1218} 1224}
1219 1225
@@ -1230,7 +1236,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
1230 1236
1231 if (rs->rs_rgd_gh.gh_gl) 1237 if (rs->rs_rgd_gh.gh_gl)
1232 gfs2_glock_dq_uninit(&rs->rs_rgd_gh); 1238 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1233 gfs2_blkrsv_put(ip); 1239 rs->rs_requested = 0;
1234} 1240}
1235 1241
1236/** 1242/**
@@ -1496,7 +1502,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
1496 /* Only happens if there is a bug in gfs2, return something distinctive 1502 /* Only happens if there is a bug in gfs2, return something distinctive
1497 * to ensure that it is noticed. 1503 * to ensure that it is noticed.
1498 */ 1504 */
1499 if (ip->i_res == NULL) 1505 if (ip->i_res->rs_requested == 0)
1500 return -ECANCELED; 1506 return -ECANCELED;
1501 1507
1502 rgd = ip->i_rgd; 1508 rgd = ip->i_rgd;
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b4b10f4de25f..d9eda5f9ef2a 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -43,6 +43,8 @@ extern void gfs2_inplace_release(struct gfs2_inode *ip);
43extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n, 43extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
44 bool dinode, u64 *generation); 44 bool dinode, u64 *generation);
45 45
46extern int gfs2_rs_alloc(struct gfs2_inode *ip);
47extern void gfs2_rs_delete(struct gfs2_inode *ip);
46extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta); 48extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta);
47extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); 49extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
48extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip); 50extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
@@ -68,4 +70,12 @@ extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
68 const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed); 70 const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed);
69extern int gfs2_fitrim(struct file *filp, void __user *argp); 71extern int gfs2_fitrim(struct file *filp, void __user *argp);
70 72
73/* This is how to tell if a reservation is "inplace" reserved: */
74static inline int gfs2_mb_reserved(struct gfs2_inode *ip)
75{
76 if (ip->i_res && ip->i_res->rs_requested)
77 return 1;
78 return 0;
79}
80
71#endif /* __RGRP_DOT_H__ */ 81#endif /* __RGRP_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 713e621c240b..65578df29446 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1554,6 +1554,7 @@ out_unlock:
1554out: 1554out:
1555 /* Case 3 starts here */ 1555 /* Case 3 starts here */
1556 truncate_inode_pages(&inode->i_data, 0); 1556 truncate_inode_pages(&inode->i_data, 0);
1557 gfs2_rs_delete(ip);
1557 clear_inode(inode); 1558 clear_inode(inode);
1558 gfs2_dir_hash_inval(ip); 1559 gfs2_dir_hash_inval(ip);
1559 ip->i_gl->gl_object = NULL; 1560 ip->i_gl->gl_object = NULL;
@@ -1576,6 +1577,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
1576 ip->i_flags = 0; 1577 ip->i_flags = 0;
1577 ip->i_gl = NULL; 1578 ip->i_gl = NULL;
1578 ip->i_rgd = NULL; 1579 ip->i_rgd = NULL;
1580 ip->i_res = NULL;
1579 } 1581 }
1580 return &ip->i_inode; 1582 return &ip->i_inode;
1581} 1583}
diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h
index 125d4572e1c0..41f42cdccbb8 100644
--- a/fs/gfs2/trans.h
+++ b/fs/gfs2/trans.h
@@ -31,7 +31,7 @@ struct gfs2_glock;
31static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip) 31static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip)
32{ 32{
33 const struct gfs2_blkreserv *rs = ip->i_res; 33 const struct gfs2_blkreserv *rs = ip->i_res;
34 if (rs->rs_requested < ip->i_rgd->rd_length) 34 if (rs && rs->rs_requested < ip->i_rgd->rd_length)
35 return rs->rs_requested + 1; 35 return rs->rs_requested + 1;
36 return ip->i_rgd->rd_length; 36 return ip->i_rgd->rd_length;
37} 37}