Commit 84f922f1 authored by Christoph Hellwig's avatar Christoph Hellwig

Merge 2.5.11 into sysvfs development tree

parents e66d5915 825ab03e
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
* This file contains code for allocating/freeing blocks. * This file contains code for allocating/freeing blocks.
*/ */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/locks.h> #include <linux/locks.h>
#include "sysv.h"
/* We don't trust the value of /* We don't trust the value of
sb->sv_sbd2->s_tfree = *sb->sv_free_blocks sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
...@@ -31,7 +30,7 @@ static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh) ...@@ -31,7 +30,7 @@ static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
{ {
char *bh_data = bh->b_data; char *bh_data = bh->b_data;
if (sb->sv_type == FSTYPE_SYSV4) if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
return (u32*)(bh_data+4); return (u32*)(bh_data+4);
else else
return (u32*)(bh_data+2); return (u32*)(bh_data+2);
...@@ -41,28 +40,29 @@ static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh) ...@@ -41,28 +40,29 @@ static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
void sysv_free_block(struct super_block * sb, u32 nr) void sysv_free_block(struct super_block * sb, u32 nr)
{ {
struct sysv_sb_info * sbi = SYSV_SB(sb);
struct buffer_head * bh; struct buffer_head * bh;
u32 *blocks = sb->sv_bcache; u32 *blocks = sbi->s_bcache;
unsigned count; unsigned count;
unsigned block = fs32_to_cpu(sb, nr); unsigned block = fs32_to_cpu(sbi, nr);
/* /*
* This code does not work at all for AFS (it has a bitmap * This code does not work at all for AFS (it has a bitmap
* free list). As AFS is supposed to be read-only no one * free list). As AFS is supposed to be read-only no one
* should call this for an AFS filesystem anyway... * should call this for an AFS filesystem anyway...
*/ */
if (sb->sv_type == FSTYPE_AFS) if (sbi->s_type == FSTYPE_AFS)
return; return;
if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) { if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
printk("sysv_free_block: trying to free block not in datazone\n"); printk("sysv_free_block: trying to free block not in datazone\n");
return; return;
} }
lock_super(sb); lock_super(sb);
count = fs16_to_cpu(sb, *sb->sv_bcache_count); count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
if (count > sb->sv_flc_size) { if (count > sbi->s_flc_size) {
printk("sysv_free_block: flc_count > flc_size\n"); printk("sysv_free_block: flc_count > flc_size\n");
unlock_super(sb); unlock_super(sb);
return; return;
...@@ -71,8 +71,8 @@ void sysv_free_block(struct super_block * sb, u32 nr) ...@@ -71,8 +71,8 @@ void sysv_free_block(struct super_block * sb, u32 nr)
* into this block being freed, ditto if it's completely empty * into this block being freed, ditto if it's completely empty
* (applies only on Coherent). * (applies only on Coherent).
*/ */
if (count == sb->sv_flc_size || count == 0) { if (count == sbi->s_flc_size || count == 0) {
block += sb->sv_block_base; block += sbi->s_block_base;
bh = sb_getblk(sb, block); bh = sb_getblk(sb, block);
if (!bh) { if (!bh) {
printk("sysv_free_block: getblk() failed\n"); printk("sysv_free_block: getblk() failed\n");
...@@ -80,42 +80,43 @@ void sysv_free_block(struct super_block * sb, u32 nr) ...@@ -80,42 +80,43 @@ void sysv_free_block(struct super_block * sb, u32 nr)
return; return;
} }
memset(bh->b_data, 0, sb->s_blocksize); memset(bh->b_data, 0, sb->s_blocksize);
*(u16*)bh->b_data = cpu_to_fs16(sb, count); *(u16*)bh->b_data = cpu_to_fs16(sbi, count);
memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t)); memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
mark_buffer_uptodate(bh, 1); mark_buffer_uptodate(bh, 1);
brelse(bh); brelse(bh);
count = 0; count = 0;
} }
sb->sv_bcache[count++] = nr; sbi->s_bcache[count++] = nr;
*sb->sv_bcache_count = cpu_to_fs16(sb, count); *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
fs32_add(sb, sb->sv_free_blocks, 1); fs32_add(sbi, sbi->s_free_blocks, 1);
dirty_sb(sb); dirty_sb(sb);
unlock_super(sb); unlock_super(sb);
} }
u32 sysv_new_block(struct super_block * sb) u32 sysv_new_block(struct super_block * sb)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
unsigned int block; unsigned int block;
u32 nr; u32 nr;
struct buffer_head * bh; struct buffer_head * bh;
unsigned count; unsigned count;
lock_super(sb); lock_super(sb);
count = fs16_to_cpu(sb, *sb->sv_bcache_count); count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
if (count == 0) /* Applies only to Coherent FS */ if (count == 0) /* Applies only to Coherent FS */
goto Enospc; goto Enospc;
nr = sb->sv_bcache[--count]; nr = sbi->s_bcache[--count];
if (nr == 0) /* Applies only to Xenix FS, SystemV FS */ if (nr == 0) /* Applies only to Xenix FS, SystemV FS */
goto Enospc; goto Enospc;
block = fs32_to_cpu(sb, nr); block = fs32_to_cpu(sbi, nr);
*sb->sv_bcache_count = cpu_to_fs16(sb, count); *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) { if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
printk("sysv_new_block: new block %d is not in data zone\n", printk("sysv_new_block: new block %d is not in data zone\n",
block); block);
goto Enospc; goto Enospc;
...@@ -124,26 +125,26 @@ u32 sysv_new_block(struct super_block * sb) ...@@ -124,26 +125,26 @@ u32 sysv_new_block(struct super_block * sb)
if (count == 0) { /* the last block continues the free list */ if (count == 0) { /* the last block continues the free list */
unsigned count; unsigned count;
block += sb->sv_block_base; block += sbi->s_block_base;
if (!(bh = sb_bread(sb, block))) { if (!(bh = sb_bread(sb, block))) {
printk("sysv_new_block: cannot read free-list block\n"); printk("sysv_new_block: cannot read free-list block\n");
/* retry this same block next time */ /* retry this same block next time */
*sb->sv_bcache_count = cpu_to_fs16(sb, 1); *sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
goto Enospc; goto Enospc;
} }
count = fs16_to_cpu(sb, *(u16*)bh->b_data); count = fs16_to_cpu(sbi, *(u16*)bh->b_data);
if (count > sb->sv_flc_size) { if (count > sbi->s_flc_size) {
printk("sysv_new_block: free-list block with >flc_size entries\n"); printk("sysv_new_block: free-list block with >flc_size entries\n");
brelse(bh); brelse(bh);
goto Enospc; goto Enospc;
} }
*sb->sv_bcache_count = cpu_to_fs16(sb, count); *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
memcpy(sb->sv_bcache, get_chunk(sb, bh), memcpy(sbi->s_bcache, get_chunk(sb, bh),
count * sizeof(sysv_zone_t)); count * sizeof(sysv_zone_t));
brelse(bh); brelse(bh);
} }
/* Now the free list head in the superblock is valid again. */ /* Now the free list head in the superblock is valid again. */
fs32_add(sb, sb->sv_free_blocks, -1); fs32_add(sbi, sbi->s_free_blocks, -1);
dirty_sb(sb); dirty_sb(sb);
unlock_super(sb); unlock_super(sb);
return nr; return nr;
...@@ -155,6 +156,7 @@ u32 sysv_new_block(struct super_block * sb) ...@@ -155,6 +156,7 @@ u32 sysv_new_block(struct super_block * sb)
unsigned long sysv_count_free_blocks(struct super_block * sb) unsigned long sysv_count_free_blocks(struct super_block * sb)
{ {
struct sysv_sb_info * sbi = SYSV_SB(sb);
int sb_count; int sb_count;
int count; int count;
struct buffer_head * bh = NULL; struct buffer_head * bh = NULL;
...@@ -167,21 +169,21 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) ...@@ -167,21 +169,21 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
* free list). As AFS is supposed to be read-only we just * free list). As AFS is supposed to be read-only we just
* lie and say it has no free block at all. * lie and say it has no free block at all.
*/ */
if (sb->sv_type == FSTYPE_AFS) if (sbi->s_type == FSTYPE_AFS)
return 0; return 0;
lock_super(sb); lock_super(sb);
sb_count = fs32_to_cpu(sb, *sb->sv_free_blocks); sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks);
if (0) if (0)
goto trust_sb; goto trust_sb;
/* this causes a lot of disk traffic ... */ /* this causes a lot of disk traffic ... */
count = 0; count = 0;
n = fs16_to_cpu(sb, *sb->sv_bcache_count); n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
blocks = sb->sv_bcache; blocks = sbi->s_bcache;
while (1) { while (1) {
if (n > sb->sv_flc_size) if (n > sbi->s_flc_size)
goto E2big; goto E2big;
block = 0; block = 0;
while (n && (block = blocks[--n]) != 0) while (n && (block = blocks[--n]) != 0)
...@@ -189,17 +191,17 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) ...@@ -189,17 +191,17 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
if (block == 0) if (block == 0)
break; break;
block = fs32_to_cpu(sb, block); block = fs32_to_cpu(sbi, block);
if (bh) if (bh)
brelse(bh); brelse(bh);
if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) if (block < sbi->s_firstdatazone || block >= sbi->s_nzones)
goto Einval; goto Einval;
block += sb->sv_block_base; block += sbi->s_block_base;
bh = sb_bread(sb, block); bh = sb_bread(sb, block);
if (!bh) if (!bh)
goto Eio; goto Eio;
n = fs16_to_cpu(sb, *(u16*)bh->b_data); n = fs16_to_cpu(sbi, *(u16*)bh->b_data);
blocks = get_chunk(sb, bh); blocks = get_chunk(sb, bh);
} }
if (bh) if (bh)
...@@ -228,7 +230,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) ...@@ -228,7 +230,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
printk("sysv_count_free_blocks: free block count was %d, " printk("sysv_count_free_blocks: free block count was %d, "
"correcting to %d\n", sb_count, count); "correcting to %d\n", sb_count, count);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_free_blocks = cpu_to_fs32(sb, count); *sbi->s_free_blocks = cpu_to_fs32(sbi, count);
dirty_sb(sb); dirty_sb(sb);
} }
goto done; goto done;
......
...@@ -13,9 +13,8 @@ ...@@ -13,9 +13,8 @@
* SystemV/Coherent directory handling functions * SystemV/Coherent directory handling functions
*/ */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include "sysv.h"
static int sysv_readdir(struct file *, void *, filldir_t); static int sysv_readdir(struct file *, void *, filldir_t);
...@@ -104,7 +103,8 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -104,7 +103,8 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
(n<<PAGE_CACHE_SHIFT) | offset, (n<<PAGE_CACHE_SHIFT) | offset,
fs16_to_cpu(sb, de->inode), DT_UNKNOWN); fs16_to_cpu(SYSV_SB(sb), de->inode),
DT_UNKNOWN);
if (over) { if (over) {
dir_put_page(page); dir_put_page(page);
goto done; goto done;
...@@ -228,7 +228,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode) ...@@ -228,7 +228,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
goto out_unlock; goto out_unlock;
memcpy (de->name, name, namelen); memcpy (de->name, name, namelen);
memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, from, to); err = dir_commit_chunk(page, from, to);
dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_mtime = dir->i_ctime = CURRENT_TIME;
mark_inode_dirty(dir); mark_inode_dirty(dir);
...@@ -280,10 +280,10 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) ...@@ -280,10 +280,10 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
memset(base, 0, PAGE_CACHE_SIZE); memset(base, 0, PAGE_CACHE_SIZE);
de = (struct sysv_dir_entry *) base; de = (struct sysv_dir_entry *) base;
de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
strcpy(de->name,"."); strcpy(de->name,".");
de++; de++;
de->inode = cpu_to_fs16(inode->i_sb, dir->i_ino); de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
strcpy(de->name,".."); strcpy(de->name,"..");
err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
...@@ -321,7 +321,8 @@ int sysv_empty_dir(struct inode * inode) ...@@ -321,7 +321,8 @@ int sysv_empty_dir(struct inode * inode)
if (de->name[0] != '.') if (de->name[0] != '.')
goto not_empty; goto not_empty;
if (!de->name[1]) { if (!de->name[1]) {
if (de->inode == cpu_to_fs16(sb, inode->i_ino)) if (de->inode == cpu_to_fs16(SYSV_SB(sb),
inode->i_ino))
continue; continue;
goto not_empty; goto not_empty;
} }
...@@ -350,7 +351,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page, ...@@ -350,7 +351,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
err = page->mapping->a_ops->prepare_write(NULL, page, from, to); err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
if (err) if (err)
BUG(); BUG();
de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, from, to); err = dir_commit_chunk(page, from, to);
UnlockPage(page); UnlockPage(page);
dir_put_page(page); dir_put_page(page);
...@@ -377,7 +378,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry) ...@@ -377,7 +378,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
ino_t res = 0; ino_t res = 0;
if (de) { if (de) {
res = fs16_to_cpu(dentry->d_sb, de->inode); res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
dir_put_page(page); dir_put_page(page);
} }
return res; return res;
......
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
* SystemV/Coherent regular file handling primitives * SystemV/Coherent regular file handling primitives
*/ */
#include <linux/fs.h> #include "sysv.h"
#include <linux/sysv_fs.h>
/* /*
* We have mostly NULLs here: the current defaults are OK for * We have mostly NULLs here: the current defaults are OK for
......
...@@ -20,12 +20,11 @@ ...@@ -20,12 +20,11 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
#include "sysv.h"
/* We don't trust the value of /* We don't trust the value of
sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes
...@@ -37,33 +36,38 @@ ...@@ -37,33 +36,38 @@
static inline sysv_ino_t * static inline sysv_ino_t *
sv_sb_fic_inode(struct super_block * sb, unsigned int i) sv_sb_fic_inode(struct super_block * sb, unsigned int i)
{ {
if (sb->sv_bh1 == sb->sv_bh2) struct sysv_sb_info *sbi = SYSV_SB(sb);
return &sb->sv_sb_fic_inodes[i];
if (sbi->s_bh1 == sbi->s_bh2)
return &sbi->s_sb_fic_inodes[i];
else { else {
/* 512 byte Xenix FS */ /* 512 byte Xenix FS */
unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]); unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
if (offset < 512) if (offset < 512)
return (sysv_ino_t*)(sb->sv_sbd1 + offset); return (sysv_ino_t*)(sbi->s_sbd1 + offset);
else else
return (sysv_ino_t*)(sb->sv_sbd2 + offset); return (sysv_ino_t*)(sbi->s_sbd2 + offset);
} }
} }
struct sysv_inode * struct sysv_inode *
sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh) sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
struct sysv_inode *res; struct sysv_inode *res;
int block = sb->sv_firstinodezone + sb->sv_block_base; int block = sbi->s_firstinodezone + sbi->s_block_base;
block += (ino-1) >> sb->sv_inodes_per_block_bits;
block += (ino-1) >> sbi->s_inodes_per_block_bits;
*bh = sb_bread(sb, block); *bh = sb_bread(sb, block);
if (!*bh) if (!*bh)
return NULL; return NULL;
res = (struct sysv_inode *) (*bh)->b_data; res = (struct sysv_inode *)(*bh)->b_data;
return res + ((ino-1) & sb->sv_inodes_per_block_1); return res + ((ino-1) & sbi->s_inodes_per_block_1);
} }
static int refill_free_cache(struct super_block *sb) static int refill_free_cache(struct super_block *sb)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
struct buffer_head * bh; struct buffer_head * bh;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
int i = 0, ino; int i = 0, ino;
...@@ -72,13 +76,13 @@ static int refill_free_cache(struct super_block *sb) ...@@ -72,13 +76,13 @@ static int refill_free_cache(struct super_block *sb)
raw_inode = sysv_raw_inode(sb, ino, &bh); raw_inode = sysv_raw_inode(sb, ino, &bh);
if (!raw_inode) if (!raw_inode)
goto out; goto out;
while (ino <= sb->sv_ninodes) { while (ino <= sbi->s_ninodes) {
if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) { if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) {
*sv_sb_fic_inode(sb,i++) = cpu_to_fs16(sb, ino); *sv_sb_fic_inode(sb,i++) = cpu_to_fs16(SYSV_SB(sb), ino);
if (i == sb->sv_fic_size) if (i == sbi->s_fic_size)
break; break;
} }
if ((ino++ & sb->sv_inodes_per_block_1) == 0) { if ((ino++ & sbi->s_inodes_per_block_1) == 0) {
brelse(bh); brelse(bh);
raw_inode = sysv_raw_inode(sb, ino, &bh); raw_inode = sysv_raw_inode(sb, ino, &bh);
if (!raw_inode) if (!raw_inode)
...@@ -93,7 +97,8 @@ static int refill_free_cache(struct super_block *sb) ...@@ -93,7 +97,8 @@ static int refill_free_cache(struct super_block *sb)
void sysv_free_inode(struct inode * inode) void sysv_free_inode(struct inode * inode)
{ {
struct super_block * sb; struct super_block *sb = inode->i_sb;
struct sysv_sb_info *sbi = SYSV_SB(sb);
unsigned int ino; unsigned int ino;
struct buffer_head * bh; struct buffer_head * bh;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
...@@ -101,7 +106,7 @@ void sysv_free_inode(struct inode * inode) ...@@ -101,7 +106,7 @@ void sysv_free_inode(struct inode * inode)
sb = inode->i_sb; sb = inode->i_sb;
ino = inode->i_ino; ino = inode->i_ino;
if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) { if (ino <= SYSV_ROOT_INO || ino > sbi->s_ninodes) {
printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
return; return;
} }
...@@ -113,12 +118,12 @@ void sysv_free_inode(struct inode * inode) ...@@ -113,12 +118,12 @@ void sysv_free_inode(struct inode * inode)
return; return;
} }
lock_super(sb); lock_super(sb);
count = fs16_to_cpu(sb, *sb->sv_sb_fic_count); count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
if (count < sb->sv_fic_size) { if (count < sbi->s_fic_size) {
*sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sb, ino); *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino);
*sb->sv_sb_fic_count = cpu_to_fs16(sb, count); *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);
} }
fs16_add(sb, sb->sv_sb_total_free_inodes, 1); fs16_add(sbi, sbi->s_sb_total_free_inodes, 1);
dirty_sb(sb); dirty_sb(sb);
memset(raw_inode, 0, sizeof(struct sysv_inode)); memset(raw_inode, 0, sizeof(struct sysv_inode));
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
...@@ -128,18 +133,18 @@ void sysv_free_inode(struct inode * inode) ...@@ -128,18 +133,18 @@ void sysv_free_inode(struct inode * inode)
struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
{ {
struct inode * inode; struct super_block *sb = dir->i_sb;
struct super_block * sb; struct sysv_sb_info *sbi = SYSV_SB(sb);
struct inode *inode;
u16 ino; u16 ino;
unsigned count; unsigned count;
sb = dir->i_sb;
inode = new_inode(sb); inode = new_inode(sb);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
lock_super(sb); lock_super(sb);
count = fs16_to_cpu(sb, *sb->sv_sb_fic_count); count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) { if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
count = refill_free_cache(sb); count = refill_free_cache(sb);
if (count == 0) { if (count == 0) {
...@@ -150,8 +155,8 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) ...@@ -150,8 +155,8 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
} }
/* Now count > 0. */ /* Now count > 0. */
ino = *sv_sb_fic_inode(sb,--count); ino = *sv_sb_fic_inode(sb,--count);
*sb->sv_sb_fic_count = cpu_to_fs16(sb, count); *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);
fs16_add(sb, sb->sv_sb_total_free_inodes, -1); fs16_add(sbi, sbi->s_sb_total_free_inodes, -1);
dirty_sb(sb); dirty_sb(sb);
if (dir->i_mode & S_ISGID) { if (dir->i_mode & S_ISGID) {
...@@ -162,7 +167,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) ...@@ -162,7 +167,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
inode->i_gid = current->fsgid; inode->i_gid = current->fsgid;
inode->i_uid = current->fsuid; inode->i_uid = current->fsuid;
inode->i_ino = fs16_to_cpu(sb, ino); inode->i_ino = fs16_to_cpu(sbi, ino);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0; inode->i_blocks = inode->i_blksize = 0;
memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data)); memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
...@@ -180,13 +185,14 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) ...@@ -180,13 +185,14 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
unsigned long sysv_count_free_inodes(struct super_block * sb) unsigned long sysv_count_free_inodes(struct super_block * sb)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
struct buffer_head * bh; struct buffer_head * bh;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
int ino, count, sb_count; int ino, count, sb_count;
lock_super(sb); lock_super(sb);
sb_count = fs16_to_cpu(sb, *sb->sv_sb_total_free_inodes); sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes);
if (0) if (0)
goto trust_sb; goto trust_sb;
...@@ -197,10 +203,10 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) ...@@ -197,10 +203,10 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
raw_inode = sysv_raw_inode(sb, ino, &bh); raw_inode = sysv_raw_inode(sb, ino, &bh);
if (!raw_inode) if (!raw_inode)
goto Eio; goto Eio;
while (ino <= sb->sv_ninodes) { while (ino <= sbi->s_ninodes) {
if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
count++; count++;
if ((ino++ & sb->sv_inodes_per_block_1) == 0) { if ((ino++ & sbi->s_inodes_per_block_1) == 0) {
brelse(bh); brelse(bh);
raw_inode = sysv_raw_inode(sb, ino, &bh); raw_inode = sysv_raw_inode(sb, ino, &bh);
if (!raw_inode) if (!raw_inode)
...@@ -220,7 +226,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) ...@@ -220,7 +226,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
"free inode count was %d, correcting to %d\n", "free inode count was %d, correcting to %d\n",
sb_count, count); sb_count, count);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_sb_total_free_inodes = cpu_to_fs16(sb, count); *sbi->s_sb_total_free_inodes = cpu_to_fs16(SYSV_SB(sb), count);
dirty_sb(sb); dirty_sb(sb);
} }
goto out; goto out;
......
...@@ -21,56 +21,68 @@ ...@@ -21,56 +21,68 @@
* the superblock. * the superblock.
*/ */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/highuid.h> #include <linux/highuid.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "sysv.h"
/* This is only called on sync() and umount(), when s_dirt=1. */ /* This is only called on sync() and umount(), when s_dirt=1. */
static void sysv_write_super(struct super_block *sb) static void sysv_write_super(struct super_block *sb)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
unsigned long time = CURRENT_TIME, old_time;
lock_kernel(); lock_kernel();
if (!(sb->s_flags & MS_RDONLY)) { if (sb->s_flags & MS_RDONLY)
/* If we are going to write out the super block, goto clean;
then attach current time stamp.
But if the filesystem was marked clean, keep it clean. */ /*
unsigned long time = CURRENT_TIME; * If we are going to write out the super block,
unsigned long old_time = fs32_to_cpu(sb, *sb->sv_sb_time); * then attach current time stamp.
if (sb->sv_type == FSTYPE_SYSV4) * But if the filesystem was marked clean, keep it clean.
if (*sb->sv_sb_state == cpu_to_fs32(sb, 0x7c269d38 - old_time)) */
*sb->sv_sb_state = cpu_to_fs32(sb, 0x7c269d38 - time); old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
*sb->sv_sb_time = cpu_to_fs32(sb, time); if (sbi->s_type == FSTYPE_SYSV4) {
mark_buffer_dirty(sb->sv_bh2); if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
*sbi->s_sb_state = cpu_to_fs32(sbi, 0x7c269d38 - time);
*sbi->s_sb_time = cpu_to_fs32(sbi, time);
mark_buffer_dirty(sbi->s_bh2);
} }
clean:
sb->s_dirt = 0; sb->s_dirt = 0;
unlock_kernel(); unlock_kernel();
} }
static void sysv_put_super(struct super_block *sb) static void sysv_put_super(struct super_block *sb)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
/* XXX ext2 also updates the state here */ /* XXX ext2 also updates the state here */
mark_buffer_dirty(sb->sv_bh1); mark_buffer_dirty(sbi->s_bh1);
if (sb->sv_bh1 != sb->sv_bh2) if (sbi->s_bh1 != sbi->s_bh2)
mark_buffer_dirty(sb->sv_bh2); mark_buffer_dirty(sbi->s_bh2);
} }
brelse(sb->sv_bh1); brelse(sbi->s_bh1);
if (sb->sv_bh1 != sb->sv_bh2) if (sbi->s_bh1 != sbi->s_bh2)
brelse(sb->sv_bh2); brelse(sbi->s_bh2);
kfree(sbi);
} }
static int sysv_statfs(struct super_block *sb, struct statfs *buf) static int sysv_statfs(struct super_block *sb, struct statfs *buf)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
buf->f_type = sb->s_magic; buf->f_type = sb->s_magic;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = sb->sv_ndatazones; buf->f_blocks = sbi->s_ndatazones;
buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb); buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb);
buf->f_files = sb->sv_ninodes; buf->f_files = sbi->s_ninodes;
buf->f_ffree = sysv_count_free_inodes(sb); buf->f_ffree = sysv_count_free_inodes(sb);
buf->f_namelen = SYSV_NAMELEN; buf->f_namelen = SYSV_NAMELEN;
return 0; return 0;
...@@ -79,15 +91,15 @@ static int sysv_statfs(struct super_block *sb, struct statfs *buf) ...@@ -79,15 +91,15 @@ static int sysv_statfs(struct super_block *sb, struct statfs *buf)
/* /*
* NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32 * NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32
*/ */
static inline void read3byte(struct super_block *sb, static inline void read3byte(struct sysv_sb_info *sbi,
unsigned char * from, unsigned char * to) unsigned char * from, unsigned char * to)
{ {
if (sb->sv_bytesex == BYTESEX_PDP) { if (sbi->s_bytesex == BYTESEX_PDP) {
to[0] = from[0]; to[0] = from[0];
to[1] = 0; to[1] = 0;
to[2] = from[1]; to[2] = from[1];
to[3] = from[2]; to[3] = from[2];
} else if (sb->sv_bytesex == BYTESEX_LE) { } else if (sbi->s_bytesex == BYTESEX_LE) {
to[0] = from[0]; to[0] = from[0];
to[1] = from[1]; to[1] = from[1];
to[2] = from[2]; to[2] = from[2];
...@@ -100,14 +112,14 @@ static inline void read3byte(struct super_block *sb, ...@@ -100,14 +112,14 @@ static inline void read3byte(struct super_block *sb,
} }
} }
static inline void write3byte(struct super_block *sb, static inline void write3byte(struct sysv_sb_info *sbi,
unsigned char * from, unsigned char * to) unsigned char * from, unsigned char * to)
{ {
if (sb->sv_bytesex == BYTESEX_PDP) { if (sbi->s_bytesex == BYTESEX_PDP) {
to[0] = from[0]; to[0] = from[0];
to[1] = from[2]; to[1] = from[2];
to[2] = from[3]; to[2] = from[3];
} else if (sb->sv_bytesex == BYTESEX_LE) { } else if (sbi->s_bytesex == BYTESEX_LE) {
to[0] = from[0]; to[0] = from[0];
to[1] = from[1]; to[1] = from[1];
to[2] = from[2]; to[2] = from[2];
...@@ -146,6 +158,7 @@ void sysv_set_inode(struct inode *inode, dev_t rdev) ...@@ -146,6 +158,7 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
static void sysv_read_inode(struct inode *inode) static void sysv_read_inode(struct inode *inode)
{ {
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
struct sysv_sb_info * sbi = SYSV_SB(sb);
struct buffer_head * bh; struct buffer_head * bh;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
struct sysv_inode_info * si; struct sysv_inode_info * si;
...@@ -153,7 +166,7 @@ static void sysv_read_inode(struct inode *inode) ...@@ -153,7 +166,7 @@ static void sysv_read_inode(struct inode *inode)
dev_t rdev = 0; dev_t rdev = 0;
ino = inode->i_ino; ino = inode->i_ino;
if (!ino || ino > sb->sv_ninodes) { if (!ino || ino > sbi->s_ninodes) {
printk("Bad inode number on dev %s: %d is out of range\n", printk("Bad inode number on dev %s: %d is out of range\n",
inode->i_sb->s_id, ino); inode->i_sb->s_id, ino);
goto bad_inode; goto bad_inode;
...@@ -165,23 +178,23 @@ static void sysv_read_inode(struct inode *inode) ...@@ -165,23 +178,23 @@ static void sysv_read_inode(struct inode *inode)
goto bad_inode; goto bad_inode;
} }
/* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */ /* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
inode->i_mode = fs16_to_cpu(sb, raw_inode->i_mode); inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode);
inode->i_uid = (uid_t)fs16_to_cpu(sb, raw_inode->i_uid); inode->i_uid = (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid);
inode->i_gid = (gid_t)fs16_to_cpu(sb, raw_inode->i_gid); inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid);
inode->i_nlink = fs16_to_cpu(sb, raw_inode->i_nlink); inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink);
inode->i_size = fs32_to_cpu(sb, raw_inode->i_size); inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
inode->i_atime = fs32_to_cpu(sb, raw_inode->i_atime); inode->i_atime = fs32_to_cpu(sbi, raw_inode->i_atime);
inode->i_mtime = fs32_to_cpu(sb, raw_inode->i_mtime); inode->i_mtime = fs32_to_cpu(sbi, raw_inode->i_mtime);
inode->i_ctime = fs32_to_cpu(sb, raw_inode->i_ctime); inode->i_ctime = fs32_to_cpu(sbi, raw_inode->i_ctime);
inode->i_blocks = inode->i_blksize = 0; inode->i_blocks = inode->i_blksize = 0;
si = SYSV_I(inode); si = SYSV_I(inode);
for (block = 0; block < 10+1+1+1; block++) for (block = 0; block < 10+1+1+1; block++)
read3byte(sb, &raw_inode->i_a.i_addb[3*block], read3byte(sbi, &raw_inode->i_data[3*block],
(unsigned char*)&si->i_data[block]); (u8 *)&si->i_data[block]);
brelse(bh); brelse(bh);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
rdev = (u16)fs32_to_cpu(sb, si->i_data[0]); rdev = (u16)fs32_to_cpu(sbi, si->i_data[0]);
si->i_dir_start_lookup = 0; si->i_dir_start_lookup = 0;
sysv_set_inode(inode, rdev); sysv_set_inode(inode, rdev);
return; return;
...@@ -194,13 +207,14 @@ static void sysv_read_inode(struct inode *inode) ...@@ -194,13 +207,14 @@ static void sysv_read_inode(struct inode *inode)
static struct buffer_head * sysv_update_inode(struct inode * inode) static struct buffer_head * sysv_update_inode(struct inode * inode)
{ {
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
struct sysv_sb_info * sbi = SYSV_SB(sb);
struct buffer_head * bh; struct buffer_head * bh;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
struct sysv_inode_info * si; struct sysv_inode_info * si;
unsigned int ino, block; unsigned int ino, block;
ino = inode->i_ino; ino = inode->i_ino;
if (!ino || ino > sb->sv_ninodes) { if (!ino || ino > sbi->s_ninodes) {
printk("Bad inode number on dev %s: %d is out of range\n", printk("Bad inode number on dev %s: %d is out of range\n",
inode->i_sb->s_id, ino); inode->i_sb->s_id, ino);
return 0; return 0;
...@@ -211,21 +225,21 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) ...@@ -211,21 +225,21 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
return 0; return 0;
} }
raw_inode->i_mode = cpu_to_fs16(sb, inode->i_mode); raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode);
raw_inode->i_uid = cpu_to_fs16(sb, fs_high2lowuid(inode->i_uid)); raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid));
raw_inode->i_gid = cpu_to_fs16(sb, fs_high2lowgid(inode->i_gid)); raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid));
raw_inode->i_nlink = cpu_to_fs16(sb, inode->i_nlink); raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink);
raw_inode->i_size = cpu_to_fs32(sb, inode->i_size); raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size);
raw_inode->i_atime = cpu_to_fs32(sb, inode->i_atime); raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime);
raw_inode->i_mtime = cpu_to_fs32(sb, inode->i_mtime); raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime);
raw_inode->i_ctime = cpu_to_fs32(sb, inode->i_ctime); raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime);
si = SYSV_I(inode); si = SYSV_I(inode);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
si->i_data[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev)); si->i_data[0] = cpu_to_fs32(sbi, kdev_t_to_nr(inode->i_rdev));
for (block = 0; block < 10+1+1+1; block++) for (block = 0; block < 10+1+1+1; block++)
write3byte(sb, (unsigned char*)&si->i_data[block], write3byte(sbi, (u8 *)&si->i_data[block],
&raw_inode->i_a.i_addb[3*block]); &raw_inode->i_data[3*block]);
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
return bh; return bh;
} }
......
...@@ -5,10 +5,8 @@ ...@@ -5,10 +5,8 @@
* AV, Sep--Dec 2000 * AV, Sep--Dec 2000
*/ */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/smp_lock.h> #include "sysv.h"
enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */ enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */
...@@ -24,9 +22,10 @@ static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode) ...@@ -24,9 +22,10 @@ static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode)
static int block_to_path(struct inode *inode, long block, int offsets[DEPTH]) static int block_to_path(struct inode *inode, long block, int offsets[DEPTH])
{ {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
int ptrs_bits = sb->sv_ind_per_block_bits; struct sysv_sb_info *sbi = SYSV_SB(sb);
unsigned long indirect_blocks = sb->sv_ind_per_block, int ptrs_bits = sbi->s_ind_per_block_bits;
double_blocks = sb->sv_ind_per_block_2; unsigned long indirect_blocks = sbi->s_ind_per_block,
double_blocks = sbi->s_ind_per_block_2;
int n = 0; int n = 0;
if (block < 0) { if (block < 0) {
...@@ -51,9 +50,9 @@ static int block_to_path(struct inode *inode, long block, int offsets[DEPTH]) ...@@ -51,9 +50,9 @@ static int block_to_path(struct inode *inode, long block, int offsets[DEPTH])
return n; return n;
} }
static inline int block_to_cpu(struct super_block *sb, u32 nr) static inline int block_to_cpu(struct sysv_sb_info *sbi, u32 nr)
{ {
return sb->sv_block_base + fs32_to_cpu(sb, nr); return sbi->s_block_base + fs32_to_cpu(sbi, nr);
} }
typedef struct { typedef struct {
...@@ -62,6 +61,8 @@ typedef struct { ...@@ -62,6 +61,8 @@ typedef struct {
struct buffer_head *bh; struct buffer_head *bh;
} Indirect; } Indirect;
static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v) static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
{ {
p->key = *(p->p = v); p->key = *(p->p = v);
...@@ -91,23 +92,26 @@ static Indirect *get_branch(struct inode *inode, ...@@ -91,23 +92,26 @@ static Indirect *get_branch(struct inode *inode,
struct buffer_head *bh; struct buffer_head *bh;
*err = 0; *err = 0;
add_chain (chain, NULL, SYSV_I(inode)->i_data + *offsets); add_chain(chain, NULL, SYSV_I(inode)->i_data + *offsets);
if (!p->key) if (!p->key)
goto no_block; goto no_block;
while (--depth) { while (--depth) {
int block = block_to_cpu(sb, p->key); int block = block_to_cpu(SYSV_SB(sb), p->key);
bh = sb_bread(sb, block); bh = sb_bread(sb, block);
if (!bh) if (!bh)
goto failure; goto failure;
read_lock(&pointers_lock);
if (!verify_chain(chain, p)) if (!verify_chain(chain, p))
goto changed; goto changed;
add_chain(++p, bh, (u32*)bh->b_data + *++offsets); add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
read_unlock(&pointers_lock);
if (!p->key) if (!p->key)
goto no_block; goto no_block;
} }
return NULL; return NULL;
changed: changed:
read_unlock(&pointers_lock);
brelse(bh); brelse(bh);
*err = -EAGAIN; *err = -EAGAIN;
goto no_block; goto no_block;
...@@ -138,7 +142,7 @@ static int alloc_branch(struct inode *inode, ...@@ -138,7 +142,7 @@ static int alloc_branch(struct inode *inode,
* Get buffer_head for parent block, zero it out and set * Get buffer_head for parent block, zero it out and set
* the pointer to new one, then send parent to disk. * the pointer to new one, then send parent to disk.
*/ */
parent = block_to_cpu(inode->i_sb, branch[n-1].key); parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key);
bh = sb_getblk(inode->i_sb, parent); bh = sb_getblk(inode->i_sb, parent);
lock_buffer(bh); lock_buffer(bh);
memset(bh->b_data, 0, blocksize); memset(bh->b_data, 0, blocksize);
...@@ -166,12 +170,14 @@ static inline int splice_branch(struct inode *inode, ...@@ -166,12 +170,14 @@ static inline int splice_branch(struct inode *inode,
int num) int num)
{ {
int i; int i;
/* Verify that place we are splicing to is still there and vacant */
/* Verify that place we are splicing to is still there and vacant */
write_lock(&pointers_lock);
if (!verify_chain(chain, where-1) || *where->p) if (!verify_chain(chain, where-1) || *where->p)
goto changed; goto changed;
*where->p = where->key; *where->p = where->key;
write_unlock(&pointers_lock);
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
/* had we spliced it onto indirect block? */ /* had we spliced it onto indirect block? */
...@@ -185,6 +191,7 @@ static inline int splice_branch(struct inode *inode, ...@@ -185,6 +191,7 @@ static inline int splice_branch(struct inode *inode,
return 0; return 0;
changed: changed:
write_unlock(&pointers_lock);
for (i = 1; i < num; i++) for (i = 1; i < num; i++)
bforget(where[i].bh); bforget(where[i].bh);
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
...@@ -205,14 +212,14 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b ...@@ -205,14 +212,14 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
if (depth == 0) if (depth == 0)
goto out; goto out;
lock_kernel();
reread: reread:
partial = get_branch(inode, depth, offsets, chain, &err); partial = get_branch(inode, depth, offsets, chain, &err);
/* Simplest case - block found, no allocation needed */ /* Simplest case - block found, no allocation needed */
if (!partial) { if (!partial) {
got_it: got_it:
map_bh(bh_result, sb, block_to_cpu(sb, chain[depth-1].key)); map_bh(bh_result, sb, block_to_cpu(SYSV_SB(sb),
chain[depth-1].key));
/* Clean up and exit */ /* Clean up and exit */
partial = chain+depth-1; /* the whole chain */ partial = chain+depth-1; /* the whole chain */
goto cleanup; goto cleanup;
...@@ -225,7 +232,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b ...@@ -225,7 +232,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
brelse(partial->bh); brelse(partial->bh);
partial--; partial--;
} }
unlock_kernel();
out: out:
return err; return err;
} }
...@@ -277,6 +283,8 @@ static Indirect *find_shared(struct inode *inode, ...@@ -277,6 +283,8 @@ static Indirect *find_shared(struct inode *inode,
*top = 0; *top = 0;
for (k = depth; k > 1 && !offsets[k-1]; k--) for (k = depth; k > 1 && !offsets[k-1]; k--)
; ;
write_lock(&pointers_lock);
partial = get_branch(inode, k, offsets, chain, &err); partial = get_branch(inode, k, offsets, chain, &err);
if (!partial) if (!partial)
partial = chain + k-1; partial = chain + k-1;
...@@ -284,8 +292,10 @@ static Indirect *find_shared(struct inode *inode, ...@@ -284,8 +292,10 @@ static Indirect *find_shared(struct inode *inode,
* If the branch acquired continuation since we've looked at it - * If the branch acquired continuation since we've looked at it -
* fine, it should all survive and (new) top doesn't belong to us. * fine, it should all survive and (new) top doesn't belong to us.
*/ */
if (!partial->key && *partial->p) if (!partial->key && *partial->p) {
write_unlock(&pointers_lock);
goto no_top; goto no_top;
}
for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--) for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
; ;
/* /*
...@@ -300,8 +310,9 @@ static Indirect *find_shared(struct inode *inode, ...@@ -300,8 +310,9 @@ static Indirect *find_shared(struct inode *inode,
*top = *p->p; *top = *p->p;
*p->p = 0; *p->p = 0;
} }
write_unlock(&pointers_lock);
while(partial > p) { while (partial > p) {
brelse(partial->bh); brelse(partial->bh);
partial--; partial--;
} }
...@@ -333,7 +344,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth) ...@@ -333,7 +344,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
if (!nr) if (!nr)
continue; continue;
*p = 0; *p = 0;
block = block_to_cpu(sb, nr); block = block_to_cpu(SYSV_SB(sb), nr);
bh = sb_bread(sb, block); bh = sb_bread(sb, block);
if (!bh) if (!bh)
continue; continue;
...@@ -372,8 +383,6 @@ void sysv_truncate (struct inode * inode) ...@@ -372,8 +383,6 @@ void sysv_truncate (struct inode * inode)
if (n == 0) if (n == 0)
return; return;
lock_kernel();
if (n == 1) { if (n == 1) {
free_data(inode, i_data+offsets[0], i_data + DIRECT); free_data(inode, i_data+offsets[0], i_data + DIRECT);
goto do_indirects; goto do_indirects;
...@@ -412,7 +421,6 @@ void sysv_truncate (struct inode * inode) ...@@ -412,7 +421,6 @@ void sysv_truncate (struct inode * inode)
sysv_sync_inode (inode); sysv_sync_inode (inode);
else else
mark_inode_dirty(inode); mark_inode_dirty(inode);
unlock_kernel();
} }
static int sysv_writepage(struct page *page) static int sysv_writepage(struct page *page)
......
...@@ -12,10 +12,9 @@ ...@@ -12,10 +12,9 @@
* Copyright (C) 1997, 1998 Krzysztof G. Baranowski * Copyright (C) 1997, 1998 Krzysztof G. Baranowski
*/ */
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include "sysv.h"
static inline void inc_count(struct inode *inode) static inline void inc_count(struct inode *inode)
{ {
...@@ -138,7 +137,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, ...@@ -138,7 +137,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (inode->i_nlink >= inode->i_sb->sv_link_max) if (inode->i_nlink >= SYSV_SB(inode->i_sb)->s_link_max)
return -EMLINK; return -EMLINK;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
...@@ -153,7 +152,7 @@ static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) ...@@ -153,7 +152,7 @@ static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode)
struct inode * inode; struct inode * inode;
int err = -EMLINK; int err = -EMLINK;
if (dir->i_nlink >= dir->i_sb->sv_link_max) if (dir->i_nlink >= SYSV_SB(dir->i_sb)->s_link_max)
goto out; goto out;
inc_count(dir); inc_count(dir);
...@@ -271,7 +270,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -271,7 +270,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
} else { } else {
if (dir_de) { if (dir_de) {
err = -EMLINK; err = -EMLINK;
if (new_dir->i_nlink >= new_dir->i_sb->sv_link_max) if (new_dir->i_nlink >= SYSV_SB(new_dir->i_sb)->s_link_max)
goto out_dir; goto out_dir;
} }
inc_count(old_inode); inc_count(old_inode);
......
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h>
#include <linux/sysv_fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h>
#include "sysv.h"
/* /*
* The following functions try to recognize specific filesystems. * The following functions try to recognize specific filesystems.
...@@ -44,10 +43,10 @@ enum { ...@@ -44,10 +43,10 @@ enum {
JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60 JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60
}; };
static void detected_xenix(struct super_block *sb) static void detected_xenix(struct sysv_sb_info *sbi)
{ {
struct buffer_head *bh1 = sb->sv_bh1; struct buffer_head *bh1 = sbi->s_bh1;
struct buffer_head *bh2 = sb->sv_bh2; struct buffer_head *bh2 = sbi->s_bh2;
struct xenix_super_block * sbd1; struct xenix_super_block * sbd1;
struct xenix_super_block * sbd2; struct xenix_super_block * sbd2;
...@@ -59,152 +58,153 @@ static void detected_xenix(struct super_block *sb) ...@@ -59,152 +58,153 @@ static void detected_xenix(struct super_block *sb)
sbd2 = (struct xenix_super_block *) (bh2->b_data - 512); sbd2 = (struct xenix_super_block *) (bh2->b_data - 512);
} }
sb->sv_link_max = XENIX_LINK_MAX; sbi->s_link_max = XENIX_LINK_MAX;
sb->sv_fic_size = XENIX_NICINOD; sbi->s_fic_size = XENIX_NICINOD;
sb->sv_flc_size = XENIX_NICFREE; sbi->s_flc_size = XENIX_NICFREE;
sb->sv_sbd1 = (char *) sbd1; sbi->s_sbd1 = (char *)sbd1;
sb->sv_sbd2 = (char *) sbd2; sbi->s_sbd2 = (char *)sbd2;
sb->sv_sb_fic_count = &sbd1->s_ninode; sbi->s_sb_fic_count = &sbd1->s_ninode;
sb->sv_sb_fic_inodes = &sbd1->s_inode[0]; sbi->s_sb_fic_inodes = &sbd1->s_inode[0];
sb->sv_sb_total_free_inodes = &sbd2->s_tinode; sbi->s_sb_total_free_inodes = &sbd2->s_tinode;
sb->sv_bcache_count = &sbd1->s_nfree; sbi->s_bcache_count = &sbd1->s_nfree;
sb->sv_bcache = &sbd1->s_free[0]; sbi->s_bcache = &sbd1->s_free[0];
sb->sv_free_blocks = &sbd2->s_tfree; sbi->s_free_blocks = &sbd2->s_tfree;
sb->sv_sb_time = &sbd2->s_time; sbi->s_sb_time = &sbd2->s_time;
sb->sv_firstdatazone = fs16_to_cpu(sb, sbd1->s_isize); sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd1->s_isize);
sb->sv_nzones = fs32_to_cpu(sb, sbd1->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd1->s_fsize);
} }
static void detected_sysv4(struct super_block *sb) static void detected_sysv4(struct sysv_sb_info *sbi)
{ {
struct sysv4_super_block * sbd; struct sysv4_super_block * sbd;
struct buffer_head *bh1 = sb->sv_bh1; struct buffer_head *bh1 = sbi->s_bh1;
struct buffer_head *bh2 = sb->sv_bh2; struct buffer_head *bh2 = sbi->s_bh2;
if (bh1 == bh2) if (bh1 == bh2)
sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2); sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2);
else else
sbd = (struct sysv4_super_block *) bh2->b_data; sbd = (struct sysv4_super_block *) bh2->b_data;
sb->sv_link_max = SYSV_LINK_MAX; sbi->s_link_max = SYSV_LINK_MAX;
sb->sv_fic_size = SYSV_NICINOD; sbi->s_fic_size = SYSV_NICINOD;
sb->sv_flc_size = SYSV_NICFREE; sbi->s_flc_size = SYSV_NICFREE;
sb->sv_sbd1 = (char *) sbd; sbi->s_sbd1 = (char *)sbd;
sb->sv_sbd2 = (char *) sbd; sbi->s_sbd2 = (char *)sbd;
sb->sv_sb_fic_count = &sbd->s_ninode; sbi->s_sb_fic_count = &sbd->s_ninode;
sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sbi->s_sb_fic_inodes = &sbd->s_inode[0];
sb->sv_sb_total_free_inodes = &sbd->s_tinode; sbi->s_sb_total_free_inodes = &sbd->s_tinode;
sb->sv_bcache_count = &sbd->s_nfree; sbi->s_bcache_count = &sbd->s_nfree;
sb->sv_bcache = &sbd->s_free[0]; sbi->s_bcache = &sbd->s_free[0];
sb->sv_free_blocks = &sbd->s_tfree; sbi->s_free_blocks = &sbd->s_tfree;
sb->sv_sb_time = &sbd->s_time; sbi->s_sb_time = &sbd->s_time;
sb->sv_sb_state = &sbd->s_state; sbi->s_sb_state = &sbd->s_state;
sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize);
sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_sysv2(struct super_block *sb) static void detected_sysv2(struct sysv_sb_info *sbi)
{ {
struct sysv2_super_block * sbd; struct sysv2_super_block *sbd;
struct buffer_head *bh1 = sb->sv_bh1; struct buffer_head *bh1 = sbi->s_bh1;
struct buffer_head *bh2 = sb->sv_bh2; struct buffer_head *bh2 = sbi->s_bh2;
if (bh1 == bh2) if (bh1 == bh2)
sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2); sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2);
else else
sbd = (struct sysv2_super_block *) bh2->b_data; sbd = (struct sysv2_super_block *) bh2->b_data;
sb->sv_link_max = SYSV_LINK_MAX; sbi->s_link_max = SYSV_LINK_MAX;
sb->sv_fic_size = SYSV_NICINOD; sbi->s_fic_size = SYSV_NICINOD;
sb->sv_flc_size = SYSV_NICFREE; sbi->s_flc_size = SYSV_NICFREE;
sb->sv_sbd1 = (char *) sbd; sbi->s_sbd1 = (char *)sbd;
sb->sv_sbd2 = (char *) sbd; sbi->s_sbd2 = (char *)sbd;
sb->sv_sb_fic_count = &sbd->s_ninode; sbi->s_sb_fic_count = &sbd->s_ninode;
sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sbi->s_sb_fic_inodes = &sbd->s_inode[0];
sb->sv_sb_total_free_inodes = &sbd->s_tinode; sbi->s_sb_total_free_inodes = &sbd->s_tinode;
sb->sv_bcache_count = &sbd->s_nfree; sbi->s_bcache_count = &sbd->s_nfree;
sb->sv_bcache = &sbd->s_free[0]; sbi->s_bcache = &sbd->s_free[0];
sb->sv_free_blocks = &sbd->s_tfree; sbi->s_free_blocks = &sbd->s_tfree;
sb->sv_sb_time = &sbd->s_time; sbi->s_sb_time = &sbd->s_time;
sb->sv_sb_state = &sbd->s_state; sbi->s_sb_state = &sbd->s_state;
sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize);
sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_coherent(struct super_block *sb) static void detected_coherent(struct sysv_sb_info *sbi)
{ {
struct coh_super_block * sbd; struct coh_super_block * sbd;
struct buffer_head *bh1 = sb->sv_bh1; struct buffer_head *bh1 = sbi->s_bh1;
sbd = (struct coh_super_block *) bh1->b_data; sbd = (struct coh_super_block *) bh1->b_data;
sb->sv_link_max = COH_LINK_MAX; sbi->s_link_max = COH_LINK_MAX;
sb->sv_fic_size = COH_NICINOD; sbi->s_fic_size = COH_NICINOD;
sb->sv_flc_size = COH_NICFREE; sbi->s_flc_size = COH_NICFREE;
sb->sv_sbd1 = (char *) sbd; sbi->s_sbd1 = (char *)sbd;
sb->sv_sbd2 = (char *) sbd; sbi->s_sbd2 = (char *)sbd;
sb->sv_sb_fic_count = &sbd->s_ninode; sbi->s_sb_fic_count = &sbd->s_ninode;
sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sbi->s_sb_fic_inodes = &sbd->s_inode[0];
sb->sv_sb_total_free_inodes = &sbd->s_tinode; sbi->s_sb_total_free_inodes = &sbd->s_tinode;
sb->sv_bcache_count = &sbd->s_nfree; sbi->s_bcache_count = &sbd->s_nfree;
sb->sv_bcache = &sbd->s_free[0]; sbi->s_bcache = &sbd->s_free[0];
sb->sv_free_blocks = &sbd->s_tfree; sbi->s_free_blocks = &sbd->s_tfree;
sb->sv_sb_time = &sbd->s_time; sbi->s_sb_time = &sbd->s_time;
sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize);
sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_v7(struct super_block *sb) static void detected_v7(struct sysv_sb_info *sbi)
{ {
struct buffer_head *bh2 = sb->sv_bh2; struct buffer_head *bh2 = sbi->s_bh2;
struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data; struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data;
sb->sv_link_max = V7_LINK_MAX; sbi->s_link_max = V7_LINK_MAX;
sb->sv_fic_size = V7_NICINOD; sbi->s_fic_size = V7_NICINOD;
sb->sv_flc_size = V7_NICFREE; sbi->s_flc_size = V7_NICFREE;
sb->sv_sbd1 = (char *)sbd; sbi->s_sbd1 = (char *)sbd;
sb->sv_sbd2 = (char *)sbd; sbi->s_sbd2 = (char *)sbd;
sb->sv_sb_fic_count = &sbd->s_ninode; sbi->s_sb_fic_count = &sbd->s_ninode;
sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sbi->s_sb_fic_inodes = &sbd->s_inode[0];
sb->sv_sb_total_free_inodes = &sbd->s_tinode; sbi->s_sb_total_free_inodes = &sbd->s_tinode;
sb->sv_bcache_count = &sbd->s_nfree; sbi->s_bcache_count = &sbd->s_nfree;
sb->sv_bcache = &sbd->s_free[0]; sbi->s_bcache = &sbd->s_free[0];
sb->sv_free_blocks = &sbd->s_tfree; sbi->s_free_blocks = &sbd->s_tfree;
sb->sv_sb_time = &sbd->s_time; sbi->s_sb_time = &sbd->s_time;
sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize);
sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static int detect_xenix (struct super_block *sb, struct buffer_head *bh) static int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh)
{ {
struct xenix_super_block * sbd = (struct xenix_super_block *)bh->b_data; struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data;
if (sbd->s_magic == cpu_to_le32(0x2b5544)) if (sbd->s_magic == cpu_to_le32(0x2b5544))
sb->sv_bytesex = BYTESEX_LE; sbi->s_bytesex = BYTESEX_LE;
else if (sbd->s_magic == cpu_to_be32(0x2b5544)) else if (sbd->s_magic == cpu_to_be32(0x2b5544))
sb->sv_bytesex = BYTESEX_BE; sbi->s_bytesex = BYTESEX_BE;
else else
return 0; return 0;
if (sbd->s_type > 2 || sbd->s_type < 1) if (sbd->s_type > 2 || sbd->s_type < 1)
return 0; return 0;
sb->sv_type = FSTYPE_XENIX; sbi->s_type = FSTYPE_XENIX;
return sbd->s_type; return sbd->s_type;
} }
static int detect_sysv (struct super_block *sb, struct buffer_head *bh) static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
{ {
struct super_block *sb = sbi->s_sb;
/* All relevant fields are at the same offsets in R2 and R4 */ /* All relevant fields are at the same offsets in R2 and R4 */
struct sysv4_super_block * sbd; struct sysv4_super_block * sbd;
sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
if (sbd->s_magic == cpu_to_le32(0xfd187e20)) if (sbd->s_magic == cpu_to_le32(0xfd187e20))
sb->sv_bytesex = BYTESEX_LE; sbi->s_bytesex = BYTESEX_LE;
else if (sbd->s_magic == cpu_to_be32(0xfd187e20)) else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
sb->sv_bytesex = BYTESEX_BE; sbi->s_bytesex = BYTESEX_BE;
else else
return 0; return 0;
if (fs16_to_cpu(sb, sbd->s_nfree) == 0xffff) { if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) {
sb->sv_type = FSTYPE_AFS; sbi->s_type = FSTYPE_AFS;
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
printk("SysV FS: SCO EAFS on %s detected, " printk("SysV FS: SCO EAFS on %s detected, "
"forcing read-only mode.\n", "forcing read-only mode.\n",
...@@ -214,11 +214,11 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh) ...@@ -214,11 +214,11 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh)
return sbd->s_type; return sbd->s_type;
} }
if (fs32_to_cpu(sb, sbd->s_time) < JAN_1_1980) { if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) {
/* this is likely to happen on SystemV2 FS */ /* this is likely to happen on SystemV2 FS */
if (sbd->s_type > 3 || sbd->s_type < 1) if (sbd->s_type > 3 || sbd->s_type < 1)
return 0; return 0;
sb->sv_type = FSTYPE_SYSV2; sbi->s_type = FSTYPE_SYSV2;
return sbd->s_type; return sbd->s_type;
} }
if ((sbd->s_type > 3 || sbd->s_type < 1) && if ((sbd->s_type > 3 || sbd->s_type < 1) &&
...@@ -236,11 +236,11 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh) ...@@ -236,11 +236,11 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh)
sb->s_flags |= MS_RDONLY; sb->s_flags |= MS_RDONLY;
} }
sb->sv_type = FSTYPE_SYSV4; sbi->s_type = FSTYPE_SYSV4;
return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type; return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
} }
static int detect_coherent (struct super_block *sb, struct buffer_head *bh) static int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh)
{ {
struct coh_super_block * sbd; struct coh_super_block * sbd;
...@@ -248,21 +248,21 @@ static int detect_coherent (struct super_block *sb, struct buffer_head *bh) ...@@ -248,21 +248,21 @@ static int detect_coherent (struct super_block *sb, struct buffer_head *bh)
if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6))
|| (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6)))
return 0; return 0;
sb->sv_bytesex = BYTESEX_PDP; sbi->s_bytesex = BYTESEX_PDP;
sb->sv_type = FSTYPE_COH; sbi->s_type = FSTYPE_COH;
return 1; return 1;
} }
static int detect_sysv_odd(struct super_block *sb, struct buffer_head *bh) static int detect_sysv_odd(struct sysv_sb_info *sbi, struct buffer_head *bh)
{ {
int size = detect_sysv(sb, bh); int size = detect_sysv(sbi, bh);
return size>2 ? 0 : size; return size>2 ? 0 : size;
} }
static struct { static struct {
int block; int block;
int (*test)(struct super_block *, struct buffer_head *); int (*test)(struct sysv_sb_info *, struct buffer_head *);
} flavours[] = { } flavours[] = {
{1, detect_xenix}, {1, detect_xenix},
{0, detect_sysv}, {0, detect_sysv},
...@@ -281,7 +281,7 @@ static char *flavour_names[] = { ...@@ -281,7 +281,7 @@ static char *flavour_names[] = {
[FSTYPE_AFS] "AFS", [FSTYPE_AFS] "AFS",
}; };
static void (*flavour_setup[])(struct super_block *) = { static void (*flavour_setup[])(struct sysv_sb_info *) = {
[FSTYPE_XENIX] detected_xenix, [FSTYPE_XENIX] detected_xenix,
[FSTYPE_SYSV4] detected_sysv4, [FSTYPE_SYSV4] detected_sysv4,
[FSTYPE_SYSV2] detected_sysv2, [FSTYPE_SYSV2] detected_sysv2,
...@@ -292,34 +292,35 @@ static void (*flavour_setup[])(struct super_block *) = { ...@@ -292,34 +292,35 @@ static void (*flavour_setup[])(struct super_block *) = {
static int complete_read_super(struct super_block *sb, int silent, int size) static int complete_read_super(struct super_block *sb, int silent, int size)
{ {
struct sysv_sb_info *sbi = SYSV_SB(sb);
struct inode *root_inode; struct inode *root_inode;
char *found = flavour_names[sb->sv_type]; char *found = flavour_names[sbi->s_type];
u_char n_bits = size+8; u_char n_bits = size+8;
int bsize = 1 << n_bits; int bsize = 1 << n_bits;
int bsize_4 = bsize >> 2; int bsize_4 = bsize >> 2;
sb->sv_firstinodezone = 2; sbi->s_firstinodezone = 2;
flavour_setup[sb->sv_type](sb); flavour_setup[sbi->s_type](sbi);
sb->sv_truncate = 1; sbi->s_truncate = 1;
sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone;
sb->sv_inodes_per_block = bsize >> 6; sbi->s_inodes_per_block = bsize >> 6;
sb->sv_inodes_per_block_1 = (bsize >> 6)-1; sbi->s_inodes_per_block_1 = (bsize >> 6)-1;
sb->sv_inodes_per_block_bits = n_bits-6; sbi->s_inodes_per_block_bits = n_bits-6;
sb->sv_ind_per_block = bsize_4; sbi->s_ind_per_block = bsize_4;
sb->sv_ind_per_block_2 = bsize_4*bsize_4; sbi->s_ind_per_block_2 = bsize_4*bsize_4;
sb->sv_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4)); sbi->s_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4));
sb->sv_ind_per_block_bits = n_bits-2; sbi->s_ind_per_block_bits = n_bits-2;
sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) sbi->s_ninodes = (sbi->s_firstdatazone - sbi->s_firstinodezone)
<< sb->sv_inodes_per_block_bits; << sbi->s_inodes_per_block_bits;
if (!silent) if (!silent)
printk("VFS: Found a %s FS (block size = %ld) on device %s\n", printk("VFS: Found a %s FS (block size = %ld) on device %s\n",
found, sb->s_blocksize, sb->s_id); found, sb->s_blocksize, sb->s_id);
sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; sb->s_magic = SYSV_MAGIC_BASE + sbi->s_type;
/* set up enough so that it can read an inode */ /* set up enough so that it can read an inode */
sb->s_op = &sysv_sops; sb->s_op = &sysv_sops;
root_inode = iget(sb,SYSV_ROOT_INO); root_inode = iget(sb,SYSV_ROOT_INO);
...@@ -333,7 +334,7 @@ static int complete_read_super(struct super_block *sb, int silent, int size) ...@@ -333,7 +334,7 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
printk("SysV FS: get root dentry failed\n"); printk("SysV FS: get root dentry failed\n");
return 0; return 0;
} }
if (sb->sv_truncate) if (sbi->s_truncate)
sb->s_root->d_op = &sysv_dentry_operations; sb->s_root->d_op = &sysv_dentry_operations;
sb->s_flags |= MS_RDONLY; sb->s_flags |= MS_RDONLY;
sb->s_dirt = 1; sb->s_dirt = 1;
...@@ -342,30 +343,39 @@ static int complete_read_super(struct super_block *sb, int silent, int size) ...@@ -342,30 +343,39 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
static int sysv_fill_super(struct super_block *sb, void *data, int silent) static int sysv_fill_super(struct super_block *sb, void *data, int silent)
{ {
struct buffer_head *bh1; struct buffer_head *bh1, *bh = NULL;
struct buffer_head *bh = NULL; struct sysv_sb_info *sbi;
unsigned long blocknr; unsigned long blocknr;
int size = 0; int size = 0, i;
int i;
if (1024 != sizeof (struct xenix_super_block)) if (1024 != sizeof (struct xenix_super_block))
panic("Xenix FS: bad super-block size"); panic("Xenix FS: bad superblock size");
if ((512 != sizeof (struct sysv4_super_block)) if (512 != sizeof (struct sysv4_super_block))
|| (512 != sizeof (struct sysv2_super_block))) panic("SystemV FS: bad superblock size");
panic("SystemV FS: bad super-block size"); if (512 != sizeof (struct sysv2_super_block))
panic("SystemV FS: bad superblock size");
if (500 != sizeof (struct coh_super_block)) if (500 != sizeof (struct coh_super_block))
panic("Coherent FS: bad super-block size"); panic("Coherent FS: bad superblock size");
if (64 != sizeof (struct sysv_inode)) if (64 != sizeof (struct sysv_inode))
panic("sysv fs: bad i-node size"); panic("sysv fs: bad inode size");
sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
memset(sbi, 0, sizeof(struct sysv_sb_info));
sbi->s_sb = sb;
sbi->s_block_base = 0;
sb->u.generic_sbp = sbi;
sb_set_blocksize(sb, BLOCK_SIZE); sb_set_blocksize(sb, BLOCK_SIZE);
sb->sv_block_base = 0;
for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) { for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) {
brelse(bh); brelse(bh);
bh = sb_bread(sb, flavours[i].block); bh = sb_bread(sb, flavours[i].block);
if (!bh) if (!bh)
continue; continue;
size = flavours[i].test(sb, bh); size = flavours[i].test(SYSV_SB(sb), bh);
} }
if (!size) if (!size)
...@@ -393,8 +403,8 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) ...@@ -393,8 +403,8 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
} }
if (bh && bh1) { if (bh && bh1) {
sb->sv_bh1 = bh1; sbi->s_bh1 = bh1;
sb->sv_bh2 = bh; sbi->s_bh2 = bh;
if (complete_read_super(sb, silent, size)) if (complete_read_super(sb, silent, size))
return 0; return 0;
} }
...@@ -404,6 +414,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) ...@@ -404,6 +414,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
sb_set_blocksize(sb, BLOCK_SIZE); sb_set_blocksize(sb, BLOCK_SIZE);
printk("oldfs: cannot read superblock\n"); printk("oldfs: cannot read superblock\n");
failed: failed:
kfree(sbi);
return -EINVAL; return -EINVAL;
Eunknown: Eunknown:
...@@ -422,6 +433,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) ...@@ -422,6 +433,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
static int v7_fill_super(struct super_block *sb, void *data, int silent) static int v7_fill_super(struct super_block *sb, void *data, int silent)
{ {
struct sysv_sb_info *sbi;
struct buffer_head *bh, *bh2 = NULL; struct buffer_head *bh, *bh2 = NULL;
struct v7_super_block *v7sb; struct v7_super_block *v7sb;
struct sysv_inode *v7i; struct sysv_inode *v7i;
...@@ -431,8 +443,16 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) ...@@ -431,8 +443,16 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
if (64 != sizeof (struct sysv_inode)) if (64 != sizeof (struct sysv_inode))
panic("sysv fs: bad i-node size"); panic("sysv fs: bad i-node size");
sb->sv_type = FSTYPE_V7; sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
sb->sv_bytesex = BYTESEX_PDP; if (!sbi)
return -ENOMEM;
memset(sbi, 0, sizeof(struct sysv_sb_info));
sbi->s_sb = sb;
sbi->s_block_base = 0;
sbi->s_type = FSTYPE_V7;
sbi->s_bytesex = BYTESEX_PDP;
sb->u.generic_sbp = sbi;
sb_set_blocksize(sb, 512); sb_set_blocksize(sb, 512);
...@@ -445,9 +465,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) ...@@ -445,9 +465,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
/* plausibility check on superblock */ /* plausibility check on superblock */
v7sb = (struct v7_super_block *) bh->b_data; v7sb = (struct v7_super_block *) bh->b_data;
if (fs16_to_cpu(sb,v7sb->s_nfree) > V7_NICFREE || if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
fs16_to_cpu(sb,v7sb->s_ninode) > V7_NICINOD || fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
fs32_to_cpu(sb,v7sb->s_time) == 0) fs32_to_cpu(sbi, v7sb->s_time) == 0)
goto failed; goto failed;
/* plausibility check on root inode: it is a directory, /* plausibility check on root inode: it is a directory,
...@@ -455,20 +475,21 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) ...@@ -455,20 +475,21 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
if ((bh2 = sb_bread(sb, 2)) == NULL) if ((bh2 = sb_bread(sb, 2)) == NULL)
goto failed; goto failed;
v7i = (struct sysv_inode *)(bh2->b_data + 64); v7i = (struct sysv_inode *)(bh2->b_data + 64);
if ((fs16_to_cpu(sb,v7i->i_mode) & ~0777) != S_IFDIR || if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
(fs32_to_cpu(sb,v7i->i_size) == 0) || (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
(fs32_to_cpu(sb,v7i->i_size) & 017) != 0) (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
goto failed; goto failed;
brelse(bh2); brelse(bh2);
sb->sv_bh1 = bh; sbi->s_bh1 = bh;
sb->sv_bh2 = bh; sbi->s_bh2 = bh;
if (complete_read_super(sb, silent, 1)) if (complete_read_super(sb, silent, 1))
return 0; return 0;
failed: failed:
brelse(bh2); brelse(bh2);
brelse(bh); brelse(bh);
kfree(sbi);
return -EINVAL; return -EINVAL;
} }
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
* Aug 2001, Christoph Hellwig (hch@infradead.org) * Aug 2001, Christoph Hellwig (hch@infradead.org)
*/ */
#include <linux/fs.h> #include "sysv.h"
#include <linux/sysv_fs.h>
static int sysv_readlink(struct dentry *dentry, char *buffer, int buflen) static int sysv_readlink(struct dentry *dentry, char *buffer, int buflen)
{ {
......
#ifndef _SYSV_FS_SB #ifndef _SYSV_H
#define _SYSV_FS_SB #define _SYSV_H
#include <linux/fs.h>
#include <linux/sysv_fs.h>
/* /*
* SystemV/V7/Coherent super-block data in memory * SystemV/V7/Coherent super-block data in memory
*
* The SystemV/V7/Coherent superblock contains dynamic data (it gets modified * The SystemV/V7/Coherent superblock contains dynamic data (it gets modified
* while the system is running). This is in contrast to the Minix and Berkeley * while the system is running). This is in contrast to the Minix and Berkeley
* filesystems (where the superblock is never modified). This affects the * filesystems (where the superblock is never modified). This affects the
...@@ -11,6 +15,7 @@ ...@@ -11,6 +15,7 @@
*/ */
struct sysv_sb_info { struct sysv_sb_info {
struct super_block *s_sb; /* VFS superblock */
int s_type; /* file system type: FSTYPE_{XENIX|SYSV|COH} */ int s_type; /* file system type: FSTYPE_{XENIX|SYSV|COH} */
char s_bytesex; /* bytesex (le/be/pdp) */ char s_bytesex; /* bytesex (le/be/pdp) */
char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */ char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
...@@ -50,40 +55,182 @@ struct sysv_sb_info { ...@@ -50,40 +55,182 @@ struct sysv_sb_info {
u32 s_nzones; /* same as s_sbd->s_fsize */ u32 s_nzones; /* same as s_sbd->s_fsize */
u16 s_namelen; /* max length of dir entry */ u16 s_namelen; /* max length of dir entry */
}; };
/* The field s_toobig_block is currently unused. */
/* sv_ == u.sysv_sb.s_ */
#define sv_type u.sysv_sb.s_type
#define sv_bytesex u.sysv_sb.s_bytesex
#define sv_truncate u.sysv_sb.s_truncate
#define sv_link_max u.sysv_sb.s_link_max
#define sv_inodes_per_block u.sysv_sb.s_inodes_per_block
#define sv_inodes_per_block_1 u.sysv_sb.s_inodes_per_block_1
#define sv_inodes_per_block_bits u.sysv_sb.s_inodes_per_block_bits
#define sv_ind_per_block u.sysv_sb.s_ind_per_block
#define sv_ind_per_block_bits u.sysv_sb.s_ind_per_block_bits
#define sv_ind_per_block_2 u.sysv_sb.s_ind_per_block_2
#define sv_toobig_block u.sysv_sb.s_toobig_block
#define sv_block_base u.sysv_sb.s_block_base
#define sv_fic_size u.sysv_sb.s_fic_size
#define sv_flc_size u.sysv_sb.s_flc_size
#define sv_bh1 u.sysv_sb.s_bh1
#define sv_bh2 u.sysv_sb.s_bh2
#define sv_sbd1 u.sysv_sb.s_sbd1
#define sv_sbd2 u.sysv_sb.s_sbd2
#define sv_sb_fic_count u.sysv_sb.s_sb_fic_count
#define sv_sb_fic_inodes u.sysv_sb.s_sb_fic_inodes
#define sv_sb_total_free_inodes u.sysv_sb.s_sb_total_free_inodes
#define sv_bcache_count u.sysv_sb.s_bcache_count
#define sv_bcache u.sysv_sb.s_bcache
#define sv_free_blocks u.sysv_sb.s_free_blocks
#define sv_sb_time u.sysv_sb.s_sb_time
#define sv_sb_state u.sysv_sb.s_sb_state
#define sv_firstinodezone u.sysv_sb.s_firstinodezone
#define sv_firstdatazone u.sysv_sb.s_firstdatazone
#define sv_ninodes u.sysv_sb.s_ninodes
#define sv_ndatazones u.sysv_sb.s_ndatazones
#define sv_nzones u.sysv_sb.s_nzones
#define sv_namelen u.sysv_sb.s_namelen
/*
* SystemV/V7/Coherent FS inode data in memory
*/
struct sysv_inode_info {
u32 i_data[13];
u32 i_dir_start_lookup;
struct inode vfs_inode;
};
static inline struct sysv_inode_info *SYSV_I(struct inode *inode)
{
return list_entry(inode, struct sysv_inode_info, vfs_inode);
}
static inline struct sysv_sb_info *SYSV_SB(struct super_block *sb)
{
return sb->u.generic_sbp;
}
/* identify the FS in memory */
enum {
FSTYPE_NONE = 0,
FSTYPE_XENIX,
FSTYPE_SYSV4,
FSTYPE_SYSV2,
FSTYPE_COH,
FSTYPE_V7,
FSTYPE_AFS,
FSTYPE_END,
};
#define SYSV_MAGIC_BASE 0x012FF7B3
#define XENIX_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_XENIX)
#define SYSV4_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV4)
#define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV2)
#define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_COH)
/* Admissible values for i_nlink: 0.._LINK_MAX */
enum {
XENIX_LINK_MAX = 126, /* ?? */
SYSV_LINK_MAX = 126, /* 127? 251? */
V7_LINK_MAX = 126, /* ?? */
COH_LINK_MAX = 10000,
};
static inline void dirty_sb(struct super_block *sb)
{
struct sysv_sb_info *sbi = SYSV_SB(sb);
mark_buffer_dirty(sbi->s_bh1);
if (sbi->s_bh1 != sbi->s_bh2)
mark_buffer_dirty(sbi->s_bh2);
sb->s_dirt = 1;
}
/* ialloc.c */
extern struct sysv_inode *sysv_raw_inode(struct super_block *, unsigned,
struct buffer_head **);
extern struct inode * sysv_new_inode(const struct inode *, mode_t);
extern void sysv_free_inode(struct inode *);
extern unsigned long sysv_count_free_inodes(struct super_block *);
/* balloc.c */
extern u32 sysv_new_block(struct super_block *);
extern void sysv_free_block(struct super_block *, u32);
extern unsigned long sysv_count_free_blocks(struct super_block *);
/* itree.c */
extern void sysv_truncate(struct inode *);
/* inode.c */
extern void sysv_write_inode(struct inode *, int);
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *, int);
extern void sysv_set_inode(struct inode *, dev_t);
/* dir.c */
extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
extern int sysv_add_link(struct dentry *, struct inode *);
extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
extern int sysv_make_empty(struct inode *, struct inode *);
extern int sysv_empty_dir(struct inode *);
extern void sysv_set_link(struct sysv_dir_entry *, struct page *,
struct inode *);
extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **);
extern ino_t sysv_inode_by_name(struct dentry *);
extern struct inode_operations sysv_file_inode_operations;
extern struct inode_operations sysv_dir_inode_operations;
extern struct inode_operations sysv_fast_symlink_inode_operations;
extern struct file_operations sysv_file_operations;
extern struct file_operations sysv_dir_operations;
extern struct address_space_operations sysv_aops;
extern struct super_operations sysv_sops;
extern struct dentry_operations sysv_dentry_operations;
enum {
BYTESEX_LE,
BYTESEX_PDP,
BYTESEX_BE,
};
static inline u32 PDP_swab(u32 x)
{
#ifdef __LITTLE_ENDIAN
return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
#else
#ifdef __BIG_ENDIAN
return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
#else
#error BYTESEX
#endif
#endif #endif
}
static inline u32 fs32_to_cpu(struct sysv_sb_info *sbi, u32 n)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return PDP_swab(n);
else if (sbi->s_bytesex == BYTESEX_LE)
return le32_to_cpu(n);
else
return be32_to_cpu(n);
}
static inline u32 cpu_to_fs32(struct sysv_sb_info *sbi, u32 n)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return PDP_swab(n);
else if (sbi->s_bytesex == BYTESEX_LE)
return cpu_to_le32(n);
else
return cpu_to_be32(n);
}
static inline u32 fs32_add(struct sysv_sb_info *sbi, u32 *n, int d)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return *n = PDP_swab(PDP_swab(*n)+d);
else if (sbi->s_bytesex == BYTESEX_LE)
return *n = cpu_to_le32(le32_to_cpu(*n)+d);
else
return *n = cpu_to_be32(be32_to_cpu(*n)+d);
}
static inline u16 fs16_to_cpu(struct sysv_sb_info *sbi, u16 n)
{
if (sbi->s_bytesex != BYTESEX_BE)
return le16_to_cpu(n);
else
return be16_to_cpu(n);
}
static inline u16 cpu_to_fs16(struct sysv_sb_info *sbi, u16 n)
{
if (sbi->s_bytesex != BYTESEX_BE)
return cpu_to_le16(n);
else
return cpu_to_be16(n);
}
static inline u16 fs16_add(struct sysv_sb_info *sbi, u16 *n, int d)
{
if (sbi->s_bytesex != BYTESEX_BE)
return *n = cpu_to_le16(le16_to_cpu(*n)+d);
else
return *n = cpu_to_be16(be16_to_cpu(*n)+d);
}
#endif /* _SYSV_H */
...@@ -679,7 +679,6 @@ struct quota_mount_options ...@@ -679,7 +679,6 @@ struct quota_mount_options
#include <linux/ext3_fs_sb.h> #include <linux/ext3_fs_sb.h>
#include <linux/hpfs_fs_sb.h> #include <linux/hpfs_fs_sb.h>
#include <linux/sysv_fs_sb.h>
#include <linux/ufs_fs_sb.h> #include <linux/ufs_fs_sb.h>
#include <linux/romfs_fs_sb.h> #include <linux/romfs_fs_sb.h>
#include <linux/adfs_fs_sb.h> #include <linux/adfs_fs_sb.h>
...@@ -723,7 +722,6 @@ struct super_block { ...@@ -723,7 +722,6 @@ struct super_block {
union { union {
struct ext3_sb_info ext3_sb; struct ext3_sb_info ext3_sb;
struct hpfs_sb_info hpfs_sb; struct hpfs_sb_info hpfs_sb;
struct sysv_sb_info sysv_sb;
struct ufs_sb_info ufs_sb; struct ufs_sb_info ufs_sb;
struct romfs_sb_info romfs_sb; struct romfs_sb_info romfs_sb;
struct adfs_sb_info adfs_sb; struct adfs_sb_info adfs_sb;
......
#ifndef _LINUX_SYSV_FS_H #ifndef _LINUX_SYSV_FS_H
#define _LINUX_SYSV_FS_H #define _LINUX_SYSV_FS_H
/* #if defined(__GNUC__)
* The SystemV/Coherent filesystem constants/structures/macros # define __packed2__ __attribute__((packed, aligned(2)))
*/
/* This code assumes
- sizeof(short) = 2, sizeof(int) = 4, sizeof(long) = 4,
- alignof(short) = 2, alignof(long) = 4.
*/
#ifdef __GNUC__
#define __packed2__ __attribute__ ((packed, aligned(2)))
#else #else
#error I want gcc! >> I want to scream! <<
#endif #endif
#include <linux/stat.h> /* declares S_IFLNK etc. */
#include <linux/sched.h> /* declares wake_up() */
#include <linux/sysv_fs_sb.h> /* defines the sv_... shortcuts */
/* temporary hack. */
#include <linux/sysv_fs_i.h>
static inline struct sysv_inode_info *SYSV_I(struct inode *inode)
{
/* I think list_entry should have a more descriptive name.. --hch */
return list_entry(inode, struct sysv_inode_info, vfs_inode);
}
/* end temporary hack. */
/* Layout on disk */
/* ============== */
static inline u32 PDP_swab(u32 x)
{
#ifdef __LITTLE_ENDIAN
return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
#else
#ifdef __BIG_ENDIAN
return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
#else
#error BYTESEX
#endif
#endif
}
/* inode numbers are 16 bit */ /* inode numbers are 16 bit */
typedef u16 sysv_ino_t; typedef u16 sysv_ino_t;
/* Block numbers are 24 bit, sometimes stored in 32 bit. /* Block numbers are 24 bit, sometimes stored in 32 bit.
On Coherent FS, they are always stored in PDP-11 manner: the least On Coherent FS, they are always stored in PDP-11 manner: the least
significant 16 bits come last. significant 16 bits come last. */
*/
typedef u32 sysv_zone_t; typedef u32 sysv_zone_t;
/* Among the blocks ... */
/* Xenix FS, Coherent FS: block 0 is the boot block, block 1 the super-block.
SystemV FS: block 0 contains both the boot sector and the super-block. */
/* The first inode zone is sb->sv_firstinodezone (1 or 2). */
/* Among the inodes ... */
/* 0 is non-existent */ /* 0 is non-existent */
#define SYSV_BADBL_INO 1 /* inode of bad blocks file */ #define SYSV_BADBL_INO 1 /* inode of bad blocks file */
#define SYSV_ROOT_INO 2 /* inode of root directory */ #define SYSV_ROOT_INO 2 /* inode of root directory */
...@@ -101,7 +53,8 @@ struct xenix_super_block { ...@@ -101,7 +53,8 @@ struct xenix_super_block {
}; };
/* SystemV FS comes in two variants: /*
* SystemV FS comes in two variants:
* sysv2: System V Release 2 (e.g. Microport), structure elements aligned(2). * sysv2: System V Release 2 (e.g. Microport), structure elements aligned(2).
* sysv4: System V Release 4 (e.g. Consensys), structure elements aligned(4). * sysv4: System V Release 4 (e.g. Consensys), structure elements aligned(4).
*/ */
...@@ -223,51 +176,21 @@ struct coh_super_block { ...@@ -223,51 +176,21 @@ struct coh_super_block {
}; };
/* SystemV/Coherent inode data on disk */ /* SystemV/Coherent inode data on disk */
struct sysv_inode { struct sysv_inode {
u16 i_mode; u16 i_mode;
u16 i_nlink; u16 i_nlink;
u16 i_uid; u16 i_uid;
u16 i_gid; u16 i_gid;
u32 i_size; u32 i_size;
union { /* directories, regular files, ... */ u8 i_data[3*(10+1+1+1)];
unsigned char i_addb[3*(10+1+1+1)+1]; /* zone numbers: max. 10 data blocks, u8 i_gen;
* then 1 indirection block,
* then 1 double indirection block,
* then 1 triple indirection block.
* Then maybe a "file generation number" ??
*/
/* named pipes on Coherent */
struct {
char p_addp[30];
s16 p_pnc;
s16 p_prx;
s16 p_pwx;
} i_p;
} i_a;
u32 i_atime; /* time of last access */ u32 i_atime; /* time of last access */
u32 i_mtime; /* time of last modification */ u32 i_mtime; /* time of last modification */
u32 i_ctime; /* time of creation */ u32 i_ctime; /* time of creation */
}; };
/* Admissible values for i_nlink: 0.._LINK_MAX */
enum {
XENIX_LINK_MAX = 126, /* ?? */
SYSV_LINK_MAX = 126, /* 127? 251? */
V7_LINK_MAX = 126, /* ?? */
COH_LINK_MAX = 10000,
};
/* The number of inodes per block is
sb->sv_inodes_per_block = block_size / sizeof(struct sysv_inode) */
/* The number of indirect pointers per block is
sb->sv_ind_per_block = block_size / sizeof(u32) */
/* SystemV/Coherent directory entry on disk */ /* SystemV/Coherent directory entry on disk */
#define SYSV_NAMELEN 14 /* max size of name in struct sysv_dir_entry */ #define SYSV_NAMELEN 14 /* max size of name in struct sysv_dir_entry */
struct sysv_dir_entry { struct sysv_dir_entry {
sysv_ino_t inode; sysv_ino_t inode;
char name[SYSV_NAMELEN]; /* up to 14 characters, the rest are zeroes */ char name[SYSV_NAMELEN]; /* up to 14 characters, the rest are zeroes */
...@@ -275,137 +198,4 @@ struct sysv_dir_entry { ...@@ -275,137 +198,4 @@ struct sysv_dir_entry {
#define SYSV_DIRSIZE sizeof(struct sysv_dir_entry) /* size of every directory entry */ #define SYSV_DIRSIZE sizeof(struct sysv_dir_entry) /* size of every directory entry */
#endif /* _LINUX_SYSV_FS_H */
/* Operations */
/* ========== */
/* identify the FS in memory */
enum {
FSTYPE_NONE = 0,
FSTYPE_XENIX,
FSTYPE_SYSV4,
FSTYPE_SYSV2,
FSTYPE_COH,
FSTYPE_V7,
FSTYPE_AFS,
FSTYPE_END,
};
#define SYSV_MAGIC_BASE 0x012FF7B3
#define XENIX_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_XENIX)
#define SYSV4_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV4)
#define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV2)
#define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_COH)
#ifdef __KERNEL__
enum {
BYTESEX_LE,
BYTESEX_PDP,
BYTESEX_BE,
};
/*
* Function prototypes
*/
extern struct inode * sysv_new_inode(const struct inode *, mode_t);
extern void sysv_free_inode(struct inode *);
extern unsigned long sysv_count_free_inodes(struct super_block *);
extern u32 sysv_new_block(struct super_block *);
extern void sysv_free_block(struct super_block *, u32);
extern unsigned long sysv_count_free_blocks(struct super_block *);
extern void sysv_truncate(struct inode *);
extern void sysv_write_inode(struct inode *, int);
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *, int);
extern void sysv_set_inode(struct inode *, dev_t);
extern struct sysv_dir_entry *sysv_find_entry(struct dentry*, struct page**);
extern int sysv_add_link(struct dentry*, struct inode*);
extern int sysv_delete_entry(struct sysv_dir_entry*, struct page*);
extern int sysv_make_empty(struct inode*, struct inode*);
extern int sysv_empty_dir(struct inode*);
extern void sysv_set_link(struct sysv_dir_entry*, struct page*, struct inode*);
extern struct sysv_dir_entry *sysv_dotdot(struct inode*, struct page**);
extern ino_t sysv_inode_by_name(struct dentry*);
extern struct inode_operations sysv_file_inode_operations;
extern struct inode_operations sysv_dir_inode_operations;
extern struct inode_operations sysv_fast_symlink_inode_operations;
extern struct file_operations sysv_file_operations;
extern struct file_operations sysv_dir_operations;
extern struct address_space_operations sysv_aops;
extern struct super_operations sysv_sops;
extern struct dentry_operations sysv_dentry_operations;
extern struct sysv_inode *sysv_raw_inode(struct super_block *, unsigned, struct buffer_head **);
static inline void dirty_sb(struct super_block *sb)
{
mark_buffer_dirty(sb->sv_bh1);
if (sb->sv_bh1 != sb->sv_bh2)
mark_buffer_dirty(sb->sv_bh2);
sb->s_dirt = 1;
}
static inline u32 fs32_to_cpu(struct super_block *sb, u32 n)
{
if (sb->sv_bytesex == BYTESEX_PDP)
return PDP_swab(n);
else if (sb->sv_bytesex == BYTESEX_LE)
return le32_to_cpu(n);
else
return be32_to_cpu(n);
}
static inline u32 cpu_to_fs32(struct super_block *sb, u32 n)
{
if (sb->sv_bytesex == BYTESEX_PDP)
return PDP_swab(n);
else if (sb->sv_bytesex == BYTESEX_LE)
return cpu_to_le32(n);
else
return cpu_to_be32(n);
}
static inline u32 fs32_add(struct super_block *sb, u32 *n, int d)
{
if (sb->sv_bytesex == BYTESEX_PDP)
return *n = PDP_swab(PDP_swab(*n)+d);
else if (sb->sv_bytesex == BYTESEX_LE)
return *n = cpu_to_le32(le32_to_cpu(*n)+d);
else
return *n = cpu_to_be32(be32_to_cpu(*n)+d);
}
static inline u16 fs16_to_cpu(struct super_block *sb, u16 n)
{
if (sb->sv_bytesex != BYTESEX_BE)
return le16_to_cpu(n);
else
return be16_to_cpu(n);
}
static inline u16 cpu_to_fs16(struct super_block *sb, u16 n)
{
if (sb->sv_bytesex != BYTESEX_BE)
return cpu_to_le16(n);
else
return cpu_to_be16(n);
}
static inline u16 fs16_add(struct super_block *sb, u16 *n, int d)
{
if (sb->sv_bytesex != BYTESEX_BE)
return *n = cpu_to_le16(le16_to_cpu(*n)+d);
else
return *n = cpu_to_be16(be16_to_cpu(*n)+d);
}
#endif /* __KERNEL__ */
#endif
#ifndef _SYSV_FS_I
#define _SYSV_FS_I
/*
* SystemV/V7/Coherent FS inode data in memory
*/
struct sysv_inode_info {
u32 i_data[10+1+1+1]; /* zone numbers: max. 10 data blocks,
* then 1 indirection block,
* then 1 double indirection block,
* then 1 triple indirection block.
*/
u32 i_dir_start_lookup;
struct inode vfs_inode;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment