goto fail;
}
+/**
+ * gfs2_set_nlink - Set the inode's link count based on on-disk info
+ * @inode: The inode in question
+ * @nlink: The link count
+ *
+ * If the link count has hit zero, it must never be raised, whatever the
+ * on-disk inode might say. When new struct inodes are created the link
+ * count is set to 1, so that we can safely use this test even when reading
+ * in on disk information for the first time.
+ */
+
+static void gfs2_set_nlink(struct inode *inode, u32 nlink)
+{
+ /*
+ * We will need to review setting the nlink count here in the
+ * light of the forthcoming ro bind mount work. This is a reminder
+ * to do that.
+ */
+ if ((inode->i_nlink != nlink) && (inode->i_nlink != 0)) {
+ if (nlink == 0)
+ clear_nlink(inode);
+ else
+ inode->i_nlink = nlink;
+ }
+}
+
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
const struct gfs2_dinode *str = buf;
ip->i_inode.i_uid = be32_to_cpu(str->di_uid);
ip->i_inode.i_gid = be32_to_cpu(str->di_gid);
- /*
- * We will need to review setting the nlink count here in the
- * light of the forthcoming ro bind mount work. This is a reminder
- * to do that.
- */
- ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
+ gfs2_set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink));
i_size_write(&ip->i_inode, be64_to_cpu(str->di_size));
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
atime.tv_sec = be64_to_cpu(str->di_atime);
/* Don't create entries in an unlinked directory */
if (!dip->i_inode.i_nlink)
- return -EPERM;
+ return -ENOENT;
error = gfs2_dir_check(&dip->i_inode, name, NULL);
switch (error) {
if (error)
goto out_child;
+ error = -ENOENT;
+ if (inode->i_nlink == 0)
+ goto out_gunlock;
+
error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0);
if (error)
goto out_gunlock;
if (error)
goto out_child;
+ error = -ENOENT;
+ if (ip->i_inode.i_nlink == 0)
+ goto out_rgrp;
+
error = gfs2_glock_nq(ghs + 2); /* rgrp */
if (error)
goto out_rgrp;
if (error)
goto out_child;
+ error = -ENOENT;
+ if (ip->i_inode.i_nlink == 0)
+ goto out_rgrp;
+
error = gfs2_glock_nq(ghs + 2); /* rgrp */
if (error)
goto out_rgrp;
goto out_gunlock;
}
+ error = -ENOENT;
+ if (ip->i_inode.i_nlink == 0)
+ goto out_gunlock;
+
/* Check out the old directory */
error = gfs2_unlink_ok(odip, &odentry->d_name, ip);
if (error)
goto out_gunlock;
+ if (nip->i_inode.i_nlink == 0) {
+ error = -EAGAIN;
+ goto out_gunlock;
+ }
+
if (S_ISDIR(nip->i_inode.i_mode)) {
if (nip->i_entries < 2) {
if (gfs2_consist_inode(nip))
if (odip != ndip) {
if (!ndip->i_inode.i_nlink) {
- error = -EINVAL;
+ error = -ENOENT;
goto out_gunlock;
}
if (ndip->i_entries == (u32)-1) {