diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index e02f85e516cb..d8cfe15255b3 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -307,6 +307,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 	struct jffs2_full_dirent *fd;
 	int namelen;
 	uint32_t alloclen;
+	uint32_t reqlen;
+	uint32_t sumsize;
 	int ret, targetlen = strlen(target);
 
 	/* FIXME: If you care. We'd need to use frags for the target
@@ -315,37 +317,41 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 		return -ENAMETOOLONG;
 
 	ri = jffs2_alloc_raw_inode();
-
 	if (!ri)
 		return -ENOMEM;
 
 	c = JFFS2_SB_INFO(dir_i->i_sb);
 
-	/* Try to reserve enough space for both node and dirent.
-	 * Just the node will do for now, though
-	 */
-	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
-				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-
-	if (ret) {
-		jffs2_free_raw_inode(ri);
-		return ret;
-	}
-
 	inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri);
-
 	if (IS_ERR(inode)) {
 		jffs2_free_raw_inode(ri);
-		jffs2_complete_reservation(c);
 		return PTR_ERR(inode);
 	}
-
 	inode->i_op = &jffs2_symlink_inode_operations;
+	inode->i_size = targetlen;
 
 	f = JFFS2_INODE_INFO(inode);
+	/* No process could find the inode now, so it's OK to release it */
+	mutex_unlock(&f->sem);
+
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
+	if (ret)
+		goto free_ri_fail;
+
+	ret = jffs2_init_acl_post(inode);
+	if (ret)
+		goto free_ri_fail;
+
+	/* Try to reserve enough space for both node and dirent */
+	namelen = dentry->d_name.len;
+	reqlen = sizeof(*ri) + targetlen + sizeof(*rd) + namelen;
+	sumsize = JFFS2_SUMMARY_INODE_SIZE + JFFS2_SUMMARY_DIRENT_SIZE(namelen);
+	ret = jffs2_reserve_space(c, reqlen, &alloclen, ALLOC_NORMAL, sumsize);
+	if (ret)
+		goto free_ri_fail;
+
+	mutex_lock(&f->sem);
 
-	inode->i_size = targetlen;
 	ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
 	ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
 	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
@@ -386,20 +392,11 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 	f->metadata = fn;
 	mutex_unlock(&f->sem);
 
-	jffs2_complete_reservation(c);
-
-	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_init_acl_post(inode);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
-				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-	if (ret)
+	ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+	if (ret) {
+		jffs2_complete_reservation(c);
 		goto fail;
+	}
 
 	rd = jffs2_alloc_raw_dirent();
 	if (!rd) {
@@ -452,6 +449,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 	d_instantiate_new(dentry, inode);
 	return 0;
 
+ free_ri_fail:
+	jffs2_free_raw_inode(ri);
  fail:
 	jffs2_iget_failed(c, inode);
 	return ret;
@@ -469,6 +468,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	struct jffs2_full_dirent *fd;
 	int namelen;
 	uint32_t alloclen;
+	uint32_t reqlen;
+	uint32_t sumsize;
 	int ret;
 
 	mode |= S_IFDIR;
@@ -479,23 +480,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 
 	c = JFFS2_SB_INFO(dir_i->i_sb);
 
-	/* Try to reserve enough space for both node and dirent.
-	 * Just the node will do for now, though
-	 */
-	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
-				  JFFS2_SUMMARY_INODE_SIZE);
-
-	if (ret) {
-		jffs2_free_raw_inode(ri);
-		return ret;
-	}
-
 	inode = jffs2_new_inode(dir_i, mode, ri);
-
 	if (IS_ERR(inode)) {
 		jffs2_free_raw_inode(ri);
-		jffs2_complete_reservation(c);
 		return PTR_ERR(inode);
 	}
 
@@ -508,6 +495,25 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	set_nlink(inode, 2);
 	/* but ic->pino_nlink is the parent ino# */
 	f->inocache->pino_nlink = dir_i->i_ino;
+	mutex_unlock(&f->sem);
+
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
+	if (ret)
+		goto free_ri_fail;
+
+	ret = jffs2_init_acl_post(inode);
+	if (ret)
+		goto free_ri_fail;
+
+	/* Try to reserve enough space for both node and dirent */
+	namelen = dentry->d_name.len;
+	reqlen = sizeof(*ri) + sizeof(*rd) + namelen;
+	sumsize = JFFS2_SUMMARY_INODE_SIZE + JFFS2_SUMMARY_DIRENT_SIZE(namelen);
+	ret = jffs2_reserve_space(c, reqlen, &alloclen, ALLOC_NORMAL, sumsize);
+	if (ret)
+		goto free_ri_fail;
+
+	mutex_lock(&f->sem);
 
 	ri->data_crc = cpu_to_je32(0);
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
@@ -529,20 +535,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	f->metadata = fn;
 	mutex_unlock(&f->sem);
 
-	jffs2_complete_reservation(c);
-
-	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_init_acl_post(inode);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
-				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-	if (ret)
+	ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+	if (ret) {
+		jffs2_complete_reservation(c);
 		goto fail;
+	}
 
 	rd = jffs2_alloc_raw_dirent();
 	if (!rd) {
@@ -596,6 +593,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	d_instantiate_new(dentry, inode);
 	return 0;
 
+ free_ri_fail:
+	jffs2_free_raw_inode(ri);
  fail:
 	jffs2_iget_failed(c, inode);
 	return ret;
@@ -638,6 +637,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	union jffs2_device_node dev;
 	int devlen = 0;
 	uint32_t alloclen;
+	uint32_t reqlen;
+	uint32_t sumsize;
 	int ret;
 
 	ri = jffs2_alloc_raw_inode();
@@ -649,29 +650,34 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		devlen = jffs2_encode_dev(&dev, rdev);
 
-	/* Try to reserve enough space for both node and dirent.
-	 * Just the node will do for now, though
-	 */
-	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen,
-				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-
-	if (ret) {
-		jffs2_free_raw_inode(ri);
-		return ret;
-	}
-
 	inode = jffs2_new_inode(dir_i, mode, ri);
-
 	if (IS_ERR(inode)) {
 		jffs2_free_raw_inode(ri);
-		jffs2_complete_reservation(c);
 		return PTR_ERR(inode);
 	}
 	inode->i_op = &jffs2_file_inode_operations;
 	init_special_inode(inode, inode->i_mode, rdev);
 
 	f = JFFS2_INODE_INFO(inode);
+	mutex_unlock(&f->sem);
+
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
+	if (ret)
+		goto free_ri_fail;
+
+	ret = jffs2_init_acl_post(inode);
+	if (ret)
+		goto free_ri_fail;
+
+	/* reserve enough space for both node and dirent */
+	namelen = dentry->d_name.len;
+	reqlen = sizeof(*ri) + devlen + sizeof(*rd) + namelen;
+	sumsize = JFFS2_SUMMARY_INODE_SIZE + JFFS2_SUMMARY_DIRENT_SIZE(namelen);
+	ret = jffs2_reserve_space(c, reqlen, &alloclen, ALLOC_NORMAL, sumsize);
+	if (ret)
+		goto free_ri_fail;
+
+	mutex_lock(&f->sem);
 
 	ri->dsize = ri->csize = cpu_to_je32(devlen);
 	ri->totlen = cpu_to_je32(sizeof(*ri) + devlen);
@@ -698,20 +704,11 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	f->metadata = fn;
 	mutex_unlock(&f->sem);
 
-	jffs2_complete_reservation(c);
-
-	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_init_acl_post(inode);
-	if (ret)
-		goto fail;
-
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
-				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
-	if (ret)
+	ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+	if (ret) {
+		jffs2_complete_reservation(c);
 		goto fail;
+	}
 
 	rd = jffs2_alloc_raw_dirent();
 	if (!rd) {
@@ -767,6 +764,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	d_instantiate_new(dentry, inode);
 	return 0;
 
+ free_ri_fail:
+	jffs2_free_raw_inode(ri);
  fail:
 	jffs2_iget_failed(c, inode);
 	return ret;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index cda9a361368e..663bb7c39ada 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -445,18 +445,30 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dnode *fn;
 	struct jffs2_full_dirent *fd;
+	uint32_t reqlen;
+	uint32_t sumsize;
 	uint32_t alloclen;
 	int ret;
 
-	/* Try to reserve enough space for both node and dirent.
-	 * Just the node will do for now, though
-	 */
-	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
-				JFFS2_SUMMARY_INODE_SIZE);
-	jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen);
+	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
+	if (ret)
+		return ret;
+
+	ret = jffs2_init_acl_post(&f->vfs_inode);
 	if (ret)
 		return ret;
 
+	/* Try to reserve enough space for both node and dirent */
+	reqlen = sizeof(*ri) + sizeof(*rd) + qstr->len;
+	sumsize = JFFS2_SUMMARY_INODE_SIZE +
+		  JFFS2_SUMMARY_DIRENT_SIZE(qstr->len);
+	ret = jffs2_reserve_space(c, reqlen, &alloclen, ALLOC_NORMAL, sumsize);
+	if (ret) {
+		jffs2_dbg(1, "jffs2_reserve_space() for dnode & dirent failed\n");
+		return ret;
+	}
+	jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen);
+
 	mutex_lock(&f->sem);
 
 	ri->data_crc = cpu_to_je32(0);
@@ -480,21 +492,10 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 	f->metadata = fn;
 
 	mutex_unlock(&f->sem);
-	jffs2_complete_reservation(c);
-
-	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
-	if (ret)
-		return ret;
-	ret = jffs2_init_acl_post(&f->vfs_inode);
-	if (ret)
-		return ret;
-
-	ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len));
 
+	ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
 	if (ret) {
-		/* Eep. */
-		jffs2_dbg(1, "jffs2_reserve_space() for dirent failed\n");
+		jffs2_complete_reservation(c);
 		return ret;
 	}
 
