The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/bfs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *      fs/bfs/inode.c
    3  *      BFS superblock and inode operations.
    4  *      Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
    5  *      From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
    6  */
    7 
    8 #include <linux/module.h>
    9 #include <linux/mm.h>
   10 #include <linux/slab.h>
   11 #include <linux/init.h>
   12 #include <linux/locks.h>
   13 #include <linux/bfs_fs.h>
   14 #include <linux/smp_lock.h>
   15 
   16 #include <asm/uaccess.h>
   17 
   18 #include "bfs_defs.h"
   19 
   20 MODULE_AUTHOR("Tigran A. Aivazian <tigran@veritas.com>");
   21 MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
   22 MODULE_LICENSE("GPL");
   23 EXPORT_NO_SYMBOLS;
   24 
   25 #undef DEBUG
   26 
   27 #ifdef DEBUG
   28 #define dprintf(x...)   printf(x)
   29 #else
   30 #define dprintf(x...)
   31 #endif
   32 
   33 void dump_imap(const char *prefix, struct super_block * s);
   34 
   35 static void bfs_read_inode(struct inode * inode)
   36 {
   37         unsigned long ino = inode->i_ino;
   38         kdev_t dev = inode->i_dev;
   39         struct bfs_inode * di;
   40         struct buffer_head * bh;
   41         int block, off;
   42 
   43         if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
   44                 printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
   45                 make_bad_inode(inode);
   46                 return;
   47         }
   48 
   49         block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
   50         bh = sb_bread(inode->i_sb, block);
   51         if (!bh) {
   52                 printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
   53                 make_bad_inode(inode);
   54                 return;
   55         }
   56 
   57         off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
   58         di = (struct bfs_inode *)bh->b_data + off;
   59 
   60         inode->i_mode = 0x0000FFFF & di->i_mode;
   61         if (di->i_vtype == BFS_VDIR) {
   62                 inode->i_mode |= S_IFDIR;
   63                 inode->i_op = &bfs_dir_inops;
   64                 inode->i_fop = &bfs_dir_operations;
   65         } else if (di->i_vtype == BFS_VREG) {
   66                 inode->i_mode |= S_IFREG;
   67                 inode->i_op = &bfs_file_inops;
   68                 inode->i_fop = &bfs_file_operations;
   69                 inode->i_mapping->a_ops = &bfs_aops;
   70         }
   71 
   72         inode->i_uid = di->i_uid;
   73         inode->i_gid = di->i_gid;
   74         inode->i_nlink = di->i_nlink;
   75         inode->i_size = BFS_FILESIZE(di);
   76         inode->i_blocks = BFS_FILEBLOCKS(di);
   77         inode->i_blksize = PAGE_SIZE;
   78         inode->i_atime = di->i_atime;
   79         inode->i_mtime = di->i_mtime;
   80         inode->i_ctime = di->i_ctime;
   81         inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
   82         inode->iu_sblock = di->i_sblock;
   83         inode->iu_eblock = di->i_eblock;
   84 
   85         brelse(bh);
   86 }
   87 
   88 static void bfs_write_inode(struct inode * inode, int unused)
   89 {
   90         unsigned long ino = inode->i_ino;
   91         kdev_t dev = inode->i_dev;
   92         struct bfs_inode * di;
   93         struct buffer_head * bh;
   94         int block, off;
   95 
   96         if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
   97                 printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
   98                 return;
   99         }
  100 
  101         lock_kernel();
  102         block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
  103         bh = sb_bread(inode->i_sb, block);
  104         if (!bh) {
  105                 printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
  106                 unlock_kernel();
  107                 return;
  108         }
  109 
  110         off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
  111         di = (struct bfs_inode *)bh->b_data + off;
  112 
  113         if (inode->i_ino == BFS_ROOT_INO)
  114                 di->i_vtype = BFS_VDIR;
  115         else
  116                 di->i_vtype = BFS_VREG;
  117 
  118         di->i_ino = inode->i_ino;
  119         di->i_mode = inode->i_mode;
  120         di->i_uid = inode->i_uid;
  121         di->i_gid = inode->i_gid;
  122         di->i_nlink = inode->i_nlink;
  123         di->i_atime = inode->i_atime;
  124         di->i_mtime = inode->i_mtime;
  125         di->i_ctime = inode->i_ctime;
  126         di->i_sblock = inode->iu_sblock;
  127         di->i_eblock = inode->iu_eblock;
  128         di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
  129 
  130         mark_buffer_dirty(bh);
  131         brelse(bh);
  132         unlock_kernel();
  133 }
  134 
  135 static void bfs_delete_inode(struct inode * inode)
  136 {
  137         unsigned long ino = inode->i_ino;
  138         kdev_t dev = inode->i_dev;
  139         struct bfs_inode * di;
  140         struct buffer_head * bh;
  141         int block, off;
  142         struct super_block * s = inode->i_sb;
  143 
  144         dprintf("ino=%08lx\n", inode->i_ino);
  145 
  146         if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) {
  147                 printf("invalid ino=%08lx\n", inode->i_ino);
  148                 return;
  149         }
  150         
  151         inode->i_size = 0;
  152         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  153         lock_kernel();
  154         mark_inode_dirty(inode);
  155         block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
  156         bh = sb_bread(s, block);
  157         if (!bh) {
  158                 printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
  159                 unlock_kernel();
  160                 return;
  161         }
  162         off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
  163         di = (struct bfs_inode *)bh->b_data + off;
  164         if (di->i_ino) {
  165                 s->su_freeb += BFS_FILEBLOCKS(di);
  166                 s->su_freei++;
  167                 clear_bit(di->i_ino, s->su_imap);
  168                 dump_imap("delete_inode", s);
  169         }
  170         di->i_ino = 0;
  171         di->i_sblock = 0;
  172         mark_buffer_dirty(bh);
  173         brelse(bh);
  174 
  175         /* if this was the last file, make the previous 
  176            block "last files last block" even if there is no real file there,
  177            saves us 1 gap */
  178         if (s->su_lf_eblk == inode->iu_eblock) {
  179                 s->su_lf_eblk = inode->iu_sblock - 1;
  180                 mark_buffer_dirty(s->su_sbh);
  181         }
  182         unlock_kernel();
  183         clear_inode(inode);
  184 }
  185 
  186 static void bfs_put_super(struct super_block *s)
  187 {
  188         brelse(s->su_sbh);
  189         kfree(s->su_imap);
  190 }
  191 
  192 static int bfs_statfs(struct super_block *s, struct statfs *buf)
  193 {
  194         buf->f_type = BFS_MAGIC;
  195         buf->f_bsize = s->s_blocksize;
  196         buf->f_blocks = s->su_blocks;
  197         buf->f_bfree = buf->f_bavail = s->su_freeb;
  198         buf->f_files = s->su_lasti + 1 - BFS_ROOT_INO;
  199         buf->f_ffree = s->su_freei;
  200         buf->f_fsid.val[0] = kdev_t_to_nr(s->s_dev);
  201         buf->f_namelen = BFS_NAMELEN;
  202         return 0;
  203 }
  204 
  205 static void bfs_write_super(struct super_block *s)
  206 {
  207         if (!(s->s_flags & MS_RDONLY))
  208                 mark_buffer_dirty(s->su_sbh);
  209         s->s_dirt = 0;
  210 }
  211 
  212 static struct super_operations bfs_sops = {
  213         read_inode:     bfs_read_inode,
  214         write_inode:    bfs_write_inode,
  215         delete_inode:   bfs_delete_inode,
  216         put_super:      bfs_put_super,
  217         write_super:    bfs_write_super,
  218         statfs:         bfs_statfs,
  219 };
  220 
  221 void dump_imap(const char *prefix, struct super_block * s)
  222 {
  223 #if 0
  224         int i;
  225         char *tmpbuf = (char *)get_free_page(GFP_KERNEL);
  226 
  227         if (!tmpbuf)
  228                 return;
  229         for (i=s->su_lasti; i>=0; i--) {
  230                 if (i>PAGE_SIZE-100) break;
  231                 if (test_bit(i, s->su_imap))
  232                         strcat(tmpbuf, "1");
  233                 else
  234                         strcat(tmpbuf, "");
  235         }
  236         printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, s->su_lasti, tmpbuf);
  237         free_page((unsigned long)tmpbuf);
  238 #endif
  239 }
  240 
  241 static struct super_block * bfs_read_super(struct super_block * s, 
  242         void * data, int silent)
  243 {
  244         kdev_t dev;
  245         struct buffer_head * bh;
  246         struct bfs_super_block * bfs_sb;
  247         struct inode * inode;
  248         int i, imap_len;
  249 
  250         dev = s->s_dev;
  251         set_blocksize(dev, BFS_BSIZE);
  252         s->s_blocksize = BFS_BSIZE;
  253         s->s_blocksize_bits = BFS_BSIZE_BITS;
  254 
  255         bh = sb_bread(s, 0);
  256         if(!bh)
  257                 goto out;
  258         bfs_sb = (struct bfs_super_block *)bh->b_data;
  259         if (bfs_sb->s_magic != BFS_MAGIC) {
  260                 if (!silent)
  261                         printf("No BFS filesystem on %s (magic=%08x)\n", 
  262                                 bdevname(dev), bfs_sb->s_magic);
  263                 goto out;
  264         }
  265         if (BFS_UNCLEAN(bfs_sb, s) && !silent)
  266                 printf("%s is unclean, continuing\n", bdevname(dev));
  267 
  268         s->s_magic = BFS_MAGIC;
  269         s->su_bfs_sb = bfs_sb;
  270         s->su_sbh = bh;
  271         s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
  272                         + BFS_ROOT_INO - 1;
  273 
  274         imap_len = s->su_lasti/8 + 1;
  275         s->su_imap = kmalloc(imap_len, GFP_KERNEL);
  276         if (!s->su_imap)
  277                 goto out;
  278         memset(s->su_imap, 0, imap_len);
  279         for (i=0; i<BFS_ROOT_INO; i++) 
  280                 set_bit(i, s->su_imap);
  281 
  282         s->s_op = &bfs_sops;
  283         inode = iget(s, BFS_ROOT_INO);
  284         if (!inode) {
  285                 kfree(s->su_imap);
  286                 goto out;
  287         }
  288         s->s_root = d_alloc_root(inode);
  289         if (!s->s_root) {
  290                 iput(inode);
  291                 kfree(s->su_imap);
  292                 goto out;
  293         }
  294 
  295         s->su_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
  296         s->su_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
  297         s->su_freei = 0;
  298         s->su_lf_eblk = 0;
  299         s->su_lf_sblk = 0;
  300         s->su_lf_ioff = 0;
  301         for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
  302                 inode = iget(s,i);
  303                 if (inode->iu_dsk_ino == 0)
  304                         s->su_freei++;
  305                 else {
  306                         set_bit(i, s->su_imap);
  307                         s->su_freeb -= inode->i_blocks;
  308                         if (inode->iu_eblock > s->su_lf_eblk) {
  309                                 s->su_lf_eblk = inode->iu_eblock;
  310                                 s->su_lf_sblk = inode->iu_sblock;
  311                                 s->su_lf_ioff = BFS_INO2OFF(i);
  312                         }
  313                 }
  314                 iput(inode);
  315         }
  316         if (!(s->s_flags & MS_RDONLY)) {
  317                 mark_buffer_dirty(bh);
  318                 s->s_dirt = 1;
  319         } 
  320         dump_imap("read_super", s);
  321         return s;
  322 
  323 out:
  324         brelse(bh);
  325         return NULL;
  326 }
  327 
  328 static DECLARE_FSTYPE_DEV(bfs_fs_type, "bfs", bfs_read_super);
  329 
  330 static int __init init_bfs_fs(void)
  331 {
  332         return register_filesystem(&bfs_fs_type);
  333 }
  334 
  335 static void __exit exit_bfs_fs(void)
  336 {
  337         unregister_filesystem(&bfs_fs_type);
  338 }
  339 
  340 module_init(init_bfs_fs)
  341 module_exit(exit_bfs_fs)

Cache object: 40633530ab0ec0da916464f972843392


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.