@@ -155,7 +155,6 @@ struct vxfs_sb {
*/
};
-
/*
* In core superblock filesystem private data for VxFS.
*/
@@ -272,13 +271,6 @@ enum {
#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
-
-/*
- * Get filesystem private data from VFS inode.
- */
-#define VXFS_INO(ip) \
- ((struct vxfs_inode_info *)(ip)->i_private)
-
/*
* Get filesystem private data from VFS superblock.
*/
@@ -99,8 +99,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
brelse(buf);
return bno;
- } else
- printk(KERN_WARNING "no matching indir?");
+ } else {
+ printk(KERN_WARNING "%s:%d no matching indir?\n", __func__, __LINE__);
+ }
return 0;
@@ -55,15 +55,18 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
/* vxfs_inode.c */
extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache *vxfs_inode_cachep;
extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
-extern struct inode * vxfs_get_fake_inode(struct super_block *,
- struct vxfs_inode_info *);
-extern void vxfs_put_fake_inode(struct inode *);
-extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t);
-extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
-extern struct inode * vxfs_iget(struct super_block *, ino_t);
-extern void vxfs_evict_inode(struct inode *);
+
+extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
+extern struct inode *vxfs_stiget(struct super_block *, ino_t);
+extern struct inode *vxfs_iget(struct super_block *, ino_t);
+extern void vxfs_evict_inode(struct inode *);
+
+extern void vxfs_destroy_inode(struct inode *ip);
+extern int vxfs_ii_cache_init(void);
+extern void vxfs_ii_cache_destroy(void);
+extern struct inode *vxfs_inode_alloc(struct super_block *sb);
+
/* vxfs_lookup.c */
extern const struct inode_operations vxfs_dir_inode_ops;
@@ -86,6 +86,9 @@ vxfs_getfsh(struct inode *ip, int which)
memcpy(fhp, bp->b_data, sizeof(*fhp));
put_bh(bp);
+#ifdef DIAGNOSTIC
+ vxfs_dumpfsh(fhp);
+#endif
return (fhp);
}
out:
@@ -93,6 +96,15 @@ out:
return NULL;
}
+static inline void inode_err_put(struct inode **i)
+{
+ struct inode *i2 = *i;
+
+ if (i2 && !IS_ERR(i2))
+ iput(i2);
+ *i = NULL;
+}
+
/**
* vxfs_read_fshead - read the fileset headers
* @sbp: superblock to which the fileset belongs
@@ -107,98 +119,73 @@ int
vxfs_read_fshead(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
- struct vxfs_fsh *pfp, *sfp;
- struct vxfs_inode_info *vip, *tip;
+ struct vxfs_fsh *pfp = NULL;
+ struct vxfs_fsh *sfp = NULL;
+ struct inode *ip1;
+ struct inode *ip2;
- vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
- if (!vip) {
+ infp->vsi_fship = ip1 = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
+ if (!ip1 || IS_ERR(ip1)) {
printk(KERN_ERR "vxfs: unable to read fsh inode\n");
return -EINVAL;
}
- if (!VXFS_ISFSH(vip)) {
+
+ if (!VXFS_ISFSH(VXFS_INO(ip1))) {
printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
- vip->vii_mode & VXFS_TYPE_MASK);
- goto out_free_fship;
+ VXFS_INO(ip1)->vii_mode & VXFS_TYPE_MASK);
+ goto out_err;
}
-
#ifdef DIAGNOSTIC
printk("vxfs: fsh inode dump:\n");
- vxfs_dumpi(vip, infp->vsi_fshino);
+ vxfs_dumpi(VXFS_INO(ip1), infp->vsi_fshino);
#endif
- infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
- if (!infp->vsi_fship) {
- printk(KERN_ERR "vxfs: unable to get fsh inode\n");
- goto out_free_fship;
- }
-
sfp = vxfs_getfsh(infp->vsi_fship, 0);
if (!sfp) {
printk(KERN_ERR "vxfs: unable to get structural fsh\n");
- goto out_iput_fship;
- }
-
-#ifdef DIAGNOSTIC
- vxfs_dumpfsh(sfp);
-#endif
+ goto out_err;
+ }
pfp = vxfs_getfsh(infp->vsi_fship, 1);
if (!pfp) {
printk(KERN_ERR "vxfs: unable to get primary fsh\n");
- goto out_free_sfp;
+ goto out_err;
}
-#ifdef DIAGNOSTIC
- vxfs_dumpfsh(pfp);
-#endif
-
- tip = vxfs_blkiget(sbp, infp->vsi_iext,
- fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
- if (!tip)
- goto out_free_pfp;
-
- infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
- if (!infp->vsi_stilist) {
- printk(KERN_ERR "vxfs: unable to get structural list inode\n");
- kfree(tip);
- goto out_free_pfp;
+ infp->vsi_stilist =
+ ip2 = vxfs_blkiget(sbp, infp->vsi_iext,
+ fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
+ if (!ip2 || IS_ERR(ip2)) {
+ goto out_err;
}
+
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
- VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK);
- goto out_iput_stilist;
+ VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK);
+ goto out_err;
}
- tip = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
- if (!tip)
- goto out_iput_stilist;
- infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
- if (!infp->vsi_ilist) {
+ infp->vsi_ilist = ip2 = vxfs_stiget(sbp,
+ fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
+ if (!ip2 || IS_ERR(ip2)) {
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
- kfree(tip);
- goto out_iput_stilist;
+ goto out_err;
}
+
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
- goto out_iput_ilist;
+ goto out_err;
}
-
+ kfree(pfp);
+ kfree(sfp);
return 0;
-
- out_iput_ilist:
- iput(infp->vsi_ilist);
- out_iput_stilist:
- iput(infp->vsi_stilist);
- out_free_pfp:
+out_err:
+ inode_err_put(&infp->vsi_fship);
+ inode_err_put(&infp->vsi_ilist);
+ inode_err_put(&infp->vsi_stilist);
kfree(pfp);
- out_free_sfp:
- kfree(sfp);
- out_iput_fship:
- iput(infp->vsi_fship);
- return -EINVAL;
- out_free_fship:
- kfree(vip);
+ kfree(sfp);
return -EINVAL;
}
@@ -41,7 +41,8 @@
#include "vxfs_extern.h"
-struct kmem_cache *vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
+static void vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip);
#ifdef DIAGNOSTIC
@@ -111,35 +112,41 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
* buffercache. This function should not be used outside the
* read_super() method, otherwise the data may be incoherent.
*/
-struct vxfs_inode_info *
+struct inode *
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
{
struct buffer_head *bp;
u_long block, offset;
+ struct inode *ip;
block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
+ ip = new_inode(sbp);
+ if (!ip)
+ return ERR_PTR(-ENOMEM);
+
bp = sb_bread(sbp, block);
+ ip->i_ino = get_next_ino();
+ ip->i_mapping->a_ops = &vxfs_aops;
if (bp && buffer_mapped(bp)) {
- struct vxfs_inode_info *vip;
+ struct vxfs_inode_info *vip = VXFS_INO(ip);
struct vxfs_dinode *dip;
- if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
- goto fail;
dip = (struct vxfs_dinode *)(bp->b_data + offset);
dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
+ vxfs_iinit(ip, vip);
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
- brelse(bp);
- return (vip);
+ } else {
+ printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
+ iput(ip);
+ ip = NULL;
}
-fail:
- printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
brelse(bp);
- return NULL;
+ return ip;
}
/**
@@ -154,21 +161,18 @@ fail:
* Returns the matching VxFS inode on success, else an error code.
*/
static struct vxfs_inode_info *
-__vxfs_iget(ino_t ino, struct inode *ilistp)
+__vxfs_iget(struct inode *ip, struct inode *ilistp, ino_t ino)
{
- struct page *pp;
- u_long offset;
+ struct page *pp;
+ u_long offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
- offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
if (!IS_ERR(pp)) {
- struct vxfs_inode_info *vip;
+ struct vxfs_inode_info *vip = VXFS_INO(ip);
struct vxfs_dinode *dip;
caddr_t kaddr = (char *)page_address(pp);
- if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
- goto fail;
dip = (struct vxfs_dinode *)(kaddr + offset);
dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
#ifdef DIAGNOSTIC
@@ -180,11 +184,6 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
printk(KERN_WARNING "vxfs: error on page %p\n", pp);
return ERR_CAST(pp);
-
-fail:
- printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
- vxfs_put_page(pp);
- return ERR_PTR(-ENOMEM);
}
/**
@@ -197,13 +196,24 @@ fail:
* the structural inode list.
* Returns the matching VxFS inode on success, else a NULL pointer.
*/
-struct vxfs_inode_info *
+struct inode *
vxfs_stiget(struct super_block *sbp, ino_t ino)
{
- struct vxfs_inode_info *vip;
+ struct inode *ip = new_inode(sbp);
+ struct vxfs_inode_info *ii;
- vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
- return IS_ERR(vip) ? NULL : vip;
+ if (!ip)
+ return NULL;
+
+ ip->i_ino = get_next_ino();
+ ip->i_mapping->a_ops = &vxfs_aops;
+ ii = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_stilist, ino);
+ if (IS_ERR(ii)) {
+ iput(ip);
+ } else {
+ vxfs_iinit(ip, ii);
+ }
+ return IS_ERR(ii) ? NULL : ip;
}
/**
@@ -271,41 +281,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
}
-/**
- * vxfs_get_fake_inode - get fake inode structure
- * @sbp: filesystem superblock
- * @vip: fspriv inode
- *
- * Description:
- * vxfs_fake_inode gets a fake inode (not in the inode hash) for a
- * superblock, vxfs_inode pair.
- * Returns the filled VFS inode.
- */
-struct inode *
-vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
-{
- struct inode *ip = NULL;
-
- if ((ip = new_inode(sbp))) {
- ip->i_ino = get_next_ino();
- vxfs_iinit(ip, vip);
- ip->i_mapping->a_ops = &vxfs_aops;
- }
- return (ip);
-}
-
-/**
- * vxfs_put_fake_inode - free faked inode
- * *ip: VFS inode
- *
- * Description:
- * vxfs_put_fake_inode frees all data associated with @ip.
- */
-void
-vxfs_put_fake_inode(struct inode *ip)
-{
- iput(ip);
-}
/**
* vxfs_iget - get an inode
@@ -329,7 +304,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
if (!(ip->i_state & I_NEW))
return ip;
- vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
+ vip = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_ilist, ino);
if (IS_ERR(vip)) {
iget_failed(ip);
return ERR_CAST(vip);
@@ -367,21 +342,65 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
static void vxfs_i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(vxfs_inode_cachep, inode->i_private);
+ struct vxfs_vfs_inode *i = container_of(inode, struct vxfs_vfs_inode, ino);
+
+ kmem_cache_free(vxfs_inode_cachep, i);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+ call_rcu(&ip->i_rcu, vxfs_i_callback);
}
/**
- * vxfs_evict_inode - remove inode from main memory
+ * vxfs_evict_inode - commit inode buffers if needed, may delete on-disk inode.
* @ip: inode to discard.
*
* Description:
- * vxfs_evict_inode() is called on the final iput and frees the private
- * inode area.
+ * vxfs_evict_inode() may be called on the final iput.
*/
void
vxfs_evict_inode(struct inode *ip)
{
truncate_inode_pages_final(&ip->i_data);
+ invalidate_inode_buffers(ip);
clear_inode(ip);
- call_rcu(&ip->i_rcu, vxfs_i_callback);
}
+
+
+
+
+struct inode *vxfs_inode_alloc(struct super_block *sb)
+{
+ struct vxfs_vfs_inode *i = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
+
+ return i ? &i->ino : NULL;
+}
+
+static void vxfs_inode_constructor(void *ptr)
+{
+ struct vxfs_vfs_inode *i = (struct vxfs_vfs_inode *) ptr;
+
+ inode_init_once(&i->ino);
+}
+
+int vxfs_ii_cache_init(void)
+{
+ vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+ sizeof(struct vxfs_vfs_inode), 0,
+ SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, vxfs_inode_constructor);
+
+ return vxfs_inode_cachep ? 0 : -ENOMEM;
+}
+
+
+void vxfs_ii_cache_destroy(void)
+{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
+ kmem_cache_destroy(vxfs_inode_cachep);
+}
+
@@ -37,7 +37,6 @@
* inodes of the Veritas Filesystem.
*/
-
#define VXFS_ISIZE 0x100 /* Inode size */
#define VXFS_NDADDR 10 /* Number of direct addrs in inode */
@@ -178,6 +177,12 @@ struct vxfs_inode_info {
} vii_org;
};
+struct vxfs_vfs_inode {
+ struct inode ino;
+ struct vxfs_inode_info cpufs_ino;
+};
+
+
#define vii_rdev vii_ftarea.rdev
#define vii_dotdot vii_ftarea.dotdot
@@ -185,4 +190,13 @@ struct vxfs_inode_info {
#define vii_ext4 vii_org.ext4
#define vii_typed vii_org.typed
+/*
+ * Get filesystem private data from VFS inode.
+ */
+static inline struct vxfs_inode_info *VXFS_INO(struct inode *i)
+{
+ return &(container_of(i, struct vxfs_vfs_inode, ino))->cpufs_ino;
+}
+
+
#endif /* _VXFS_INODE_H_ */
@@ -59,6 +59,8 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
static int vxfs_remount(struct super_block *, int *, char *);
static const struct super_operations vxfs_super_ops = {
+ .alloc_inode = vxfs_inode_alloc,
+ .destroy_inode = vxfs_destroy_inode,
.evict_inode = vxfs_evict_inode,
.put_super = vxfs_put_super,
.statfs = vxfs_statfs,
@@ -79,9 +81,9 @@ vxfs_put_super(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
- vxfs_put_fake_inode(infp->vsi_fship);
- vxfs_put_fake_inode(infp->vsi_ilist);
- vxfs_put_fake_inode(infp->vsi_stilist);
+ iput(infp->vsi_fship);
+ iput(infp->vsi_ilist);
+ iput(infp->vsi_stilist);
brelse(infp->vsi_bp);
kfree(infp);
@@ -253,17 +255,18 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
goto out;
}
+
if (vxfs_read_olt(sbp, bsize)) {
printk(KERN_WARNING "vxfs: unable to read olt\n");
goto out;
}
+ sbp->s_op = &vxfs_super_ops;
if (vxfs_read_fshead(sbp)) {
printk(KERN_WARNING "vxfs: unable to read fshead\n");
goto out;
}
- sbp->s_op = &vxfs_super_ops;
root = vxfs_iget(sbp, VXFS_ROOT_INO);
if (IS_ERR(root)) {
ret = PTR_ERR(root);
@@ -278,9 +281,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
return 0;
out_free_ilist:
- vxfs_put_fake_inode(infp->vsi_fship);
- vxfs_put_fake_inode(infp->vsi_ilist);
- vxfs_put_fake_inode(infp->vsi_stilist);
+ iput(infp->vsi_fship);
+ iput(infp->vsi_ilist);
+ iput(infp->vsi_stilist);
out:
brelse(infp->vsi_bp);
kfree(infp);
@@ -309,29 +312,23 @@ MODULE_ALIAS("vxfs");
static int __init
vxfs_init(void)
{
- int rv;
+ int rc = vxfs_ii_cache_init();
- vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
- sizeof(struct vxfs_inode_info), 0,
- SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
- if (!vxfs_inode_cachep)
- return -ENOMEM;
- rv = register_filesystem(&vxfs_fs_type);
- if (rv < 0)
- kmem_cache_destroy(vxfs_inode_cachep);
- return rv;
+ if (!rc) {
+ rc = register_filesystem(&vxfs_fs_type);
+ if (rc < 0)
+ vxfs_ii_cache_destroy();
+ }
+ printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __func__, __DATE__, __TIME__, rc);
+
+ return rc;
}
static void __exit
vxfs_cleanup(void)
{
unregister_filesystem(&vxfs_fs_type);
- /*
- * Make sure all delayed rcu free inodes are flushed before we
- * destroy cache.
- */
- rcu_barrier();
- kmem_cache_destroy(vxfs_inode_cachep);
+ vxfs_ii_cache_destroy();
}
module_init(vxfs_init);