diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-23 00:40:54 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-23 00:40:54 +0000 |
commit | 529c593ece216e4aaffd36bd940cb94f1fa63129 (patch) | |
tree | 78f1c0b805f5656aa7b0417a043c5346f700a2cf /fs/bfs | |
parent | 0bd079751d25808d1972baee5c4eaa1db2227257 (diff) |
Merge with 2.3.43. I did ignore all modifications to the qlogicisp.c
driver due to the Origin A64 hacks.
Diffstat (limited to 'fs/bfs')
-rw-r--r-- | fs/bfs/bfs_defs.h | 4 | ||||
-rw-r--r-- | fs/bfs/dir.c | 36 | ||||
-rw-r--r-- | fs/bfs/file.c | 159 | ||||
-rw-r--r-- | fs/bfs/inode.c | 94 |
4 files changed, 162 insertions, 131 deletions
diff --git a/fs/bfs/bfs_defs.h b/fs/bfs/bfs_defs.h index 54d7dad29..c2756cdb9 100644 --- a/fs/bfs/bfs_defs.h +++ b/fs/bfs/bfs_defs.h @@ -5,7 +5,6 @@ #define su_lf_ioff u.bfs_sb.si_lf_ioff #define su_lf_sblk u.bfs_sb.si_lf_sblk #define su_lf_eblk u.bfs_sb.si_lf_eblk -#define su_bmap u.bfs_sb.si_bmap #define su_imap u.bfs_sb.si_imap #define su_sbh u.bfs_sb.si_sbh #define su_bfs_sb u.bfs_sb.si_bfs_sb @@ -13,3 +12,6 @@ #define iu_dsk_ino u.bfs_i.i_dsk_ino #define iu_sblock u.bfs_i.i_sblock #define iu_eblock u.bfs_i.i_eblock + +#define printf(format, args...) \ + printk(KERN_ERR "BFS-fs: " __FUNCTION__ "(): " format, ## args) diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index b6159be85..83b3e517b 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -14,9 +14,9 @@ #undef DEBUG #ifdef DEBUG -#define DBG(x...) printk(x) +#define dprintf(x...) printf(x) #else -#define DBG(x...) +#define dprintf(x...) #endif static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino); @@ -38,14 +38,13 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) int block; if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) { - printk(KERN_ERR "BFS-fs: %s(): Bad inode or not a directory %s:%08lx\n", - __FUNCTION__, bdevname(dev), dir->i_ino); + printf("Bad inode or not a directory %s:%08lx\n", bdevname(dev), dir->i_ino); return -EBADF; } if (f->f_pos & (BFS_DIRENT_SIZE-1)) { - printk(KERN_ERR "BFS-fs: %s(): Bad f_pos=%08lx for %s:%08lx\n", - __FUNCTION__, (unsigned long)f->f_pos, bdevname(dev), dir->i_ino); + printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, + bdevname(dev), dir->i_ino); return -EBADF; } @@ -77,18 +76,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) } static struct file_operations bfs_dir_operations = { - llseek: NULL, read: bfs_dir_read, - write: NULL, readdir: bfs_readdir, - poll: NULL, - ioctl: NULL, - mmap: NULL, - open: NULL, - flush: NULL, - release: NULL, fsync: file_fsync, - fasync: NULL, }; extern void dump_imap(const char *, struct super_block *); @@ -117,6 +107,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode) inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = inode->i_blksize = 0; inode->i_op = &bfs_file_inops; + inode->i_mapping->a_ops = &bfs_aops; inode->i_mode = mode; inode->i_ino = inode->iu_dsk_ino = ino; inode->iu_sblock = inode->iu_eblock = 0; @@ -189,9 +180,8 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry) goto out_brelse; if (!inode->i_nlink) { - printk(KERN_WARNING - "BFS-fs: %s(): unlinking non-existent file %s:%lu (nlink=%d)\n", - __FUNCTION__, bdevname(inode->i_dev), inode->i_ino, inode->i_nlink); + printf("unlinking non-existent file %s:%lu (nlink=%d)\n", bdevname(inode->i_dev), + inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } de->ino = 0; @@ -276,14 +266,6 @@ struct inode_operations bfs_dir_inops = { rmdir: NULL, mknod: NULL, rename: bfs_rename, - readlink: NULL, - follow_link: NULL, - get_block: NULL, - readpage: NULL, - writepage: NULL, - truncate: NULL, - permission: NULL, - revalidate: NULL }; static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino) @@ -294,7 +276,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int kdev_t dev; int i; - DBG(KERN_ERR "BFS-fs: %s(%s,%d)\n", __FUNCTION__, name, namelen); + dprintf("name=%s, namelen=%d\n", name, namelen); if (!namelen) return -ENOENT; diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 9e7503626..c3d5a8905 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -5,68 +5,149 @@ */ #include <linux/fs.h> +#include <linux/locks.h> #include <linux/bfs_fs.h> +#include <linux/smp_lock.h> #include "bfs_defs.h" #undef DEBUG #ifdef DEBUG -#define DBG(x...) printk(x) +#define dprintf(x...) printf(x) #else -#define DBG(x...) +#define dprintf(x...) #endif -static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos) -{ - return generic_file_write(f, buf, count, ppos, block_write_partial_page); -} - static struct file_operations bfs_file_operations = { - llseek: NULL, read: generic_file_read, - write: bfs_file_write, - readdir: NULL, - poll: NULL, - ioctl: NULL, + write: generic_file_write, mmap: generic_file_mmap, - open: NULL, - flush: NULL, - release: NULL, - fsync: NULL, - fasync: NULL, }; +static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev) +{ + struct buffer_head *bh, *new = NULL; + + bh = bread(dev, from, BFS_BSIZE); + if (!bh) + return -EIO; + new = getblk(dev, to, BFS_BSIZE); + memcpy(new->b_data, bh->b_data, bh->b_size); + mark_buffer_dirty(new, 1); + bforget(bh); + brelse(new); + return 0; +} + +static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end, + unsigned long where) +{ + unsigned long i; + + dprintf("%08lx-%08lx->%08lx\n", start, end, where); + for (i = start; i <= end; i++) + if(bfs_move_block(i, where + i, dev)) { + dprintf("failed to move block %08lx -> %08lx\n", i, where + i); + return -EIO; + } + return 0; +} + static int bfs_get_block(struct inode * inode, long block, struct buffer_head * bh_result, int create) { - long phys = inode->iu_sblock + block; - if (!create || phys <= inode->iu_eblock) { + long phys, next_free_block; + int err; + struct super_block *s = inode->i_sb; + + if (block < 0 || block > s->su_blocks) + return -EIO; + + phys = inode->iu_sblock + block; + if (!create) { + if (phys <= inode->iu_eblock) { + dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys); + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = phys; + bh_result->b_state |= (1UL << BH_Mapped); + } + return 0; + } + + /* if the file is not empty and the requested block is within the range + of blocks allocated for this file, we can grant it */ + if (inode->i_size && phys <= inode->iu_eblock) { + dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", create, block, phys); bh_result->b_dev = inode->i_dev; bh_result->b_blocknr = phys; bh_result->b_state |= (1UL << BH_Mapped); return 0; - } - /* no support for file migration, working on it */ - return -EIO; + } + + /* the rest has to be protected against itself */ + lock_kernel(); + + /* if the last data block for this file is the last allocated block, we can + extend the file trivially, without moving it anywhere */ + if (inode->iu_eblock == s->su_lf_eblk) { + dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", create, block, phys); + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = phys; + bh_result->b_state |= (1UL << BH_Mapped); + s->su_lf_eblk = inode->iu_eblock = inode->iu_sblock + block; + mark_inode_dirty(inode); + mark_buffer_dirty(s->su_sbh, 1); + err = 0; + goto out; + } + + /* Ok, we have to move this entire file to the next free block */ + next_free_block = s->su_lf_eblk + 1; + if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */ + err = bfs_move_blocks(inode->i_dev, inode->iu_sblock, inode->iu_eblock, next_free_block); + if (err) { + dprintf("failed to move ino=%08lx -> possible fs corruption\n", inode->i_ino); + goto out; + } + } else + err = 0; + + inode->iu_sblock = next_free_block; + s->su_lf_eblk = inode->iu_eblock = next_free_block + block; + mark_inode_dirty(inode); + mark_buffer_dirty(s->su_sbh, 1); + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = inode->iu_sblock + block; + bh_result->b_state |= (1UL << BH_Mapped); +out: + unlock_kernel(); + return err; +} + +static int bfs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,bfs_get_block); +} +static int bfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,bfs_get_block); +} +static int bfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,bfs_get_block); +} +static int bfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,bfs_get_block); } +struct address_space_operations bfs_aops = { + readpage: bfs_readpage, + writepage: bfs_writepage, + prepare_write: bfs_prepare_write, + commit_write: generic_commit_write, + bmap: bfs_bmap +}; struct inode_operations bfs_file_inops = { default_file_ops: &bfs_file_operations, - create: NULL, - lookup: NULL, - link: NULL, - unlink: NULL, - symlink: NULL, - mkdir: NULL, - rmdir: NULL, - mknod: NULL, - rename: NULL, - readlink: NULL, - follow_link: NULL, - get_block: bfs_get_block, - readpage: block_read_full_page, - writepage: block_write_full_page, - truncate: NULL, - permission: NULL, - revalidate: NULL }; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index c0ee15dc4..14e440f27 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -5,7 +5,6 @@ * 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> @@ -18,15 +17,15 @@ #include "bfs_defs.h" MODULE_AUTHOR("Tigran A. Aivazian"); -MODULE_DESCRIPTION("UnixWare BFS filesystem for Linux"); +MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux"); EXPORT_NO_SYMBOLS; #undef DEBUG #ifdef DEBUG -#define DBG(x...) printk(x) +#define dprintf(x...) printf(x) #else -#define DBG(x...) +#define dprintf(x...) #endif void dump_imap(const char *prefix, struct super_block * s); @@ -40,8 +39,7 @@ static void bfs_read_inode(struct inode * inode) 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); + printf("Bad inode number %s:%08lx\n", bdevname(dev), ino); make_bad_inode(inode); return; } @@ -49,8 +47,7 @@ static void bfs_read_inode(struct inode * 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); + printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino); make_bad_inode(inode); return; } @@ -65,6 +62,7 @@ static void bfs_read_inode(struct inode * inode) } else if (di->i_vtype == BFS_VREG) { inode->i_mode |= S_IFREG; inode->i_op = &bfs_file_inops; + inode->i_mapping->a_ops = &bfs_aops; } else inode->i_op = NULL; @@ -94,16 +92,14 @@ static void bfs_write_inode(struct inode * inode) 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); + printf("Bad inode number %s:%08lx\n", 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); + printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino); return; } @@ -140,30 +136,12 @@ static void bfs_delete_inode(struct inode * inode) int block, off; struct super_block * s = inode->i_sb; - DBG(KERN_ERR "%s(ino=%08lx)\n", __FUNCTION__, inode->i_ino); + dprintf("ino=%08lx\n", inode->i_ino); - if (!inode) + if (!inode || !inode->i_dev || inode->i_count > 1 || inode->i_nlink || !s) 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); + printf("invalid ino=%08lx\n", inode->i_ino); return; } @@ -173,8 +151,7 @@ static void bfs_delete_inode(struct inode * 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); + printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino); return; } off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; @@ -189,6 +166,14 @@ static void bfs_delete_inode(struct inode * inode) di->i_sblock = 0; mark_buffer_dirty(bh, 1); brelse(bh); + + /* if this was the last file, make the previous + block "last files last block" even if there is no real file there, + saves us 1 gap */ + if (s->su_lf_eblk == inode->iu_eblock) { + s->su_lf_eblk = inode->iu_sblock - 1; + mark_buffer_dirty(s->su_sbh, 1); + } clear_inode(inode); } @@ -196,7 +181,6 @@ static void bfs_put_super(struct super_block *s) { brelse(s->su_sbh); kfree(s->su_imap); - kfree(s->su_bmap); MOD_DEC_USE_COUNT; } @@ -251,7 +235,7 @@ void dump_imap(const char *prefix, struct super_block * s) else strcat(tmpbuf, "0"); } - printk(KERN_ERR "BFS-fs: %s: lasti=%d <%s>\n", prefix, s->su_lasti, tmpbuf); + printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, s->su_lasti, tmpbuf); free_page((unsigned long)tmpbuf); #endif } @@ -263,7 +247,7 @@ static struct super_block * bfs_read_super(struct super_block * s, struct buffer_head * bh; struct bfs_super_block * bfs_sb; struct inode * inode; - int i, imap_len, bmap_len; + int i, imap_len; MOD_INC_USE_COUNT; lock_super(s); @@ -272,58 +256,43 @@ static struct super_block * bfs_read_super(struct super_block * s, 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); + bh = bread(dev, 0, BFS_BSIZE); 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); + printf("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)); + printf("%s is unclean, continuing\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; - bmap_len = sizeof(struct bfs_bmap) * s->su_lasti; - s->su_bmap = kmalloc(bmap_len, GFP_KERNEL); - if (!s->su_bmap) - goto out; - memset(s->su_bmap, 0, bmap_len); imap_len = s->su_lasti/8 + 1; s->su_imap = kmalloc(imap_len, GFP_KERNEL); - if (!s->su_imap) { - kfree(s->su_bmap); + if (!s->su_imap) goto out; - } memset(s->su_imap, 0, imap_len); - for (i=0; i<BFS_ROOT_INO; i++) { - s->su_bmap[i].start = s->su_bmap[i].end = 0; + 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); - kfree(s->su_bmap); goto out; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); kfree(s->su_imap); - kfree(s->su_bmap); goto out; } @@ -335,10 +304,9 @@ static struct super_block * bfs_read_super(struct super_block * s, 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) { + if (inode->iu_dsk_ino == 0) s->su_freei++; - s->su_bmap[i].start = s->su_bmap[i].end = 0; - } else { + else { set_bit(i, s->su_imap); s->su_freeb -= inode->i_blocks; if (inode->iu_eblock > s->su_lf_eblk) { @@ -346,8 +314,6 @@ static struct super_block * bfs_read_super(struct super_block * s, s->su_lf_sblk = inode->iu_sblock; s->su_lf_ioff = BFS_INO2OFF(i); } - s->su_bmap[i].start = inode->iu_sblock; - s->su_bmap[i].end = inode->iu_eblock; } iput(inode); } |