summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
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 4c193e38f8e..2a00b96eac0 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)
* Returns: errno
*/
-int gfs2_lookupi(struct gfs2_inode *dip, struct qstr *name, int is_root,
- struct gfs2_inode **ipp)
+int gfs2_lookupi(struct inode *dir, struct qstr *name, int is_root,
+ struct inode **inodep)
{
+ struct gfs2_inode *ipp;
+ struct gfs2_inode *dip = get_v2ip(dir);
struct gfs2_sbd *sdp = dip->i_sbd;
struct gfs2_holder d_gh;
struct gfs2_inum inum;
unsigned int type;
struct gfs2_glock *gl;
- int error;
+ int error = 0;
+
+ *inodep = NULL;
if (!name->len || name->len > GFS2_FNAMESIZE)
return -ENAMETOOLONG;
if (gfs2_filecmp(name, ".", 1) ||
- (gfs2_filecmp(name, "..", 2) && dip == get_v2ip(sdp->sd_root_dir))) {
+ (gfs2_filecmp(name, "..", 2) && dir == sdp->sd_root_dir)) {
gfs2_inode_hold(dip);
- *ipp = dip;
- return 0;
+ ipp = dip;
+ goto done;
}
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,
if (error)
goto out;
- error = gfs2_inode_get(gl, &inum, CREATE, ipp);
+ error = gfs2_inode_get(gl, &inum, CREATE, &ipp);
if (!error)
- gfs2_inode_min_init(*ipp, type);
+ gfs2_inode_min_init(ipp, type);
gfs2_glock_put(gl);
- out:
+out:
gfs2_glock_dq_uninit(&d_gh);
-
+done:
+ if (error == 0) {
+ *inodep = gfs2_ip2v(ipp);
+ if (!*inodep)
+ error = -ENOMEM;
+ gfs2_inode_put(ipp);
+ }
return error;
}
@@ -1171,15 +1181,16 @@ static int link_dinode(struct gfs2_inode *dip, struct qstr *name,
* @ghs[0] is an initialized holder for the directory
* @ghs[1] is the holder for the inode lock
*
- * If the return value is 0, the glocks on both the directory and the new
+ * If the return value is not NULL, the glocks on both the directory and the new
* file are held. A transaction has been started and an inplace reservation
* is held, as well.
*
- * Returns: errno
+ * Returns: An inode
*/
-int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
+struct inode *gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
{
+ struct inode *inode;
struct gfs2_inode *dip = get_gl2ip(ghs->gh_gl);
struct gfs2_sbd *sdp = dip->i_sbd;
struct gfs2_unlinked *ul;
@@ -1187,11 +1198,11 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
int error;
if (!name->len || name->len > GFS2_FNAMESIZE)
- return -ENAMETOOLONG;
+ return ERR_PTR(-ENAMETOOLONG);
error = gfs2_unlinked_get(sdp, &ul);
if (error)
- return error;
+ return ERR_PTR(error);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);
error = gfs2_glock_nq(ghs);
@@ -1220,7 +1231,7 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
ghs + 1);
if (error) {
gfs2_unlinked_put(sdp, ul);
- return error;
+ return ERR_PTR(error);
}
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)
if (error) {
gfs2_glock_dq_uninit(ghs + 1);
gfs2_unlinked_put(sdp, ul);
- return error;
+ return ERR_PTR(error);
}
error = create_ok(dip, name, mode);
@@ -1266,7 +1277,11 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
gfs2_unlinked_put(sdp, ul);
- return 0;
+ inode = gfs2_ip2v(ip);
+ gfs2_inode_put(ip);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ return inode;
fail_iput:
gfs2_inode_put(ip);
@@ -1280,7 +1295,7 @@ int gfs2_createi(struct gfs2_holder *ghs, struct qstr *name, unsigned int mode)
fail:
gfs2_unlinked_put(sdp, ul);
- return error;
+ return ERR_PTR(error);
}
/**
@@ -1445,7 +1460,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, struct qstr *name,
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
{
struct gfs2_sbd *sdp = this->i_sbd;
- struct gfs2_inode *tmp;
+ struct inode *dir = to->i_vnode;
+ struct inode *tmp;
struct qstr dotdot;
int error = 0;
@@ -1453,27 +1469,27 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
dotdot.name = "..";
dotdot.len = 2;
- gfs2_inode_hold(to);
+ igrab(dir);
for (;;) {
- if (to == this) {
+ if (dir == this->i_vnode) {
error = -EINVAL;
break;
}
- if (to == get_v2ip(sdp->sd_root_dir)) {
+ if (dir == sdp->sd_root_dir) {
error = 0;
break;
}
- error = gfs2_lookupi(to, &dotdot, 1, &tmp);
+ error = gfs2_lookupi(dir, &dotdot, 1, &tmp);
if (error)
break;
- gfs2_inode_put(to);
- to = tmp;
+ iput(dir);
+ dir = tmp;
}
- gfs2_inode_put(to);
+ iput(dir);
return error;
}