summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2014-01-06 06:28:41 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2014-01-06 06:28:41 -0500
commit3c1c0ae1db74b1f3e606f42158b5dadd89105c1f (patch)
treea3731a3e3ff2d6e76a3411e55a7de6749b3b129c
parent70d4ee94b370c5ef54d0870600f16bd92d18013c (diff)
GFS2: Add directory addition info structure
The intent is that this structure will hold the information required when adding entries to a directory (linking). To start with, it will contain only the number of blocks which are required to link the new entry into the directory. The current calculation returns either 0 or the maximim number of blocks that can ever be requested by such a transaction. The intent is that in a later patch, we can update the dir code to calculate this value more accurately. In addition further patches will also add further fields to the new structure to increase its utility. In addition this patch fixes a bug where the link used during inode creation was adding requesting too many blocks in some cases. This is harmless unless the fs is close to being full. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/dir.c12
-rw-r--r--fs/gfs2/dir.h7
-rw-r--r--fs/gfs2/inode.c57
3 files changed, 43 insertions, 33 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 2e5fc268d324..0b6be202a82c 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -2017,18 +2017,24 @@ out:
2017 * gfs2_diradd_alloc_required - find if adding entry will require an allocation 2017 * gfs2_diradd_alloc_required - find if adding entry will require an allocation
2018 * @ip: the file being written to 2018 * @ip: the file being written to
2019 * @filname: the filename that's going to be added 2019 * @filname: the filename that's going to be added
2020 * @da: The structure to return dir alloc info
2020 * 2021 *
2021 * Returns: 1 if alloc required, 0 if not, -ve on error 2022 * Returns: 0 if ok, -ve on error
2022 */ 2023 */
2023 2024
2024int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name) 2025int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name,
2026 struct gfs2_diradd *da)
2025{ 2027{
2028 struct gfs2_sbd *sdp = GFS2_SB(inode);
2026 struct gfs2_dirent *dent; 2029 struct gfs2_dirent *dent;
2027 struct buffer_head *bh; 2030 struct buffer_head *bh;
2028 2031
2032 da->nr_blocks = 0;
2033
2029 dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh); 2034 dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh);
2030 if (!dent) { 2035 if (!dent) {
2031 return 1; 2036 da->nr_blocks = sdp->sd_max_dirres;
2037 return 0;
2032 } 2038 }
2033 if (IS_ERR(dent)) 2039 if (IS_ERR(dent))
2034 return PTR_ERR(dent); 2040 return PTR_ERR(dent);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 4f03bbd1873f..c5573e703a7a 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -17,6 +17,10 @@ struct inode;
17struct gfs2_inode; 17struct gfs2_inode;
18struct gfs2_inum; 18struct gfs2_inum;
19 19
20struct gfs2_diradd {
21 unsigned nr_blocks;
22};
23
20extern struct inode *gfs2_dir_search(struct inode *dir, 24extern struct inode *gfs2_dir_search(struct inode *dir,
21 const struct qstr *filename, 25 const struct qstr *filename,
22 bool fail_on_exist); 26 bool fail_on_exist);
@@ -33,7 +37,8 @@ extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
33extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); 37extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
34 38
35extern int gfs2_diradd_alloc_required(struct inode *dir, 39extern int gfs2_diradd_alloc_required(struct inode *dir,
36 const struct qstr *filename); 40 const struct qstr *filename,
41 struct gfs2_diradd *da);
37extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, 42extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
38 struct buffer_head **bhp); 43 struct buffer_head **bhp);
39extern void gfs2_dir_hash_inval(struct gfs2_inode *ip); 44extern void gfs2_dir_hash_inval(struct gfs2_inode *ip);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7119504159f1..9ac8f13a8c37 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -470,13 +470,13 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
470} 470}
471 471
472static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, 472static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
473 struct gfs2_inode *ip, int arq) 473 struct gfs2_inode *ip, struct gfs2_diradd *da)
474{ 474{
475 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 475 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
476 struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, }; 476 struct gfs2_alloc_parms ap = { .target = da->nr_blocks, };
477 int error; 477 int error;
478 478
479 if (arq) { 479 if (da->nr_blocks) {
480 error = gfs2_quota_lock_check(dip); 480 error = gfs2_quota_lock_check(dip);
481 if (error) 481 if (error)
482 goto fail_quota_locks; 482 goto fail_quota_locks;
@@ -485,8 +485,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
485 if (error) 485 if (error)
486 goto fail_quota_locks; 486 goto fail_quota_locks;
487 487
488 error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + 488 error = gfs2_trans_begin(sdp, da->nr_blocks +
489 dip->i_rgd->rd_length + 489 gfs2_rg_blocks(dip, da->nr_blocks) +
490 2 * RES_DINODE + 490 2 * RES_DINODE +
491 RES_STATFS + RES_QUOTA, 0); 491 RES_STATFS + RES_QUOTA, 0);
492 if (error) 492 if (error)
@@ -560,7 +560,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
560 struct dentry *d; 560 struct dentry *d;
561 int error; 561 int error;
562 u32 aflags = 0; 562 u32 aflags = 0;
563 int arq; 563 struct gfs2_diradd da;
564 564
565 if (!name->len || name->len > GFS2_FNAMESIZE) 565 if (!name->len || name->len > GFS2_FNAMESIZE)
566 return -ENAMETOOLONG; 566 return -ENAMETOOLONG;
@@ -602,7 +602,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
602 goto fail_gunlock; 602 goto fail_gunlock;
603 } 603 }
604 604
605 arq = error = gfs2_diradd_alloc_required(dir, name); 605 error = gfs2_diradd_alloc_required(dir, name, &da);
606 if (error < 0) 606 if (error < 0)
607 goto fail_gunlock; 607 goto fail_gunlock;
608 608
@@ -690,7 +690,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
690 if (error) 690 if (error)
691 goto fail_gunlock3; 691 goto fail_gunlock3;
692 692
693 error = link_dinode(dip, name, ip, arq); 693 error = link_dinode(dip, name, ip, &da);
694 if (error) 694 if (error)
695 goto fail_gunlock3; 695 goto fail_gunlock3;
696 696
@@ -817,7 +817,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
817 struct gfs2_inode *ip = GFS2_I(inode); 817 struct gfs2_inode *ip = GFS2_I(inode);
818 struct gfs2_holder ghs[2]; 818 struct gfs2_holder ghs[2];
819 struct buffer_head *dibh; 819 struct buffer_head *dibh;
820 int alloc_required; 820 struct gfs2_diradd da;
821 int error; 821 int error;
822 822
823 if (S_ISDIR(inode->i_mode)) 823 if (S_ISDIR(inode->i_mode))
@@ -872,13 +872,12 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
872 if (ip->i_inode.i_nlink == (u32)-1) 872 if (ip->i_inode.i_nlink == (u32)-1)
873 goto out_gunlock; 873 goto out_gunlock;
874 874
875 alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name); 875 error = gfs2_diradd_alloc_required(dir, &dentry->d_name, &da);
876 if (error < 0) 876 if (error < 0)
877 goto out_gunlock; 877 goto out_gunlock;
878 error = 0;
879 878
880 if (alloc_required) { 879 if (da.nr_blocks) {
881 struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, }; 880 struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
882 error = gfs2_quota_lock_check(dip); 881 error = gfs2_quota_lock_check(dip);
883 if (error) 882 if (error)
884 goto out_gunlock; 883 goto out_gunlock;
@@ -887,8 +886,8 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
887 if (error) 886 if (error)
888 goto out_gunlock_q; 887 goto out_gunlock_q;
889 888
890 error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + 889 error = gfs2_trans_begin(sdp, da.nr_blocks +
891 gfs2_rg_blocks(dip, sdp->sd_max_dirres) + 890 gfs2_rg_blocks(dip, da.nr_blocks) +
892 2 * RES_DINODE + RES_STATFS + 891 2 * RES_DINODE + RES_STATFS +
893 RES_QUOTA, 0); 892 RES_QUOTA, 0);
894 if (error) 893 if (error)
@@ -919,10 +918,10 @@ out_brelse:
919out_end_trans: 918out_end_trans:
920 gfs2_trans_end(sdp); 919 gfs2_trans_end(sdp);
921out_ipres: 920out_ipres:
922 if (alloc_required) 921 if (da.nr_blocks)
923 gfs2_inplace_release(dip); 922 gfs2_inplace_release(dip);
924out_gunlock_q: 923out_gunlock_q:
925 if (alloc_required) 924 if (da.nr_blocks)
926 gfs2_quota_unlock(dip); 925 gfs2_quota_unlock(dip);
927out_gunlock: 926out_gunlock:
928 gfs2_glock_dq(ghs + 1); 927 gfs2_glock_dq(ghs + 1);
@@ -1254,7 +1253,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1254 struct gfs2_rgrpd *nrgd; 1253 struct gfs2_rgrpd *nrgd;
1255 unsigned int num_gh; 1254 unsigned int num_gh;
1256 int dir_rename = 0; 1255 int dir_rename = 0;
1257 int alloc_required = 0; 1256 struct gfs2_diradd da = { .nr_blocks = 0, };
1258 unsigned int x; 1257 unsigned int x;
1259 int error; 1258 int error;
1260 1259
@@ -1388,14 +1387,14 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1388 goto out_gunlock; 1387 goto out_gunlock;
1389 } 1388 }
1390 1389
1391 if (nip == NULL) 1390 if (nip == NULL) {
1392 alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); 1391 error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name, &da);
1393 error = alloc_required; 1392 if (error)
1394 if (error < 0) 1393 goto out_gunlock;
1395 goto out_gunlock; 1394 }
1396 1395
1397 if (alloc_required) { 1396 if (da.nr_blocks) {
1398 struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, }; 1397 struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
1399 error = gfs2_quota_lock_check(ndip); 1398 error = gfs2_quota_lock_check(ndip);
1400 if (error) 1399 if (error)
1401 goto out_gunlock; 1400 goto out_gunlock;
@@ -1404,8 +1403,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1404 if (error) 1403 if (error)
1405 goto out_gunlock_q; 1404 goto out_gunlock_q;
1406 1405
1407 error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + 1406 error = gfs2_trans_begin(sdp, da.nr_blocks +
1408 gfs2_rg_blocks(ndip, sdp->sd_max_dirres) + 1407 gfs2_rg_blocks(ndip, da.nr_blocks) +
1409 4 * RES_DINODE + 4 * RES_LEAF + 1408 4 * RES_DINODE + 4 * RES_LEAF +
1410 RES_STATFS + RES_QUOTA + 4, 0); 1409 RES_STATFS + RES_QUOTA + 4, 0);
1411 if (error) 1410 if (error)
@@ -1448,10 +1447,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
1448out_end_trans: 1447out_end_trans:
1449 gfs2_trans_end(sdp); 1448 gfs2_trans_end(sdp);
1450out_ipreserv: 1449out_ipreserv:
1451 if (alloc_required) 1450 if (da.nr_blocks)
1452 gfs2_inplace_release(ndip); 1451 gfs2_inplace_release(ndip);
1453out_gunlock_q: 1452out_gunlock_q:
1454 if (alloc_required) 1453 if (da.nr_blocks)
1455 gfs2_quota_unlock(ndip); 1454 gfs2_quota_unlock(ndip);
1456out_gunlock: 1455out_gunlock:
1457 while (x--) { 1456 while (x--) {