diff options
-rw-r--r-- | fs/gfs2/inode.c | 35 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 23 |
2 files changed, 50 insertions, 8 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 94c3a7db1116..5a02606b68c0 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -248,6 +248,32 @@ fail_iput: | |||
248 | goto fail; | 248 | goto fail; |
249 | } | 249 | } |
250 | 250 | ||
251 | /** | ||
252 | * gfs2_set_nlink - Set the inode's link count based on on-disk info | ||
253 | * @inode: The inode in question | ||
254 | * @nlink: The link count | ||
255 | * | ||
256 | * If the link count has hit zero, it must never be raised, whatever the | ||
257 | * on-disk inode might say. When new struct inodes are created the link | ||
258 | * count is set to 1, so that we can safely use this test even when reading | ||
259 | * in on disk information for the first time. | ||
260 | */ | ||
261 | |||
262 | static void gfs2_set_nlink(struct inode *inode, u32 nlink) | ||
263 | { | ||
264 | /* | ||
265 | * We will need to review setting the nlink count here in the | ||
266 | * light of the forthcoming ro bind mount work. This is a reminder | ||
267 | * to do that. | ||
268 | */ | ||
269 | if ((inode->i_nlink != nlink) && (inode->i_nlink != 0)) { | ||
270 | if (nlink == 0) | ||
271 | clear_nlink(inode); | ||
272 | else | ||
273 | inode->i_nlink = nlink; | ||
274 | } | ||
275 | } | ||
276 | |||
251 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | 277 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) |
252 | { | 278 | { |
253 | const struct gfs2_dinode *str = buf; | 279 | const struct gfs2_dinode *str = buf; |
@@ -269,12 +295,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
269 | 295 | ||
270 | ip->i_inode.i_uid = be32_to_cpu(str->di_uid); | 296 | ip->i_inode.i_uid = be32_to_cpu(str->di_uid); |
271 | ip->i_inode.i_gid = be32_to_cpu(str->di_gid); | 297 | ip->i_inode.i_gid = be32_to_cpu(str->di_gid); |
272 | /* | 298 | gfs2_set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink)); |
273 | * We will need to review setting the nlink count here in the | ||
274 | * light of the forthcoming ro bind mount work. This is a reminder | ||
275 | * to do that. | ||
276 | */ | ||
277 | ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); | ||
278 | i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); | 299 | i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); |
279 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); | 300 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); |
280 | atime.tv_sec = be64_to_cpu(str->di_atime); | 301 | 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, | |||
484 | 505 | ||
485 | /* Don't create entries in an unlinked directory */ | 506 | /* Don't create entries in an unlinked directory */ |
486 | if (!dip->i_inode.i_nlink) | 507 | if (!dip->i_inode.i_nlink) |
487 | return -EPERM; | 508 | return -ENOENT; |
488 | 509 | ||
489 | error = gfs2_dir_check(&dip->i_inode, name, NULL); | 510 | error = gfs2_dir_check(&dip->i_inode, name, NULL); |
490 | switch (error) { | 511 | switch (error) { |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 09e436a50723..1005f9eb456e 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -162,6 +162,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
162 | if (error) | 162 | if (error) |
163 | goto out_child; | 163 | goto out_child; |
164 | 164 | ||
165 | error = -ENOENT; | ||
166 | if (inode->i_nlink == 0) | ||
167 | goto out_gunlock; | ||
168 | |||
165 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0); | 169 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0); |
166 | if (error) | 170 | if (error) |
167 | goto out_gunlock; | 171 | goto out_gunlock; |
@@ -335,6 +339,10 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
335 | if (error) | 339 | if (error) |
336 | goto out_child; | 340 | goto out_child; |
337 | 341 | ||
342 | error = -ENOENT; | ||
343 | if (ip->i_inode.i_nlink == 0) | ||
344 | goto out_rgrp; | ||
345 | |||
338 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | 346 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ |
339 | if (error) | 347 | if (error) |
340 | goto out_rgrp; | 348 | goto out_rgrp; |
@@ -589,6 +597,10 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
589 | if (error) | 597 | if (error) |
590 | goto out_child; | 598 | goto out_child; |
591 | 599 | ||
600 | error = -ENOENT; | ||
601 | if (ip->i_inode.i_nlink == 0) | ||
602 | goto out_rgrp; | ||
603 | |||
592 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | 604 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ |
593 | if (error) | 605 | if (error) |
594 | goto out_rgrp; | 606 | goto out_rgrp; |
@@ -792,6 +804,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
792 | goto out_gunlock; | 804 | goto out_gunlock; |
793 | } | 805 | } |
794 | 806 | ||
807 | error = -ENOENT; | ||
808 | if (ip->i_inode.i_nlink == 0) | ||
809 | goto out_gunlock; | ||
810 | |||
795 | /* Check out the old directory */ | 811 | /* Check out the old directory */ |
796 | 812 | ||
797 | error = gfs2_unlink_ok(odip, &odentry->d_name, ip); | 813 | error = gfs2_unlink_ok(odip, &odentry->d_name, ip); |
@@ -805,6 +821,11 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
805 | if (error) | 821 | if (error) |
806 | goto out_gunlock; | 822 | goto out_gunlock; |
807 | 823 | ||
824 | if (nip->i_inode.i_nlink == 0) { | ||
825 | error = -EAGAIN; | ||
826 | goto out_gunlock; | ||
827 | } | ||
828 | |||
808 | if (S_ISDIR(nip->i_inode.i_mode)) { | 829 | if (S_ISDIR(nip->i_inode.i_mode)) { |
809 | if (nip->i_entries < 2) { | 830 | if (nip->i_entries < 2) { |
810 | if (gfs2_consist_inode(nip)) | 831 | if (gfs2_consist_inode(nip)) |
@@ -835,7 +856,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
835 | 856 | ||
836 | if (odip != ndip) { | 857 | if (odip != ndip) { |
837 | if (!ndip->i_inode.i_nlink) { | 858 | if (!ndip->i_inode.i_nlink) { |
838 | error = -EINVAL; | 859 | error = -ENOENT; |
839 | goto out_gunlock; | 860 | goto out_gunlock; |
840 | } | 861 | } |
841 | if (ndip->i_entries == (u32)-1) { | 862 | if (ndip->i_entries == (u32)-1) { |