aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/export.c')
-rw-r--r--fs/ocfs2/export.c84
1 files changed, 77 insertions, 7 deletions
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 2f27b332d8b3..de3da8eb558c 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -31,6 +31,7 @@
31 31
32#include "ocfs2.h" 32#include "ocfs2.h"
33 33
34#include "alloc.h"
34#include "dir.h" 35#include "dir.h"
35#include "dlmglue.h" 36#include "dlmglue.h"
36#include "dcache.h" 37#include "dcache.h"
@@ -38,6 +39,7 @@
38#include "inode.h" 39#include "inode.h"
39 40
40#include "buffer_head_io.h" 41#include "buffer_head_io.h"
42#include "suballoc.h"
41 43
42struct ocfs2_inode_handle 44struct ocfs2_inode_handle
43{ 45{
@@ -49,29 +51,97 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
49 struct ocfs2_inode_handle *handle) 51 struct ocfs2_inode_handle *handle)
50{ 52{
51 struct inode *inode; 53 struct inode *inode;
54 struct ocfs2_super *osb = OCFS2_SB(sb);
55 u64 blkno = handle->ih_blkno;
56 int status, set;
52 struct dentry *result; 57 struct dentry *result;
53 58
54 mlog_entry("(0x%p, 0x%p)\n", sb, handle); 59 mlog_entry("(0x%p, 0x%p)\n", sb, handle);
55 60
56 if (handle->ih_blkno == 0) { 61 if (blkno == 0) {
57 mlog_errno(-ESTALE); 62 mlog(0, "nfs wants inode with blkno: 0\n");
58 return ERR_PTR(-ESTALE); 63 result = ERR_PTR(-ESTALE);
64 goto bail;
65 }
66
67 inode = ocfs2_ilookup(sb, blkno);
68 /*
69 * If the inode exists in memory, we only need to check it's
70 * generation number
71 */
72 if (inode)
73 goto check_gen;
74
75 /*
76 * This will synchronize us against ocfs2_delete_inode() on
77 * all nodes
78 */
79 status = ocfs2_nfs_sync_lock(osb, 1);
80 if (status < 0) {
81 mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d\n", status);
82 goto check_err;
83 }
84
85 status = ocfs2_test_inode_bit(osb, blkno, &set);
86 if (status < 0) {
87 if (status == -EINVAL) {
88 /*
89 * The blkno NFS gave us doesn't even show up
90 * as an inode, we return -ESTALE to be
91 * nice
92 */
93 mlog(0, "test inode bit failed %d\n", status);
94 status = -ESTALE;
95 } else {
96 mlog(ML_ERROR, "test inode bit failed %d\n", status);
97 }
98 goto unlock_nfs_sync;
99 }
100
101 /* If the inode allocator bit is clear, this inode must be stale */
102 if (!set) {
103 mlog(0, "inode %llu suballoc bit is clear\n", blkno);
104 status = -ESTALE;
105 goto unlock_nfs_sync;
59 } 106 }
60 107
61 inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno, 0, 0); 108 inode = ocfs2_iget(osb, blkno, 0, 0);
62 109
63 if (IS_ERR(inode)) 110unlock_nfs_sync:
64 return (void *)inode; 111 ocfs2_nfs_sync_unlock(osb, 1);
65 112
113check_err:
114 if (status < 0) {
115 if (status == -ESTALE) {
116 mlog(0, "stale inode ino: %llu generation: %u\n",
117 blkno, handle->ih_generation);
118 }
119 result = ERR_PTR(status);
120 goto bail;
121 }
122
123 if (IS_ERR(inode)) {
124 mlog_errno(PTR_ERR(inode));
125 result = (void *)inode;
126 goto bail;
127 }
128
129check_gen:
66 if (handle->ih_generation != inode->i_generation) { 130 if (handle->ih_generation != inode->i_generation) {
67 iput(inode); 131 iput(inode);
68 return ERR_PTR(-ESTALE); 132 mlog(0, "stale inode ino: %llu generation: %u\n", blkno,
133 handle->ih_generation);
134 result = ERR_PTR(-ESTALE);
135 goto bail;
69 } 136 }
70 137
71 result = d_obtain_alias(inode); 138 result = d_obtain_alias(inode);
72 if (!IS_ERR(result)) 139 if (!IS_ERR(result))
73 result->d_op = &ocfs2_dentry_ops; 140 result->d_op = &ocfs2_dentry_ops;
141 else
142 mlog_errno(PTR_ERR(result));
74 143
144bail:
75 mlog_exit_ptr(result); 145 mlog_exit_ptr(result);
76 return result; 146 return result;
77} 147}