aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-02-13 07:27:43 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-02-13 07:27:43 -0500
commit7359a19cc758946aba0e45233b8641256b194884 (patch)
treed96aaeb2fb239efe6fdb0b4698eb94108719f423 /fs/gfs2/inode.c
parent18ec7d5c3f434aed9661ed10a9e1f48cdeb4981d (diff)
[GFS2] Fix for root inode ref count bug
Umount is now working correctly again. The bug was due to not getting an extra ref count when mounting the fs. We should have bumped it by two (once for the internal pointer to the root inode from the super block and once for the inode hanging off the dcache entry for root). Also this patch tidys up the code dealing with looking up and creating inodes. We now pass Linux inodes (with gfs2_inodes attached) rather than the other way around and this reduces code duplication in various places. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 4c193e38f8e4..2a00b96eac01 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -711,24 +711,28 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
711 * Returns: errno 711 * Returns: errno
712 */ 712 */
713 713
714int gfs2_lookupi(struct gfs2_inode *dip, struct qstr *name, int is_root, 714int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
715 struct gfs2_inode **ipp) 715 struct inode **inodep)
716{ 716{
717 struct gfs2_inode *ipp;
718 struct gfs2_inode *dip = get_v2ip(dir);
717 struct gfs2_sbd *sdp = dip->i_sbd; 719 struct gfs2_sbd *sdp = dip->i_sbd;
718 struct gfs2_holder d_gh; 720 struct gfs2_holder d_gh;
719 struct gfs2_inum inum; 721 struct gfs2_inum inum;
720 unsigned int type; 722 unsigned int type;
721 struct gfs2_glock *gl; 723 struct gfs2_glock *gl;
722 int error; 724 int error = 0;
725
726 *inodep = NULL;
723 727
724 if (!name->len || name->len > GFS2_FNAMESIZE) 728 if (!name->len || name->len > GFS2_FNAMESIZE)
725 return -ENAMETOOLONG; 729 return -ENAMETOOLONG;
726 730
727 if (gfs2_filecmp(name, ".", 1) || 731 if (gfs2_filecmp(name, ".", 1) ||
728 (gfs2_filecmp(name, "..", 2) && dip == get_v2ip(sdp->sd_root_dir))) { 732 (gfs2_filecmp(name, "..", 2) && dir == sdp->sd_root_dir)) {
729 gfs2_inode_hold(dip); 733 gfs2_inode_hold(dip);
730 *ipp = dip; 734 ipp = dip;
731 return 0; 735 goto done;
732 } 736 }
733 737
734 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); 738 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
@@ -750,15 +754,21 @@ int gfs2_lookupi(struct gfs2_inode *dip, struct qstr *name, int is_root,
750 if (error) 754 if (error)
751 goto out; 755 goto out;
752 756
753 error = gfs2_inode_get(gl, &inum, CREATE, ipp); 757 error = gfs2_inode_get(gl, &inum, CREATE, &ipp);
754 if (!error) 758 if (!error)
755 gfs2_inode_min_init(*ipp, type); 759 gfs2_inode_min_init(ipp, type);
756 760
757 gfs2_glock_put(gl); 761 gfs2_glock_put(gl);
758 762
759 out: 763out:
760 gfs2_glock_dq_uninit(&d_gh); 764 gfs2_glock_dq_uninit(&d_gh);
761 765done:
766 if (error == 0) {
767 *inodep = gfs2_ip2v(ipp);
768 if (!*inodep)
769 error = -ENOMEM;
770 gfs2_inode_put(ipp);
771 }
762 return error; 772 return error;
763} 773}
764 774
@@ -1171,15 +1181,16 @@ static int link_dinode(struct gfs2_inode *dip, struct qstr *name,
1171 * @ghs[0] is an initialized holder for the directory 1181 * @ghs[0] is an initialized holder for the directory
1172 * @ghs[1] is the holder for the inode lock 1182 * @ghs[1] is the holder for the inode lock
1173 * 1183 *
1174 * If the return value is 0, the glocks on both the directory and the new 1184 * If the return value is not NULL, the glocks on both the directory and the new
1175 * file are held. A transaction has been started and an inplace reservation 1185 * file are held. A transaction has been started and an inplace reservation
1176 * is held, as well. 1186 * is held, as well.
1177 * 1187 *
1178 * Returns: errno 1188 * Returns: An inode
1179 */ 1189 */
1180 1190
1181int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode) 1191struct inode *gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1182{ 1192{
1193 struct inode *inode;
1183 struct gfs2_inode *dip = get_gl2ip(ghs->gh_gl); 1194 struct gfs2_inode *dip = get_gl2ip(ghs->gh_gl);
1184 struct gfs2_sbd *sdp = dip->i_sbd; 1195 struct gfs2_sbd *sdp = dip->i_sbd;
1185 struct gfs2_unlinked *ul; 1196 struct gfs2_unlinked *ul;
@@ -1187,11 +1198,11 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1187 int error; 1198 int error;
1188 1199
1189 if (!name->len || name->len > GFS2_FNAMESIZE) 1200 if (!name->len || name->len > GFS2_FNAMESIZE)
1190 return -ENAMETOOLONG; 1201 return ERR_PTR(-ENAMETOOLONG);
1191 1202
1192 error = gfs2_unlinked_get(sdp, &ul); 1203 error = gfs2_unlinked_get(sdp, &ul);
1193 if (error) 1204 if (error)
1194 return error; 1205 return ERR_PTR(error);
1195 1206
1196 gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs); 1207 gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);
1197 error = gfs2_glock_nq(ghs); 1208 error = gfs2_glock_nq(ghs);
@@ -1220,7 +1231,7 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1220 ghs + 1); 1231 ghs + 1);
1221 if (error) { 1232 if (error) {
1222 gfs2_unlinked_put(sdp, ul); 1233 gfs2_unlinked_put(sdp, ul);
1223 return error; 1234 return ERR_PTR(error);
1224 } 1235 }
1225 1236
1226 gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs); 1237 gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);
@@ -1228,7 +1239,7 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1228 if (error) { 1239 if (error) {
1229 gfs2_glock_dq_uninit(ghs + 1); 1240 gfs2_glock_dq_uninit(ghs + 1);
1230 gfs2_unlinked_put(sdp, ul); 1241 gfs2_unlinked_put(sdp, ul);
1231 return error; 1242 return ERR_PTR(error);
1232 } 1243 }
1233 1244
1234 error = create_ok(dip, name, mode); 1245 error = create_ok(dip, name, mode);
@@ -1266,7 +1277,11 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1266 1277
1267 gfs2_unlinked_put(sdp, ul); 1278 gfs2_unlinked_put(sdp, ul);
1268 1279
1269 return 0; 1280 inode = gfs2_ip2v(ip);
1281 gfs2_inode_put(ip);
1282 if (!inode)
1283 return ERR_PTR(-ENOMEM);
1284 return inode;
1270 1285
1271 fail_iput: 1286 fail_iput:
1272 gfs2_inode_put(ip); 1287 gfs2_inode_put(ip);
@@ -1280,7 +1295,7 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
1280 fail: 1295 fail:
1281 gfs2_unlinked_put(sdp, ul); 1296 gfs2_unlinked_put(sdp, ul);
1282 1297
1283 return error; 1298 return ERR_PTR(error);
1284} 1299}
1285 1300
1286/** 1301/**
@@ -1445,7 +1460,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, struct qstr *name,
1445int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) 1460int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
1446{ 1461{
1447 struct gfs2_sbd *sdp = this->i_sbd; 1462 struct gfs2_sbd *sdp = this->i_sbd;
1448 struct gfs2_inode *tmp; 1463 struct inode *dir = to->i_vnode;
1464 struct inode *tmp;
1449 struct qstr dotdot; 1465 struct qstr dotdot;
1450 int error = 0; 1466 int error = 0;
1451 1467
@@ -1453,27 +1469,27 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
1453 dotdot.name = ".."; 1469 dotdot.name = "..";
1454 dotdot.len = 2; 1470 dotdot.len = 2;
1455 1471
1456 gfs2_inode_hold(to); 1472 igrab(dir);
1457 1473
1458 for (;;) { 1474 for (;;) {
1459 if (to == this) { 1475 if (dir == this->i_vnode) {
1460 error = -EINVAL; 1476 error = -EINVAL;
1461 break; 1477 break;
1462 } 1478 }
1463 if (to == get_v2ip(sdp->sd_root_dir)) { 1479 if (dir == sdp->sd_root_dir) {
1464 error = 0; 1480 error = 0;
1465 break; 1481 break;
1466 } 1482 }
1467 1483
1468 error = gfs2_lookupi(to, &dotdot, 1, &tmp); 1484 error = gfs2_lookupi(dir, &dotdot, 1, &tmp);
1469 if (error) 1485 if (error)
1470 break; 1486 break;
1471 1487
1472 gfs2_inode_put(to); 1488 iput(dir);
1473 to = tmp; 1489 dir = tmp;
1474 } 1490 }
1475 1491
1476 gfs2_inode_put(to); 1492 iput(dir);
1477 1493
1478 return error; 1494 return error;
1479} 1495}