summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/freevxfs/vxfs.h7
-rw-r--r--fs/freevxfs/vxfs_extern.h1
-rw-r--r--fs/freevxfs/vxfs_inode.c215
-rw-r--r--fs/freevxfs/vxfs_inode.h7
-rw-r--r--fs/freevxfs/vxfs_super.c28
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 */
54extern const struct address_space_operations vxfs_immed_aops; 54extern const struct address_space_operations vxfs_immed_aops;
55extern struct kmem_cache *vxfs_inode_cachep;
56extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); 55extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
57extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); 56extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
58extern struct inode *vxfs_stiget(struct super_block *, ino_t); 57extern 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
45struct kmem_cache *vxfs_inode_cachep;
46
47static 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 */
76static __inline__ umode_t
77vxfs_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
73static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, 99static 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
147fail:
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 */
164static struct vxfs_inode_info * 209static 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);
192fail:
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:
208struct inode * 247struct inode *
209vxfs_stiget(struct super_block *sbp, ino_t ino) 248vxfs_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 */
231static __inline__ umode_t
232vxfs_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 */
263static void
264vxfs_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 */
298static struct inode *
299vxfs_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
371static 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 */
153struct vxfs_inode_info { 153struct 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
188static 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");
52MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); 52MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
53MODULE_LICENSE("Dual BSD/GPL"); 53MODULE_LICENSE("Dual BSD/GPL");
54 54
55static 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
122static 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
132static 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
139static void vxfs_destroy_inode(struct inode *inode)
140{
141 call_rcu(&inode->i_rcu, vxfs_i_callback);
142}
143
120static const struct super_operations vxfs_super_ops = { 144static 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);