|
@@ -248,6 +248,32 @@ fail_iput:
|
|
|
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;
|
|
@@ -269,12 +295,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *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);
|
|
@@ -484,7 +505,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
|
|
|
|
|
|
/* 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) {
|