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 { #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. */ 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 *); /* 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_blkiget(struct super_block *, u_long, ino_t); 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 @@ #include "vxfs_extern.h" -struct kmem_cache *vxfs_inode_cachep; - -static struct inode * vxfs_get_fake_inode(struct super_block *, - struct vxfs_inode_info *); - #ifdef DIAGNOSTIC /* * Dump inode contents (partially). @@ -70,9 +65,42 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) } #endif +/** + * vxfs_transmod - mode for a VxFS inode + * @vip: VxFS inode + * + * Description: + * vxfs_transmod returns a Linux mode_t for a given + * VxFS inode structure. + */ +static __inline__ umode_t +vxfs_transmod(struct vxfs_inode_info *vip) +{ + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; + + if (VXFS_ISFIFO(vip)) + ret |= S_IFIFO; + if (VXFS_ISCHR(vip)) + ret |= S_IFCHR; + if (VXFS_ISDIR(vip)) + ret |= S_IFDIR; + if (VXFS_ISBLK(vip)) + ret |= S_IFBLK; + if (VXFS_ISLNK(vip)) + ret |= S_IFLNK; + if (VXFS_ISREG(vip)) + ret |= S_IFREG; + if (VXFS_ISSOC(vip)) + ret |= S_IFSOCK; + + return (ret); +} + static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, struct vxfs_inode_info *vip, struct vxfs_dinode *dip) { + struct inode *inode = &vip->vfs_inode; + vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); @@ -96,6 +124,23 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, /* don't endian swap the fields that differ by orgtype */ memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); + + inode->i_mode = vxfs_transmod(vip); + i_uid_write(inode, (uid_t)vip->vii_uid); + i_gid_write(inode, (gid_t)vip->vii_gid); + + set_nlink(inode, vip->vii_nlink); + inode->i_size = vip->vii_size; + + inode->i_atime.tv_sec = vip->vii_atime; + inode->i_ctime.tv_sec = vip->vii_ctime; + inode->i_mtime.tv_sec = vip->vii_mtime; + inode->i_atime.tv_nsec = 0; + inode->i_ctime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; + + inode->i_blocks = vip->vii_blocks; + inode->i_generation = vip->vii_gen; } /** @@ -121,48 +166,48 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) struct inode *inode; u_long block, offset; + inode = new_inode(sbp); + if (!inode) + return NULL; + inode->i_ino = get_next_ino(); + block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); bp = sb_bread(sbp, block); if (bp && buffer_mapped(bp)) { - struct vxfs_inode_info *vip; + struct vxfs_inode_info *vip = VXFS_INO(inode); 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); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif brelse(bp); - - inode = vxfs_get_fake_inode(sbp, vip); - if (!inode) - kmem_cache_free(vxfs_inode_cachep, vip); return inode; } -fail: printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); brelse(bp); + iput(inode); return NULL; } /** * __vxfs_iget - generic find inode facility - * @sbp: VFS superblock - * @ino: inode number * @ilistp: inode list + * @vip: VxFS inode to fill in + * @ino: inode number * * Description: * Search the for inode number @ino in the filesystem * described by @sbp. Use the specified inode table (@ilistp). * Returns the matching inode on success, else an error code. */ -static struct vxfs_inode_info * -__vxfs_iget(ino_t ino, struct inode *ilistp) +static int +__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) { struct page *pp; u_long offset; @@ -171,28 +216,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp) pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); if (!IS_ERR(pp)) { - struct vxfs_inode_info *vip; 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); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif vxfs_put_page(pp); - return (vip); + return 0; } - 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); + printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", + pp, (unsigned long)ino); + return PTR_ERR(pp); } /** @@ -208,104 +247,21 @@ fail: struct inode * vxfs_stiget(struct super_block *sbp, ino_t ino) { - struct vxfs_inode_info *vip; struct inode *inode; + int error; - vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); - if (IS_ERR(vip)) - return NULL; - inode = vxfs_get_fake_inode(sbp, vip); + inode = new_inode(sbp); if (!inode) - kmem_cache_free(vxfs_inode_cachep, vip); - return inode; -} - -/** - * vxfs_transmod - mode for a VxFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_transmod returns a Linux mode_t for a given - * VxFS inode structure. - */ -static __inline__ umode_t -vxfs_transmod(struct vxfs_inode_info *vip) -{ - umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; - - if (VXFS_ISFIFO(vip)) - ret |= S_IFIFO; - if (VXFS_ISCHR(vip)) - ret |= S_IFCHR; - if (VXFS_ISDIR(vip)) - ret |= S_IFDIR; - if (VXFS_ISBLK(vip)) - ret |= S_IFBLK; - if (VXFS_ISLNK(vip)) - ret |= S_IFLNK; - if (VXFS_ISREG(vip)) - ret |= S_IFREG; - if (VXFS_ISSOC(vip)) - ret |= S_IFSOCK; - - return (ret); -} - -/** - * vxfs_iinit- helper to fill inode fields - * @ip: VFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_instino is a helper function to fill in all relevant - * fields in @ip from @vip. - */ -static void -vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) -{ - - ip->i_mode = vxfs_transmod(vip); - i_uid_write(ip, (uid_t)vip->vii_uid); - i_gid_write(ip, (gid_t)vip->vii_gid); - - set_nlink(ip, vip->vii_nlink); - ip->i_size = vip->vii_size; - - ip->i_atime.tv_sec = vip->vii_atime; - ip->i_ctime.tv_sec = vip->vii_ctime; - ip->i_mtime.tv_sec = vip->vii_mtime; - ip->i_atime.tv_nsec = 0; - ip->i_ctime.tv_nsec = 0; - ip->i_mtime.tv_nsec = 0; - - ip->i_blocks = vip->vii_blocks; - ip->i_generation = vip->vii_gen; - - ip->i_private = 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. - */ -static struct inode * -vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) -{ - struct inode *ip = NULL; + return NULL; + inode->i_ino = get_next_ino(); - if ((ip = new_inode(sbp))) { - ip->i_ino = get_next_ino(); - vxfs_iinit(ip, vip); - ip->i_mapping->a_ops = &vxfs_aops; + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); + if (error) { + iput(inode); + return NULL; } - return (ip); + + return inode; } /** @@ -323,6 +279,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino) struct vxfs_inode_info *vip; const struct address_space_operations *aops; struct inode *ip; + int error; ip = iget_locked(sbp, ino); if (!ip) @@ -330,14 +287,13 @@ 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); - if (IS_ERR(vip)) { + vip = VXFS_INO(ip); + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); + if (error) { iget_failed(ip); - return ERR_CAST(vip); + return ERR_PTR(error); } - vxfs_iinit(ip, vip); - if (VXFS_ISIMMED(vip)) aops = &vxfs_immed_aops; else @@ -368,12 +324,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino) return ip; } -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); -} - /** * vxfs_evict_inode - remove inode from main memory * @ip: inode to discard. @@ -387,5 +337,4 @@ vxfs_evict_inode(struct inode *ip) { truncate_inode_pages_final(&ip->i_data); clear_inode(ip); - call_rcu(&ip->i_rcu, vxfs_i_callback); } 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 { * The inode as represented in the main memory. */ struct vxfs_inode_info { + struct inode vfs_inode; + __u32 vii_mode; __u32 vii_nlink; /* Link count */ __u32 vii_uid; /* UID */ @@ -183,4 +185,9 @@ struct vxfs_inode_info { #define vii_ext4 vii_org.ext4 #define vii_typed vii_org.typed +static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode) +{ + return container_of(inode, struct vxfs_inode_info, vfs_inode); +} + #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"); MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); MODULE_LICENSE("Dual BSD/GPL"); +static struct kmem_cache *vxfs_inode_cachep; + /** * vxfs_put_super - free superblock resources * @sbp: VFS superblock. @@ -117,7 +119,31 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) return 0; } +static struct inode *vxfs_alloc_inode(struct super_block *sb) +{ + struct vxfs_inode_info *vi; + + vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL); + if (!vi) + return NULL; + return &vi->vfs_inode; +} + +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, VXFS_INO(inode)); +} + +static void vxfs_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, vxfs_i_callback); +} + static const struct super_operations vxfs_super_ops = { + .alloc_inode = vxfs_alloc_inode, + .destroy_inode = vxfs_destroy_inode, .evict_inode = vxfs_evict_inode, .put_super = vxfs_put_super, .statfs = vxfs_statfs, @@ -206,6 +232,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } + sbp->s_op = &vxfs_super_ops; sbp->s_fs_info = infp; 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) goto out; } - sbp->s_op = &vxfs_super_ops; root = vxfs_iget(sbp, VXFS_ROOT_INO); if (IS_ERR(root)) { ret = PTR_ERR(root); |