diff options
Diffstat (limited to 'fs/freevxfs')
| -rw-r--r-- | fs/freevxfs/Kconfig | 16 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_extern.h | 7 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_fshead.c | 2 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_immed.c | 1 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_inode.c | 38 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_lookup.c | 81 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_olt.h | 2 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_subr.c | 2 | ||||
| -rw-r--r-- | fs/freevxfs/vxfs_super.c | 27 |
9 files changed, 95 insertions, 81 deletions
diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig new file mode 100644 index 00000000000..8dc1cd5c1ef --- /dev/null +++ b/fs/freevxfs/Kconfig @@ -0,0 +1,16 @@ +config VXFS_FS + tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" + depends on BLOCK + help + FreeVxFS is a file system driver that support the VERITAS VxFS(TM) + file system format. VERITAS VxFS(TM) is the standard file system + of SCO UnixWare (and possibly others) and optionally available + for Sunsoft Solaris, HP-UX and many other operating systems. + Currently only readonly access is supported. + + NOTE: the file system type as used by mount(1), mount(2) and + fstab(5) is 'vxfs' as it describes the file system format, not + the actual driver. + + To compile this as a module, choose M here: the module will be + called freevxfs. If unsure, say N. diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 2b46064f66b..881aa3d217f 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -50,7 +50,11 @@ extern daddr_t vxfs_bmap1(struct inode *, long); /* vxfs_fshead.c */ extern int vxfs_read_fshead(struct super_block *); +/* vxfs_immed.c */ +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 *, @@ -59,7 +63,7 @@ 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_clear_inode(struct inode *); +extern void vxfs_evict_inode(struct inode *); /* vxfs_lookup.c */ extern const struct inode_operations vxfs_dir_inode_ops; @@ -69,6 +73,7 @@ extern const struct file_operations vxfs_dir_operations; extern int vxfs_read_olt(struct super_block *, u_long); /* vxfs_subr.c */ +extern const struct address_space_operations vxfs_aops; extern struct page * vxfs_get_page(struct address_space *, u_long); extern void vxfs_put_page(struct page *); extern struct buffer_head * vxfs_bread(struct inode *, int); diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index 78948b4b189..c9a6a94e58e 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -164,7 +164,7 @@ vxfs_read_fshead(struct super_block *sbp) goto out_free_pfp; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { - printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", + 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; } diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c index 8a5959a61ba..c36aeaf92e4 100644 --- a/fs/freevxfs/vxfs_immed.c +++ b/fs/freevxfs/vxfs_immed.c @@ -35,6 +35,7 @@ #include <linux/namei.h> #include "vxfs.h" +#include "vxfs_extern.h" #include "vxfs_inode.h" diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index ad88d2364bc..363e3ae25f6 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -41,11 +41,6 @@ #include "vxfs_extern.h" -extern const struct address_space_operations vxfs_aops; -extern const struct address_space_operations vxfs_immed_aops; - -extern const struct inode_operations vxfs_immed_symlink_iops; - struct kmem_cache *vxfs_inode_cachep; @@ -192,10 +187,10 @@ vxfs_stiget(struct super_block *sbp, ino_t ino) * vxfs_transmod returns a Linux mode_t for a given * VxFS inode structure. */ -static __inline__ mode_t +static __inline__ umode_t vxfs_transmod(struct vxfs_inode_info *vip) { - mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; if (VXFS_ISFIFO(vip)) ret |= S_IFIFO; @@ -229,10 +224,10 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) { ip->i_mode = vxfs_transmod(vip); - ip->i_uid = (uid_t)vip->vii_uid; - ip->i_gid = (gid_t)vip->vii_gid; + i_uid_write(ip, (uid_t)vip->vii_uid); + i_gid_write(ip, (gid_t)vip->vii_gid); - ip->i_nlink = vip->vii_nlink; + set_nlink(ip, vip->vii_nlink); ip->i_size = vip->vii_size; ip->i_atime.tv_sec = vip->vii_atime; @@ -265,6 +260,7 @@ 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; } @@ -276,7 +272,7 @@ vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) * *ip: VFS inode * * Description: - * vxfs_put_fake_inode frees all data asssociated with @ip. + * vxfs_put_fake_inode frees all data associated with @ip. */ void vxfs_put_fake_inode(struct inode *ip) @@ -330,8 +326,10 @@ vxfs_iget(struct super_block *sbp, ino_t ino) if (!VXFS_ISIMMED(vip)) { ip->i_op = &page_symlink_inode_operations; ip->i_mapping->a_ops = &vxfs_aops; - } else + } else { ip->i_op = &vxfs_immed_symlink_iops; + vip->vii_immed.vi_immed[ip->i_size] = '\0'; + } } else init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); @@ -339,16 +337,24 @@ 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_clear_inode - remove inode from main memory + * vxfs_evict_inode - remove inode from main memory * @ip: inode to discard. * * Description: - * vxfs_clear_inode() is called on the final iput and frees the private + * vxfs_evict_inode() is called on the final iput and frees the private * inode area. */ void -vxfs_clear_inode(struct inode *ip) +vxfs_evict_inode(struct inode *ip) { - kmem_cache_free(vxfs_inode_cachep, ip->i_private); + truncate_inode_pages_final(&ip->i_data); + clear_inode(ip); + call_rcu(&ip->i_rcu, vxfs_i_callback); } diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index aee049cb9f8..99c7f0a37af 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -36,7 +36,6 @@ #include <linux/highmem.h> #include <linux/kernel.h> #include <linux/pagemap.h> -#include <linux/smp_lock.h> #include "vxfs.h" #include "vxfs_dir.h" @@ -49,15 +48,17 @@ #define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize)) -static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); -static int vxfs_readdir(struct file *, void *, filldir_t); +static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int); +static int vxfs_readdir(struct file *, struct dir_context *); const struct inode_operations vxfs_dir_inode_ops = { .lookup = vxfs_lookup, }; const struct file_operations vxfs_dir_operations = { - .readdir = vxfs_readdir, + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = vxfs_readdir, }; @@ -161,7 +162,7 @@ vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) /** * vxfs_inode_by_name - find inode number for dentry * @dip: directory to search in - * @dp: dentry we seach for + * @dp: dentry we search for * * Description: * vxfs_inode_by_name finds out the inode number of @@ -191,7 +192,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp) * vxfs_lookup - lookup pathname component * @dip: dir in which we lookup * @dp: dentry we lookup - * @nd: lookup nameidata + * @flags: lookup flags * * Description: * vxfs_lookup tries to lookup the pathname component described @@ -202,7 +203,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp) * in the return pointer. */ static struct dentry * -vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) +vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags) { struct inode *ip = NULL; ino_t ino; @@ -210,16 +211,12 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) if (dp->d_name.len > VXFS_NAMELEN) return ERR_PTR(-ENAMETOOLONG); - lock_kernel(); ino = vxfs_inode_by_name(dip, dp); if (ino) { ip = vxfs_iget(dip->i_sb, ino); - if (IS_ERR(ip)) { - unlock_kernel(); + if (IS_ERR(ip)) return ERR_CAST(ip); - } } - unlock_kernel(); d_add(dp, ip); return NULL; } @@ -238,35 +235,28 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) * Zero. */ static int -vxfs_readdir(struct file *fp, void *retp, filldir_t filler) +vxfs_readdir(struct file *fp, struct dir_context *ctx) { - struct inode *ip = fp->f_path.dentry->d_inode; + struct inode *ip = file_inode(fp); struct super_block *sbp = ip->i_sb; u_long bsize = sbp->s_blocksize; u_long page, npages, block, pblocks, nblocks, offset; loff_t pos; - lock_kernel(); - - switch ((long)fp->f_pos) { - case 0: - if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) - goto out; - fp->f_pos++; - /* fallthrough */ - case 1: - if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0) - goto out; - fp->f_pos++; - /* fallthrough */ + if (ctx->pos == 0) { + if (!dir_emit_dot(fp, ctx)) + return 0; + ctx->pos = 1; } - - pos = fp->f_pos - 2; + if (ctx->pos == 1) { + if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR)) + return 0; + ctx->pos = 2; + } + pos = ctx->pos - 2; - if (pos > VXFS_DIRROUND(ip->i_size)) { - unlock_kernel(); + if (pos > VXFS_DIRROUND(ip->i_size)) return 0; - } npages = dir_pages(ip); nblocks = dir_blocks(ip); @@ -277,16 +267,16 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; for (; page < npages; page++, block = 0) { - caddr_t kaddr; + char *kaddr; struct page *pp; pp = vxfs_get_page(ip->i_mapping, page); if (IS_ERR(pp)) continue; - kaddr = (caddr_t)page_address(pp); + kaddr = (char *)page_address(pp); for (; block <= nblocks && block <= pblocks; block++) { - caddr_t baddr, limit; + char *baddr, *limit; struct vxfs_dirblk *dbp; struct vxfs_direct *de; @@ -299,21 +289,18 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) (kaddr + offset) : (baddr + VXFS_DIRBLKOV(dbp))); - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { - int over; - + for (; (char *)de <= limit; de = vxfs_next_entry(de)) { if (!de->d_reclen) break; if (!de->d_ino) continue; - offset = (caddr_t)de - kaddr; - over = filler(retp, de->d_name, de->d_namelen, - ((page << PAGE_CACHE_SHIFT) | offset) + 2, - de->d_ino, DT_UNKNOWN); - if (over) { + offset = (char *)de - kaddr; + ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; + if (!dir_emit(ctx, de->d_name, de->d_namelen, + de->d_ino, DT_UNKNOWN)) { vxfs_put_page(pp); - goto done; + return 0; } } offset = 0; @@ -321,10 +308,6 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) vxfs_put_page(pp); offset = 0; } - -done: - fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; -out: - unlock_kernel(); + ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; return 0; } diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h index d8324296486..b7b3af50261 100644 --- a/fs/freevxfs/vxfs_olt.h +++ b/fs/freevxfs/vxfs_olt.h @@ -60,7 +60,7 @@ enum { * * The Object Location Table header is placed at the beginning of each * OLT extent. It is used to fing certain filesystem-wide metadata, e.g. - * the inital inode list, the fileset header or the device configuration. + * the initial inode list, the fileset header or the device configuration. */ struct vxfs_olt { u_int32_t olt_magic; /* magic number */ diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c index ed8f0b0dd88..5d318c44f85 100644 --- a/fs/freevxfs/vxfs_subr.c +++ b/fs/freevxfs/vxfs_subr.c @@ -33,7 +33,6 @@ #include <linux/fs.h> #include <linux/buffer_head.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/pagemap.h> #include "vxfs_extern.h" @@ -45,7 +44,6 @@ static sector_t vxfs_bmap(struct address_space *, sector_t); const struct address_space_operations vxfs_aops = { .readpage = vxfs_readpage, .bmap = vxfs_bmap, - .sync_page = block_sync_page, }; inline void diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1dacda83157..7ca8c75d50d 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -52,7 +52,6 @@ MODULE_AUTHOR("Christoph Hellwig"); MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ static void vxfs_put_super(struct super_block *); @@ -60,7 +59,7 @@ 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 = { - .clear_inode = vxfs_clear_inode, + .evict_inode = vxfs_evict_inode, .put_super = vxfs_put_super, .statfs = vxfs_statfs, .remount_fs = vxfs_remount, @@ -125,12 +124,13 @@ vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) static int vxfs_remount(struct super_block *sb, int *flags, char *data) { + sync_filesystem(sb); *flags |= MS_RDONLY; return 0; } /** - * vxfs_read_super - read superblock into memory and initalize filesystem + * vxfs_read_super - read superblock into memory and initialize filesystem * @sbp: VFS superblock (to fill) * @dp: fs private mount data * @silent: do not complain loudly when sth is wrong @@ -143,7 +143,7 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) * The superblock on success, else %NULL. * * Locking: - * We are under the bkl and @sbp->s_lock. + * We are under @sbp->s_lock. */ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) { @@ -224,9 +224,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) ret = PTR_ERR(root); goto out; } - sbp->s_root = d_alloc_root(root); + sbp->s_root = d_make_root(root); if (!sbp->s_root) { - iput(root); printk(KERN_WARNING "vxfs: unable to get root dentry.\n"); goto out_free_ilist; } @@ -246,20 +245,21 @@ out: /* * The usual module blurb. */ -static int vxfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) +static struct dentry *vxfs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) { - return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super, - mnt); + return mount_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); } static struct file_system_type vxfs_fs_type = { .owner = THIS_MODULE, .name = "vxfs", - .get_sb = vxfs_get_sb, + .mount = vxfs_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; +MODULE_ALIAS_FS("vxfs"); /* makes mount -t vxfs autoload the module */ +MODULE_ALIAS("vxfs"); static int __init vxfs_init(void) @@ -281,6 +281,11 @@ 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); } |
