diff options
-rw-r--r-- | fs/freevxfs/vxfs.h | 7 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_extern.h | 1 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.c | 215 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.h | 7 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_super.c | 28 |
5 files changed, 116 insertions, 142 deletions
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h index 4b561ded5eb1..f52f259aacb3 100644 --- a/fs/freevxfs/vxfs.h +++ b/fs/freevxfs/vxfs.h | |||
@@ -272,13 +272,6 @@ enum { | |||
272 | #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) | 272 | #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) |
273 | #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) | 273 | #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) |
274 | 274 | ||
275 | |||
276 | /* | ||
277 | * Get filesystem private data from VFS inode. | ||
278 | */ | ||
279 | #define VXFS_INO(ip) \ | ||
280 | ((struct vxfs_inode_info *)(ip)->i_private) | ||
281 | |||
282 | /* | 275 | /* |
283 | * Get filesystem private data from VFS superblock. | 276 | * Get filesystem private data from VFS superblock. |
284 | */ | 277 | */ |
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 2ec8c0f27865..f5c428e21024 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h | |||
@@ -52,7 +52,6 @@ extern int vxfs_read_fshead(struct super_block *); | |||
52 | 52 | ||
53 | /* vxfs_inode.c */ | 53 | /* vxfs_inode.c */ |
54 | extern const struct address_space_operations vxfs_immed_aops; | 54 | extern const struct address_space_operations vxfs_immed_aops; |
55 | extern struct kmem_cache *vxfs_inode_cachep; | ||
56 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); | 55 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); |
57 | extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); | 56 | extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); |
58 | extern struct inode *vxfs_stiget(struct super_block *, ino_t); | 57 | extern struct inode *vxfs_stiget(struct super_block *, ino_t); |
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 7b5de83405f2..b718d0ff2e45 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c | |||
@@ -42,11 +42,6 @@ | |||
42 | #include "vxfs_extern.h" | 42 | #include "vxfs_extern.h" |
43 | 43 | ||
44 | 44 | ||
45 | struct kmem_cache *vxfs_inode_cachep; | ||
46 | |||
47 | static struct inode * vxfs_get_fake_inode(struct super_block *, | ||
48 | struct vxfs_inode_info *); | ||
49 | |||
50 | #ifdef DIAGNOSTIC | 45 | #ifdef DIAGNOSTIC |
51 | /* | 46 | /* |
52 | * Dump inode contents (partially). | 47 | * Dump inode contents (partially). |
@@ -70,9 +65,42 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) | |||
70 | } | 65 | } |
71 | #endif | 66 | #endif |
72 | 67 | ||
68 | /** | ||
69 | * vxfs_transmod - mode for a VxFS inode | ||
70 | * @vip: VxFS inode | ||
71 | * | ||
72 | * Description: | ||
73 | * vxfs_transmod returns a Linux mode_t for a given | ||
74 | * VxFS inode structure. | ||
75 | */ | ||
76 | static __inline__ umode_t | ||
77 | vxfs_transmod(struct vxfs_inode_info *vip) | ||
78 | { | ||
79 | umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; | ||
80 | |||
81 | if (VXFS_ISFIFO(vip)) | ||
82 | ret |= S_IFIFO; | ||
83 | if (VXFS_ISCHR(vip)) | ||
84 | ret |= S_IFCHR; | ||
85 | if (VXFS_ISDIR(vip)) | ||
86 | ret |= S_IFDIR; | ||
87 | if (VXFS_ISBLK(vip)) | ||
88 | ret |= S_IFBLK; | ||
89 | if (VXFS_ISLNK(vip)) | ||
90 | ret |= S_IFLNK; | ||
91 | if (VXFS_ISREG(vip)) | ||
92 | ret |= S_IFREG; | ||
93 | if (VXFS_ISSOC(vip)) | ||
94 | ret |= S_IFSOCK; | ||
95 | |||
96 | return (ret); | ||
97 | } | ||
98 | |||
73 | static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, | 99 | static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, |
74 | struct vxfs_inode_info *vip, struct vxfs_dinode *dip) | 100 | struct vxfs_inode_info *vip, struct vxfs_dinode *dip) |
75 | { | 101 | { |
102 | struct inode *inode = &vip->vfs_inode; | ||
103 | |||
76 | vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); | 104 | vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); |
77 | vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); | 105 | vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); |
78 | vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); | 106 | vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); |
@@ -96,6 +124,23 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, | |||
96 | 124 | ||
97 | /* don't endian swap the fields that differ by orgtype */ | 125 | /* don't endian swap the fields that differ by orgtype */ |
98 | memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); | 126 | memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); |
127 | |||
128 | inode->i_mode = vxfs_transmod(vip); | ||
129 | i_uid_write(inode, (uid_t)vip->vii_uid); | ||
130 | i_gid_write(inode, (gid_t)vip->vii_gid); | ||
131 | |||
132 | set_nlink(inode, vip->vii_nlink); | ||
133 | inode->i_size = vip->vii_size; | ||
134 | |||
135 | inode->i_atime.tv_sec = vip->vii_atime; | ||
136 | inode->i_ctime.tv_sec = vip->vii_ctime; | ||
137 | inode->i_mtime.tv_sec = vip->vii_mtime; | ||
138 | inode->i_atime.tv_nsec = 0; | ||
139 | inode->i_ctime.tv_nsec = 0; | ||
140 | inode->i_mtime.tv_nsec = 0; | ||
141 | |||
142 | inode->i_blocks = vip->vii_blocks; | ||
143 | inode->i_generation = vip->vii_gen; | ||
99 | } | 144 | } |
100 | 145 | ||
101 | /** | 146 | /** |
@@ -121,48 +166,48 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) | |||
121 | struct inode *inode; | 166 | struct inode *inode; |
122 | u_long block, offset; | 167 | u_long block, offset; |
123 | 168 | ||
169 | inode = new_inode(sbp); | ||
170 | if (!inode) | ||
171 | return NULL; | ||
172 | inode->i_ino = get_next_ino(); | ||
173 | |||
124 | block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); | 174 | block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); |
125 | offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); | 175 | offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); |
126 | bp = sb_bread(sbp, block); | 176 | bp = sb_bread(sbp, block); |
127 | 177 | ||
128 | if (bp && buffer_mapped(bp)) { | 178 | if (bp && buffer_mapped(bp)) { |
129 | struct vxfs_inode_info *vip; | 179 | struct vxfs_inode_info *vip = VXFS_INO(inode); |
130 | struct vxfs_dinode *dip; | 180 | struct vxfs_dinode *dip; |
131 | 181 | ||
132 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) | ||
133 | goto fail; | ||
134 | dip = (struct vxfs_dinode *)(bp->b_data + offset); | 182 | dip = (struct vxfs_dinode *)(bp->b_data + offset); |
135 | dip2vip_cpy(VXFS_SBI(sbp), vip, dip); | 183 | dip2vip_cpy(VXFS_SBI(sbp), vip, dip); |
184 | vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; | ||
136 | #ifdef DIAGNOSTIC | 185 | #ifdef DIAGNOSTIC |
137 | vxfs_dumpi(vip, ino); | 186 | vxfs_dumpi(vip, ino); |
138 | #endif | 187 | #endif |
139 | brelse(bp); | 188 | brelse(bp); |
140 | |||
141 | inode = vxfs_get_fake_inode(sbp, vip); | ||
142 | if (!inode) | ||
143 | kmem_cache_free(vxfs_inode_cachep, vip); | ||
144 | return inode; | 189 | return inode; |
145 | } | 190 | } |
146 | 191 | ||
147 | fail: | ||
148 | printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); | 192 | printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); |
149 | brelse(bp); | 193 | brelse(bp); |
194 | iput(inode); | ||
150 | return NULL; | 195 | return NULL; |
151 | } | 196 | } |
152 | 197 | ||
153 | /** | 198 | /** |
154 | * __vxfs_iget - generic find inode facility | 199 | * __vxfs_iget - generic find inode facility |
155 | * @sbp: VFS superblock | ||
156 | * @ino: inode number | ||
157 | * @ilistp: inode list | 200 | * @ilistp: inode list |
201 | * @vip: VxFS inode to fill in | ||
202 | * @ino: inode number | ||
158 | * | 203 | * |
159 | * Description: | 204 | * Description: |
160 | * Search the for inode number @ino in the filesystem | 205 | * Search the for inode number @ino in the filesystem |
161 | * described by @sbp. Use the specified inode table (@ilistp). | 206 | * described by @sbp. Use the specified inode table (@ilistp). |
162 | * Returns the matching inode on success, else an error code. | 207 | * Returns the matching inode on success, else an error code. |
163 | */ | 208 | */ |
164 | static struct vxfs_inode_info * | 209 | static int |
165 | __vxfs_iget(ino_t ino, struct inode *ilistp) | 210 | __vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) |
166 | { | 211 | { |
167 | struct page *pp; | 212 | struct page *pp; |
168 | u_long offset; | 213 | u_long offset; |
@@ -171,28 +216,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp) | |||
171 | pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); | 216 | pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); |
172 | 217 | ||
173 | if (!IS_ERR(pp)) { | 218 | if (!IS_ERR(pp)) { |
174 | struct vxfs_inode_info *vip; | ||
175 | struct vxfs_dinode *dip; | 219 | struct vxfs_dinode *dip; |
176 | caddr_t kaddr = (char *)page_address(pp); | 220 | caddr_t kaddr = (char *)page_address(pp); |
177 | 221 | ||
178 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) | ||
179 | goto fail; | ||
180 | dip = (struct vxfs_dinode *)(kaddr + offset); | 222 | dip = (struct vxfs_dinode *)(kaddr + offset); |
181 | dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); | 223 | dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); |
224 | vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; | ||
182 | #ifdef DIAGNOSTIC | 225 | #ifdef DIAGNOSTIC |
183 | vxfs_dumpi(vip, ino); | 226 | vxfs_dumpi(vip, ino); |
184 | #endif | 227 | #endif |
185 | vxfs_put_page(pp); | 228 | vxfs_put_page(pp); |
186 | return (vip); | 229 | return 0; |
187 | } | 230 | } |
188 | 231 | ||
189 | printk(KERN_WARNING "vxfs: error on page %p\n", pp); | 232 | printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", |
190 | return ERR_CAST(pp); | 233 | pp, (unsigned long)ino); |
191 | 234 | return PTR_ERR(pp); | |
192 | fail: | ||
193 | printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); | ||
194 | vxfs_put_page(pp); | ||
195 | return ERR_PTR(-ENOMEM); | ||
196 | } | 235 | } |
197 | 236 | ||
198 | /** | 237 | /** |
@@ -208,104 +247,21 @@ fail: | |||
208 | struct inode * | 247 | struct inode * |
209 | vxfs_stiget(struct super_block *sbp, ino_t ino) | 248 | vxfs_stiget(struct super_block *sbp, ino_t ino) |
210 | { | 249 | { |
211 | struct vxfs_inode_info *vip; | ||
212 | struct inode *inode; | 250 | struct inode *inode; |
251 | int error; | ||
213 | 252 | ||
214 | vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); | 253 | inode = new_inode(sbp); |
215 | if (IS_ERR(vip)) | ||
216 | return NULL; | ||
217 | inode = vxfs_get_fake_inode(sbp, vip); | ||
218 | if (!inode) | 254 | if (!inode) |
219 | kmem_cache_free(vxfs_inode_cachep, vip); | 255 | return NULL; |
220 | return inode; | 256 | inode->i_ino = get_next_ino(); |
221 | } | ||
222 | |||
223 | /** | ||
224 | * vxfs_transmod - mode for a VxFS inode | ||
225 | * @vip: VxFS inode | ||
226 | * | ||
227 | * Description: | ||
228 | * vxfs_transmod returns a Linux mode_t for a given | ||
229 | * VxFS inode structure. | ||
230 | */ | ||
231 | static __inline__ umode_t | ||
232 | vxfs_transmod(struct vxfs_inode_info *vip) | ||
233 | { | ||
234 | umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; | ||
235 | |||
236 | if (VXFS_ISFIFO(vip)) | ||
237 | ret |= S_IFIFO; | ||
238 | if (VXFS_ISCHR(vip)) | ||
239 | ret |= S_IFCHR; | ||
240 | if (VXFS_ISDIR(vip)) | ||
241 | ret |= S_IFDIR; | ||
242 | if (VXFS_ISBLK(vip)) | ||
243 | ret |= S_IFBLK; | ||
244 | if (VXFS_ISLNK(vip)) | ||
245 | ret |= S_IFLNK; | ||
246 | if (VXFS_ISREG(vip)) | ||
247 | ret |= S_IFREG; | ||
248 | if (VXFS_ISSOC(vip)) | ||
249 | ret |= S_IFSOCK; | ||
250 | |||
251 | return (ret); | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * vxfs_iinit- helper to fill inode fields | ||
256 | * @ip: VFS inode | ||
257 | * @vip: VxFS inode | ||
258 | * | ||
259 | * Description: | ||
260 | * vxfs_instino is a helper function to fill in all relevant | ||
261 | * fields in @ip from @vip. | ||
262 | */ | ||
263 | static void | ||
264 | vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) | ||
265 | { | ||
266 | |||
267 | ip->i_mode = vxfs_transmod(vip); | ||
268 | i_uid_write(ip, (uid_t)vip->vii_uid); | ||
269 | i_gid_write(ip, (gid_t)vip->vii_gid); | ||
270 | |||
271 | set_nlink(ip, vip->vii_nlink); | ||
272 | ip->i_size = vip->vii_size; | ||
273 | |||
274 | ip->i_atime.tv_sec = vip->vii_atime; | ||
275 | ip->i_ctime.tv_sec = vip->vii_ctime; | ||
276 | ip->i_mtime.tv_sec = vip->vii_mtime; | ||
277 | ip->i_atime.tv_nsec = 0; | ||
278 | ip->i_ctime.tv_nsec = 0; | ||
279 | ip->i_mtime.tv_nsec = 0; | ||
280 | |||
281 | ip->i_blocks = vip->vii_blocks; | ||
282 | ip->i_generation = vip->vii_gen; | ||
283 | |||
284 | ip->i_private = vip; | ||
285 | |||
286 | } | ||
287 | |||
288 | /** | ||
289 | * vxfs_get_fake_inode - get fake inode structure | ||
290 | * @sbp: filesystem superblock | ||
291 | * @vip: fspriv inode | ||
292 | * | ||
293 | * Description: | ||
294 | * vxfs_fake_inode gets a fake inode (not in the inode hash) for a | ||
295 | * superblock, vxfs_inode pair. | ||
296 | * Returns the filled VFS inode. | ||
297 | */ | ||
298 | static struct inode * | ||
299 | vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) | ||
300 | { | ||
301 | struct inode *ip = NULL; | ||
302 | 257 | ||
303 | if ((ip = new_inode(sbp))) { | 258 | error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); |
304 | ip->i_ino = get_next_ino(); | 259 | if (error) { |
305 | vxfs_iinit(ip, vip); | 260 | iput(inode); |
306 | ip->i_mapping->a_ops = &vxfs_aops; | 261 | return NULL; |
307 | } | 262 | } |
308 | return (ip); | 263 | |
264 | return inode; | ||
309 | } | 265 | } |
310 | 266 | ||
311 | /** | 267 | /** |
@@ -323,6 +279,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
323 | struct vxfs_inode_info *vip; | 279 | struct vxfs_inode_info *vip; |
324 | const struct address_space_operations *aops; | 280 | const struct address_space_operations *aops; |
325 | struct inode *ip; | 281 | struct inode *ip; |
282 | int error; | ||
326 | 283 | ||
327 | ip = iget_locked(sbp, ino); | 284 | ip = iget_locked(sbp, ino); |
328 | if (!ip) | 285 | if (!ip) |
@@ -330,14 +287,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
330 | if (!(ip->i_state & I_NEW)) | 287 | if (!(ip->i_state & I_NEW)) |
331 | return ip; | 288 | return ip; |
332 | 289 | ||
333 | vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); | 290 | vip = VXFS_INO(ip); |
334 | if (IS_ERR(vip)) { | 291 | error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); |
292 | if (error) { | ||
335 | iget_failed(ip); | 293 | iget_failed(ip); |
336 | return ERR_CAST(vip); | 294 | return ERR_PTR(error); |
337 | } | 295 | } |
338 | 296 | ||
339 | vxfs_iinit(ip, vip); | ||
340 | |||
341 | if (VXFS_ISIMMED(vip)) | 297 | if (VXFS_ISIMMED(vip)) |
342 | aops = &vxfs_immed_aops; | 298 | aops = &vxfs_immed_aops; |
343 | else | 299 | else |
@@ -368,12 +324,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
368 | return ip; | 324 | return ip; |
369 | } | 325 | } |
370 | 326 | ||
371 | static void vxfs_i_callback(struct rcu_head *head) | ||
372 | { | ||
373 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
374 | kmem_cache_free(vxfs_inode_cachep, inode->i_private); | ||
375 | } | ||
376 | |||
377 | /** | 327 | /** |
378 | * vxfs_evict_inode - remove inode from main memory | 328 | * vxfs_evict_inode - remove inode from main memory |
379 | * @ip: inode to discard. | 329 | * @ip: inode to discard. |
@@ -387,5 +337,4 @@ vxfs_evict_inode(struct inode *ip) | |||
387 | { | 337 | { |
388 | truncate_inode_pages_final(&ip->i_data); | 338 | truncate_inode_pages_final(&ip->i_data); |
389 | clear_inode(ip); | 339 | clear_inode(ip); |
390 | call_rcu(&ip->i_rcu, vxfs_i_callback); | ||
391 | } | 340 | } |
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h index 93d01148e5db..ad6b77c0ebcc 100644 --- a/fs/freevxfs/vxfs_inode.h +++ b/fs/freevxfs/vxfs_inode.h | |||
@@ -151,6 +151,8 @@ struct vxfs_dinode { | |||
151 | * The inode as represented in the main memory. | 151 | * The inode as represented in the main memory. |
152 | */ | 152 | */ |
153 | struct vxfs_inode_info { | 153 | struct vxfs_inode_info { |
154 | struct inode vfs_inode; | ||
155 | |||
154 | __u32 vii_mode; | 156 | __u32 vii_mode; |
155 | __u32 vii_nlink; /* Link count */ | 157 | __u32 vii_nlink; /* Link count */ |
156 | __u32 vii_uid; /* UID */ | 158 | __u32 vii_uid; /* UID */ |
@@ -183,4 +185,9 @@ struct vxfs_inode_info { | |||
183 | #define vii_ext4 vii_org.ext4 | 185 | #define vii_ext4 vii_org.ext4 |
184 | #define vii_typed vii_org.typed | 186 | #define vii_typed vii_org.typed |
185 | 187 | ||
188 | static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode) | ||
189 | { | ||
190 | return container_of(inode, struct vxfs_inode_info, vfs_inode); | ||
191 | } | ||
192 | |||
186 | #endif /* _VXFS_INODE_H_ */ | 193 | #endif /* _VXFS_INODE_H_ */ |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 40125cc825f2..dfa775ef4d1d 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -52,6 +52,8 @@ MODULE_AUTHOR("Christoph Hellwig"); | |||
52 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); | 52 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); |
53 | MODULE_LICENSE("Dual BSD/GPL"); | 53 | MODULE_LICENSE("Dual BSD/GPL"); |
54 | 54 | ||
55 | static struct kmem_cache *vxfs_inode_cachep; | ||
56 | |||
55 | /** | 57 | /** |
56 | * vxfs_put_super - free superblock resources | 58 | * vxfs_put_super - free superblock resources |
57 | * @sbp: VFS superblock. | 59 | * @sbp: VFS superblock. |
@@ -117,7 +119,31 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) | |||
117 | return 0; | 119 | return 0; |
118 | } | 120 | } |
119 | 121 | ||
122 | static struct inode *vxfs_alloc_inode(struct super_block *sb) | ||
123 | { | ||
124 | struct vxfs_inode_info *vi; | ||
125 | |||
126 | vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL); | ||
127 | if (!vi) | ||
128 | return NULL; | ||
129 | return &vi->vfs_inode; | ||
130 | } | ||
131 | |||
132 | static void vxfs_i_callback(struct rcu_head *head) | ||
133 | { | ||
134 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
135 | |||
136 | kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode)); | ||
137 | } | ||
138 | |||
139 | static void vxfs_destroy_inode(struct inode *inode) | ||
140 | { | ||
141 | call_rcu(&inode->i_rcu, vxfs_i_callback); | ||
142 | } | ||
143 | |||
120 | static const struct super_operations vxfs_super_ops = { | 144 | static const struct super_operations vxfs_super_ops = { |
145 | .alloc_inode = vxfs_alloc_inode, | ||
146 | .destroy_inode = vxfs_destroy_inode, | ||
121 | .evict_inode = vxfs_evict_inode, | 147 | .evict_inode = vxfs_evict_inode, |
122 | .put_super = vxfs_put_super, | 148 | .put_super = vxfs_put_super, |
123 | .statfs = vxfs_statfs, | 149 | .statfs = vxfs_statfs, |
@@ -206,6 +232,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) | |||
206 | goto out; | 232 | goto out; |
207 | } | 233 | } |
208 | 234 | ||
235 | sbp->s_op = &vxfs_super_ops; | ||
209 | sbp->s_fs_info = infp; | 236 | sbp->s_fs_info = infp; |
210 | 237 | ||
211 | if (!vxfs_try_sb_magic(sbp, silent, 1, | 238 | if (!vxfs_try_sb_magic(sbp, silent, 1, |
@@ -256,7 +283,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) | |||
256 | goto out; | 283 | goto out; |
257 | } | 284 | } |
258 | 285 | ||
259 | sbp->s_op = &vxfs_super_ops; | ||
260 | root = vxfs_iget(sbp, VXFS_ROOT_INO); | 286 | root = vxfs_iget(sbp, VXFS_ROOT_INO); |
261 | if (IS_ERR(root)) { | 287 | if (IS_ERR(root)) { |
262 | ret = PTR_ERR(root); | 288 | ret = PTR_ERR(root); |