summaryrefslogtreecommitdiffstats
path: root/fs/bfs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
commit529c593ece216e4aaffd36bd940cb94f1fa63129 (patch)
tree78f1c0b805f5656aa7b0417a043c5346f700a2cf /fs/bfs
parent0bd079751d25808d1972baee5c4eaa1db2227257 (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.h4
-rw-r--r--fs/bfs/dir.c36
-rw-r--r--fs/bfs/file.c159
-rw-r--r--fs/bfs/inode.c94
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);
}