diff options
Diffstat (limited to 'fs/ocfs2/export.c')
-rw-r--r-- | fs/ocfs2/export.c | 84 |
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 | ||
42 | struct ocfs2_inode_handle | 44 | struct 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)) | 110 | unlock_nfs_sync: |
64 | return (void *)inode; | 111 | ocfs2_nfs_sync_unlock(osb, 1); |
65 | 112 | ||
113 | check_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 | |||
129 | check_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 | ||
144 | bail: | ||
75 | mlog_exit_ptr(result); | 145 | mlog_exit_ptr(result); |
76 | return result; | 146 | return result; |
77 | } | 147 | } |