aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-20 12:30:04 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-20 12:30:04 -0500
commitc752666c17f870fa8ae9f16804dd457e9e6daaec (patch)
treec3c48383f386a24edbdf3c6292f25b587e6d9368 /fs/gfs2/inode.c
parent419c93e0b6b9eef0bf26b8ad415f2a5bf4300119 (diff)
[GFS2] Fix bug in directory code and tidy up
Due to a typo, the dir leaf split operation was (for the first split in a directory) writing the new hash vaules at the wrong offset. This is now fixed. Also some other tidy ups are included: - We use GFS2's hash function for dentries (see ops_dentry.c) so that we don't have to keep recalculating the hash values. - A lot of common code is eliminated between the various directory lookup routines. - Better error checking on directory lookup (previously different routines checked for different errors) - The leaf split operation has a couple of redundant operations removed from it, so it should be faster. There is still further scope for further clean ups in the directory code, and readdir in particular could do with slimming down a bit. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index cd1de61bff2f..d403d51d5b0f 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -228,12 +228,10 @@ struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum *inum)
228 228
229void gfs2_inode_min_init(struct gfs2_inode *ip, unsigned int type) 229void gfs2_inode_min_init(struct gfs2_inode *ip, unsigned int type)
230{ 230{
231 spin_lock(&ip->i_spin);
232 if (!test_and_set_bit(GIF_MIN_INIT, &ip->i_flags)) { 231 if (!test_and_set_bit(GIF_MIN_INIT, &ip->i_flags)) {
233 ip->i_di.di_nlink = 1; 232 ip->i_di.di_nlink = 1;
234 ip->i_di.di_mode = DT2IF(type); 233 ip->i_di.di_mode = DT2IF(type);
235 } 234 }
236 spin_unlock(&ip->i_spin);
237} 235}
238 236
239/** 237/**
@@ -257,10 +255,8 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
257 return -EIO; 255 return -EIO;
258 } 256 }
259 257
260 spin_lock(&ip->i_spin);
261 gfs2_dinode_in(&ip->i_di, dibh->b_data); 258 gfs2_dinode_in(&ip->i_di, dibh->b_data);
262 set_bit(GIF_MIN_INIT, &ip->i_flags); 259 set_bit(GIF_MIN_INIT, &ip->i_flags);
263 spin_unlock(&ip->i_spin);
264 260
265 brelse(dibh); 261 brelse(dibh);
266 262
@@ -702,6 +698,16 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
702 return 0; 698 return 0;
703} 699}
704 700
701struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
702{
703 struct qstr qstr;
704 qstr.name = name;
705 qstr.len = strlen(name);
706 qstr.hash = gfs2_disk_hash(qstr.name, qstr.len);
707 return gfs2_lookupi(dip, &qstr, 1, NULL);
708}
709
710
705/** 711/**
706 * gfs2_lookupi - Look up a filename in a directory and return its inode 712 * gfs2_lookupi - Look up a filename in a directory and return its inode
707 * @d_gh: An initialized holder for the directory glock 713 * @d_gh: An initialized holder for the directory glock
@@ -715,8 +721,9 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
715 * Returns: errno 721 * Returns: errno
716 */ 722 */
717 723
718int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root, 724struct inode *gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
719 struct inode **inodep) 725 struct nameidata *nd)
726
720{ 727{
721 struct super_block *sb = dir->i_sb; 728 struct super_block *sb = dir->i_sb;
722 struct gfs2_inode *ipp; 729 struct gfs2_inode *ipp;
@@ -727,14 +734,14 @@ int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
727 unsigned int type; 734 unsigned int type;
728 struct gfs2_glock *gl; 735 struct gfs2_glock *gl;
729 int error = 0; 736 int error = 0;
730 737 struct inode *inode = NULL;
731 *inodep = NULL;
732 738
733 if (!name->len || name->len > GFS2_FNAMESIZE) 739 if (!name->len || name->len > GFS2_FNAMESIZE)
734 return -ENAMETOOLONG; 740 return ERR_PTR(-ENAMETOOLONG);
735 741
736 if (gfs2_filecmp(name, ".", 1) || 742 if ((name->len == 1 && memcmp(name->name, ".", 1) == 0) ||
737 (gfs2_filecmp(name, "..", 2) && dir == sb->s_root->d_inode)) { 743 (name->len == 2 && memcmp(name->name, "..", 2) == 0 &&
744 dir == sb->s_root->d_inode)) {
738 gfs2_inode_hold(dip); 745 gfs2_inode_hold(dip);
739 ipp = dip; 746 ipp = dip;
740 goto done; 747 goto done;
@@ -742,7 +749,7 @@ int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
742 749
743 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); 750 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
744 if (error) 751 if (error)
745 return error; 752 return ERR_PTR(error);
746 753
747 if (!is_root) { 754 if (!is_root) {
748 error = gfs2_repermission(dip->i_vnode, MAY_EXEC, NULL); 755 error = gfs2_repermission(dip->i_vnode, MAY_EXEC, NULL);
@@ -750,7 +757,7 @@ int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
750 goto out; 757 goto out;
751 } 758 }
752 759
753 error = gfs2_dir_search(dip, name, &inum, &type); 760 error = gfs2_dir_search(dir, name, &inum, &type);
754 if (error) 761 if (error)
755 goto out; 762 goto out;
756 763
@@ -768,13 +775,16 @@ int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
768out: 775out:
769 gfs2_glock_dq_uninit(&d_gh); 776 gfs2_glock_dq_uninit(&d_gh);
770done: 777done:
778 if (error == -ENOENT)
779 return NULL;
771 if (error == 0) { 780 if (error == 0) {
772 *inodep = gfs2_ip2v(ipp); 781 inode = gfs2_ip2v(ipp);
773 if (!*inodep)
774 error = -ENOMEM;
775 gfs2_inode_put(ipp); 782 gfs2_inode_put(ipp);
783 if (!inode)
784 return ERR_PTR(-ENOMEM);
785 return inode;
776 } 786 }
777 return error; 787 return ERR_PTR(error);
778} 788}
779 789
780static int pick_formal_ino_1(struct gfs2_sbd *sdp, uint64_t *formal_ino) 790static int pick_formal_ino_1(struct gfs2_sbd *sdp, uint64_t *formal_ino)
@@ -918,7 +928,7 @@ static int create_ok(struct gfs2_inode *dip, struct qstr *name,
918 if (!dip->i_di.di_nlink) 928 if (!dip->i_di.di_nlink)
919 return -EPERM; 929 return -EPERM;
920 930
921 error = gfs2_dir_search(dip, name, NULL, NULL); 931 error = gfs2_dir_search(dip->i_vnode, name, NULL, NULL);
922 switch (error) { 932 switch (error) {
923 case -ENOENT: 933 case -ENOENT:
924 error = 0; 934 error = 0;
@@ -1116,7 +1126,9 @@ static int link_dinode(struct gfs2_inode *dip, struct qstr *name,
1116 if (error) 1126 if (error)
1117 goto fail; 1127 goto fail;
1118 1128
1119 error = gfs2_diradd_alloc_required(dip, name, &alloc_required); 1129 error = alloc_required = gfs2_diradd_alloc_required(dip->i_vnode, name);
1130 if (alloc_required < 0)
1131 goto fail;
1120 if (alloc_required) { 1132 if (alloc_required) {
1121 error = gfs2_quota_check(dip, dip->i_di.di_uid, 1133 error = gfs2_quota_check(dip, dip->i_di.di_uid,
1122 dip->i_di.di_gid); 1134 dip->i_di.di_gid);
@@ -1145,7 +1157,7 @@ static int link_dinode(struct gfs2_inode *dip, struct qstr *name,
1145 goto fail_quota_locks; 1157 goto fail_quota_locks;
1146 } 1158 }
1147 1159
1148 error = gfs2_dir_add(dip, name, &ip->i_num, IF2DT(ip->i_di.di_mode)); 1160 error = gfs2_dir_add(dip->i_vnode, name, &ip->i_num, IF2DT(ip->i_di.di_mode));
1149 if (error) 1161 if (error)
1150 goto fail_end_trans; 1162 goto fail_end_trans;
1151 1163
@@ -1379,12 +1391,14 @@ int gfs2_rmdiri(struct gfs2_inode *dip, struct qstr *name,
1379 1391
1380 dotname.len = 1; 1392 dotname.len = 1;
1381 dotname.name = "."; 1393 dotname.name = ".";
1394 dotname.hash = gfs2_disk_hash(dotname.name, dotname.len);
1382 error = gfs2_dir_del(ip, &dotname); 1395 error = gfs2_dir_del(ip, &dotname);
1383 if (error) 1396 if (error)
1384 return error; 1397 return error;
1385 1398
1386 dotname.len = 2; 1399 dotname.len = 2;
1387 dotname.name = ".."; 1400 dotname.name = "..";
1401 dotname.hash = gfs2_disk_hash(dotname.name, dotname.len);
1388 error = gfs2_dir_del(ip, &dotname); 1402 error = gfs2_dir_del(ip, &dotname);
1389 if (error) 1403 if (error)
1390 return error; 1404 return error;
@@ -1439,7 +1453,7 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, struct qstr *name,
1439 if (error) 1453 if (error)
1440 return error; 1454 return error;
1441 1455
1442 error = gfs2_dir_search(dip, name, &inum, &type); 1456 error = gfs2_dir_search(dip->i_vnode, name, &inum, &type);
1443 if (error) 1457 if (error)
1444 return error; 1458 return error;
1445 1459
@@ -1476,6 +1490,7 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
1476 memset(&dotdot, 0, sizeof(struct qstr)); 1490 memset(&dotdot, 0, sizeof(struct qstr));
1477 dotdot.name = ".."; 1491 dotdot.name = "..";
1478 dotdot.len = 2; 1492 dotdot.len = 2;
1493 dotdot.hash = gfs2_disk_hash(dotdot.name, dotdot.len);
1479 1494
1480 igrab(dir); 1495 igrab(dir);
1481 1496
@@ -1489,9 +1504,11 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
1489 break; 1504 break;
1490 } 1505 }
1491 1506
1492 error = gfs2_lookupi(dir, &dotdot, 1, &tmp); 1507 tmp = gfs2_lookupi(dir, &dotdot, 1, NULL);
1493 if (error) 1508 if (IS_ERR(tmp)) {
1509 error = PTR_ERR(tmp);
1494 break; 1510 break;
1511 }
1495 1512
1496 iput(dir); 1513 iput(dir);
1497 dir = tmp; 1514 dir = tmp;