patch-2.3.25 linux/fs/bfs/inode.c
Next file: linux/fs/binfmt_elf.c
Previous file: linux/fs/bfs/file.c
Back to the patch index
Back to the overall index
- Lines: 376
- Date:
Fri Oct 29 11:05:08 1999
- Orig file:
v2.3.24/linux/fs/bfs/inode.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.24/linux/fs/bfs/inode.c linux/fs/bfs/inode.c
@@ -0,0 +1,375 @@
+/*
+ * fs/bfs/inode.c
+ * BFS superblock and inode operations.
+ * Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/locks.h>
+#include <linux/bfs_fs.h>
+
+#include <asm/uaccess.h>
+
+#include "bfs_defs.h"
+
+MODULE_AUTHOR("Tigran A. Aivazian");
+MODULE_DESCRIPTION("UnixWare BFS filesystem for Linux");
+EXPORT_NO_SYMBOLS;
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void dump_imap(const char *prefix, struct super_block * s);
+
+static void bfs_read_inode(struct inode * inode)
+{
+ unsigned long ino = inode->i_ino;
+ kdev_t dev = inode->i_dev;
+ struct bfs_inode * di;
+ struct buffer_head * bh;
+ int block, off;
+
+ if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+ printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n",
+ __FUNCTION__, bdevname(dev), ino);
+ make_bad_inode(inode);
+ return;
+ }
+
+ block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ bh = bread(dev, block, BFS_BSIZE);
+ if (!bh) {
+ printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+ __FUNCTION__, bdevname(dev), ino);
+ make_bad_inode(inode);
+ return;
+ }
+
+ off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
+ di = (struct bfs_inode *)bh->b_data + off;
+
+ inode->i_mode = 0x0000FFFF & di->i_mode;
+ if (di->i_vtype == BFS_VDIR) {
+ inode->i_mode |= S_IFDIR;
+ inode->i_op = &bfs_dir_inops;
+ } else if (di->i_vtype == BFS_VREG) {
+ inode->i_mode |= S_IFREG;
+ inode->i_op = &bfs_file_inops;
+ } else
+ inode->i_op = NULL;
+
+ inode->i_uid = di->i_uid;
+ inode->i_gid = di->i_gid;
+ inode->i_nlink = di->i_nlink;
+ inode->i_size = BFS_FILESIZE(di);
+ inode->i_blocks = BFS_FILEBLOCKS(di);
+ inode->i_blksize = PAGE_SIZE;
+ inode->i_atime = di->i_atime;
+ inode->i_mtime = di->i_mtime;
+ inode->i_ctime = di->i_ctime;
+ inode->i_rdev = 0; /* BFS doesn't have special nodes */
+ inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
+ inode->iu_sblock = di->i_sblock;
+ inode->iu_eblock = di->i_eblock;
+
+ brelse(bh);
+}
+
+static void bfs_write_inode(struct inode * inode)
+{
+ unsigned long ino = inode->i_ino;
+ kdev_t dev = inode->i_dev;
+ struct bfs_inode * di;
+ struct buffer_head * bh;
+ int block, off;
+
+ if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+ printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n",
+ __FUNCTION__, bdevname(dev), ino);
+ return;
+ }
+
+ block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ bh = bread(dev, block, BFS_BSIZE);
+ if (!bh) {
+ printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+ __FUNCTION__, bdevname(dev), ino);
+ return;
+ }
+
+ off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+ di = (struct bfs_inode *)bh->b_data + off;
+
+ if (inode->i_ino == BFS_ROOT_INO)
+ di->i_vtype = BFS_VDIR;
+ else
+ di->i_vtype = BFS_VREG;
+
+ di->i_ino = inode->i_ino;
+ di->i_mode = inode->i_mode;
+ di->i_uid = inode->i_uid;
+ di->i_gid = inode->i_gid;
+ di->i_nlink = inode->i_nlink;
+ di->i_atime = inode->i_atime;
+ di->i_mtime = inode->i_mtime;
+ di->i_ctime = inode->i_ctime;
+ di->i_sblock = inode->iu_sblock;
+ di->i_eblock = inode->iu_eblock;
+ di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
+
+ mark_buffer_dirty(bh, 1);
+ brelse(bh);
+}
+
+static void bfs_delete_inode(struct inode * inode)
+{
+ unsigned long ino = inode->i_ino;
+ kdev_t dev = inode->i_dev;
+ struct bfs_inode * di;
+ struct buffer_head * bh;
+ int block, off;
+ struct super_block * s = inode->i_sb;
+
+ DBG(KERN_ERR "%s(ino=%08lx)\n", __FUNCTION__, inode->i_ino);
+
+ if (!inode)
+ return;
+ if (!inode->i_dev) {
+ printk(KERN_ERR "BFS-fs: free_inode(%08lx) !dev\n", inode->i_ino);
+ return;
+ }
+ if (inode->i_count > 1) {
+ printk(KERN_ERR "BFS-fs: free_inode(%08lx) count=%d\n",
+ inode->i_ino, inode->i_count);
+ return;
+ }
+ if (inode->i_nlink) {
+ printk(KERN_ERR "BFS-fs: free_inode(%08lx) nlink=%d\n",
+ inode->i_ino, inode->i_nlink);
+ return;
+ }
+ if (!inode->i_sb) {
+ printk(KERN_ERR "BFS-fs: free_inode(%08lx) !sb\n", inode->i_ino);
+ return;
+ }
+ if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) {
+ printk(KERN_ERR "BFS-fs: free_inode(%08lx) invalid ino\n", inode->i_ino);
+ return;
+ }
+
+ inode->i_size = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ bh = bread(dev, block, BFS_BSIZE);
+ if (!bh) {
+ printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+ __FUNCTION__, bdevname(dev), ino);
+ return;
+ }
+ off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+ di = (struct bfs_inode *)bh->b_data + off;
+ if (di->i_ino) {
+ s->su_freeb += BFS_FILEBLOCKS(di);
+ s->su_freei++;
+ clear_bit(di->i_ino, s->su_imap);
+ dump_imap("delete_inode", s);
+ }
+ di->i_ino = 0;
+ di->i_sblock = 0;
+ mark_buffer_dirty(bh, 1);
+ brelse(bh);
+ clear_inode(inode);
+}
+
+static void bfs_put_super(struct super_block *s)
+{
+ brelse(s->su_sbh);
+ kfree(s->su_imap);
+ MOD_DEC_USE_COUNT;
+}
+
+static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = BFS_MAGIC;
+ tmp.f_bsize = s->s_blocksize;
+ tmp.f_blocks = s->su_blocks;
+ tmp.f_bfree = tmp.f_bavail = s->su_freeb;
+ tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO;
+ tmp.f_ffree = s->su_freei;
+ tmp.f_fsid.val[0] = s->s_dev;
+ tmp.f_namelen = BFS_NAMELEN;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static void bfs_write_super(struct super_block *s)
+{
+ if (!(s->s_flags & MS_RDONLY))
+ mark_buffer_dirty(s->su_sbh, 1);
+ s->s_dirt = 0;
+}
+
+static struct super_operations bfs_sops = {
+ read_inode: bfs_read_inode,
+ write_inode: bfs_write_inode,
+ put_inode: NULL,
+ delete_inode: bfs_delete_inode,
+ notify_change: NULL,
+ put_super: bfs_put_super,
+ write_super: bfs_write_super,
+ statfs: bfs_statfs,
+ remount_fs: NULL,
+ clear_inode: NULL,
+ umount_begin: NULL
+};
+
+void dump_imap(const char *prefix, struct super_block * s)
+{
+#if 0
+ int i;
+ char *tmpbuf = (char *)get_free_page(GFP_KERNEL);
+
+ if (!tmpbuf)
+ return;
+ memset(tmpbuf, 0, 400);
+ for (i=s->su_lasti; i>=0; i--) {
+ if (i>PAGE_SIZE-100) break;
+ if (test_bit(i, s->su_imap))
+ strcat(tmpbuf, "1");
+ else
+ strcat(tmpbuf, "0");
+ }
+ printk(KERN_ERR "BFS-fs: %s: lasti=%d <%s>\n", prefix, s->su_lasti, tmpbuf);
+ free_page((unsigned long)tmpbuf);
+#endif
+}
+
+static struct super_block * bfs_read_super(struct super_block * s,
+ void * data, int silent)
+{
+ kdev_t dev;
+ struct buffer_head * bh;
+ struct bfs_super_block * bfs_sb;
+ struct inode * inode;
+ int i, imap_len;
+
+ MOD_INC_USE_COUNT;
+ lock_super(s);
+ dev = s->s_dev;
+ set_blocksize(dev, BFS_BSIZE);
+ s->s_blocksize = BFS_BSIZE;
+ s->s_blocksize_bits = BFS_BSIZE_BITS;
+
+ /* read ahead 8K to get inodes as we'll need them in a tick */
+ bh = breada(dev, 0, BFS_BSIZE, 0, 8192);
+ if(!bh)
+ goto out;
+ bfs_sb = (struct bfs_super_block *)bh->b_data;
+ if (bfs_sb->s_magic != BFS_MAGIC) {
+ if (!silent)
+ printk(KERN_ERR "BFS-fs: No BFS filesystem on %s (magic=%08x)\n",
+ bdevname(dev), bfs_sb->s_magic);
+ goto out;
+ }
+ if (BFS_UNCLEAN(bfs_sb, s) && !silent)
+ printk(KERN_WARNING "BFS-fs: %s is unclean\n", bdevname(dev));
+
+#ifndef CONFIG_BFS_FS_WRITE
+ s->s_flags |= MS_RDONLY;
+#endif
+ s->s_magic = BFS_MAGIC;
+ s->su_bfs_sb = bfs_sb;
+ s->su_sbh = bh;
+ s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode)
+ + BFS_ROOT_INO - 1;
+
+ imap_len = s->su_lasti/8 + 1;
+ s->su_imap = kmalloc(imap_len, GFP_KERNEL);
+ if (!s->su_imap)
+ goto out;
+ memset(s->su_imap, 0, imap_len);
+ for (i=0; i<BFS_ROOT_INO; i++)
+ set_bit(i, s->su_imap);
+
+ s->s_op = &bfs_sops;
+ inode = iget(s, BFS_ROOT_INO);
+ if (!inode) {
+ kfree(s->su_imap);
+ goto out;
+ }
+ s->s_root = d_alloc_root(inode);
+ if (!s->s_root) {
+ iput(inode);
+ kfree(s->su_imap);
+ goto out;
+ }
+
+ s->su_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
+ s->su_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
+ s->su_freei = 0;
+ s->su_lf_eblk = 0;
+ s->su_lf_sblk = 0;
+ s->su_lf_ioff = 0;
+ for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
+ inode = iget(s,i);
+ if (inode->iu_dsk_ino == 0)
+ s->su_freei++;
+ else {
+ set_bit(i, s->su_imap);
+ s->su_freeb -= inode->i_blocks;
+ if (inode->iu_eblock > s->su_lf_eblk) {
+ s->su_lf_eblk = inode->iu_eblock;
+ s->su_lf_sblk = inode->iu_sblock;
+ s->su_lf_ioff = BFS_INO2OFF(i);
+ }
+ }
+ iput(inode);
+ }
+ if (!(s->s_flags & MS_RDONLY)) {
+ mark_buffer_dirty(bh, 1);
+ s->s_dirt = 1;
+ }
+ dump_imap("read_super", s);
+ unlock_super(s);
+ return s;
+
+out:
+ brelse(bh);
+ s->s_dev = 0;
+ unlock_super(s);
+ MOD_DEC_USE_COUNT;
+ return NULL;
+}
+
+static struct file_system_type bfs_fs_type = {
+ name: "bfs",
+ fs_flags: FS_REQUIRES_DEV,
+ read_super: bfs_read_super,
+ next: NULL
+};
+
+#ifdef MODULE
+#define init_bfs_fs init_module
+
+void cleanup_module(void)
+{
+ unregister_filesystem(&bfs_fs_type);
+}
+#endif
+
+int __init init_bfs_fs(void)
+{
+ return register_filesystem(&bfs_fs_type);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)