summaryrefslogtreecommitdiffstats
path: root/fs/freevxfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-06-01 02:44:45 -0400
committerChristoph Hellwig <hch@lst.de>2016-06-01 03:23:24 -0400
commit2f137e31e07118bead0d17ccc89b0e71aec74732 (patch)
treef7ac2621f116e5290730730b5f58db991acb65fc /fs/freevxfs
parentf2bf2c70488145c961306b873c75147048db743d (diff)
freevxfs: implement ->alloc_inode and ->destroy_inode
This driver predates those methods and was trying to be clever allocating it's own private data. Switch to the generic scheme used by other file systems. Based on an earlier patch from Krzysztof Błaszkowski <kb@sysmikro.com.pl>. Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/freevxfs')
-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);