summaryrefslogtreecommitdiffstats
path: root/fs/affs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/affs')
-rw-r--r--fs/affs/Changes95
-rw-r--r--fs/affs/amigaffs.c96
-rw-r--r--fs/affs/bitmap.c52
-rw-r--r--fs/affs/dir.c25
-rw-r--r--fs/affs/file.c99
-rw-r--r--fs/affs/inode.c201
-rw-r--r--fs/affs/namei.c37
-rw-r--r--fs/affs/symlink.c4
8 files changed, 400 insertions, 209 deletions
diff --git a/fs/affs/Changes b/fs/affs/Changes
new file mode 100644
index 000000000..a65dc326a
--- /dev/null
+++ b/fs/affs/Changes
@@ -0,0 +1,95 @@
+(Note: I consider version numbers as cheap. That means
+that I do not like numbers like 0.1 and the like for
+things that can be used since quite some time. But
+then, 3.1 doesn't mean 'perfectly stable', too.)
+
+Known bugs:
+-----------
+
+- Doesn't work on the alpha. The only 64/32-bit
+ problem that I'm aware of (pointer/int conversion
+ in readdir()) gives compiler warnings but is
+ apparently not causing the failure, as directory
+ reads basically work (but all files are of size 0).
+ Alas, I've got no alpha to debug. :-(
+- If an affs mounted filesystem is exported via
+ nfs, it cannot be written to. No networking to
+ test that, either. :-(
+
+Please direct bug reports to: hjw@zvw.de
+
+Version 3.4
+-----------
+
+- Hash chains are now sorted by block numbers.
+ (Thanks to Kars de Jong for finding this.)
+- Removed all unnecessary external symbols.
+
+Version 3.3
+-----------
+
+- Tried to make all types 'correct' and consistent.
+- Errors and warnings are now reported via a
+ function. They are all prefixed by a severity
+ and have the same appearance:
+ "AFFS: <function>: <error message>"
+ (There's one exception to this, as in that function
+ is no pointer to the super block available.)
+- The filesystem is remounted read-only after an
+ error.
+- The names of newly created filesystem objects are
+ now checked for validity.
+- Minor cleanups in comments.
+- Added this Changes file. At last!
+
+Version 3.2
+-----------
+
+- Extension block cache: Reading/writing of huge files
+ (several MB) is much faster (of course the added
+ overhead slows down opening, but this is hardly
+ noticeable).
+- The same get_block()-routine can now be used for
+ both OFS and FFS.
+- The super block is now searched in the block that
+ was calculated and in the one following. This
+ should remedy the round-off error introduced by
+ the 1-k blocks that Linux uses.
+- Minor changes to adhere to the new VFS interface.
+- The number of used blocks is now also calculated
+ if the filesystem is mounted read-only.
+- Prefixed some constants with AFFS_ to avoid name
+ clashes.
+- Removed 'EXPERIMENTAL' status.
+
+Version 3.1
+-----------
+
+- Fixed a nasty bug which didn't allow read-only
+ mounts.
+- Allow dir-cache filesystems to be mounted
+ read only.
+- OFS support.
+- Several other changes I just cannot remember
+ any more.
+
+Version 3.0
+-----------
+
+- Almost complete rewrite for the new VFS
+ interface in Linux 1.3.
+- Write support.
+- Support for hard and symbolic links.
+- Lots of things I remeber even less ...
+
+Version 2.0
+-----------
+
+- Fixed a few things to get it compiled.
+- Automatic root block calculation.
+- Partition checker for genhd.c
+
+========================================
+
+Let's just call Ray Burr's original affs
+'Version 1.0'.
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 63d76a86e..4afd66e49 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -5,8 +5,10 @@
*
* (C) 1993 Ray Burr - Amiga FFS filesystem.
*
+ * Please send bug reports to: hjw@zvw.de
*/
+#include <stdarg.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/affs_fs.h>
@@ -17,6 +19,8 @@
extern struct timezone sys_tz;
+static char ErrorBuffer[256];
+
/*
* Functions for accessing Amiga-FFS structures.
*
@@ -28,7 +32,7 @@ extern struct timezone sys_tz;
0 is returned. Otherwise, the key number in the next used hash slot
is returned. */
-int
+static int
affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos)
{
struct dir_front *dir_front = dir_data;
@@ -54,24 +58,23 @@ affs_get_file_name(int bsize, void *fh_data, char **name)
file_end = GET_END_PTR(struct file_end, fh_data, bsize);
if (file_end->file_name[0] == 0
|| file_end->file_name[0] > 30) {
- printk ("affs_get_file_name: OOPS! bad filename\n");
- printk (" file_end->file_name[0] = %d\n",
+ printk(KERN_WARNING "AFFS: bad filename (length=%d chars)\n",
file_end->file_name[0]);
*name = "***BAD_FILE***";
return 14;
}
- *name = (char *) &file_end->file_name[1];
+ *name = (char *)&file_end->file_name[1];
return file_end->file_name[0];
}
/* Find the predecessor in the hash chain */
int
-affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
+affs_fix_hash_pred(struct inode *startino, int startoffset, s32 key, s32 newkey)
{
struct buffer_head *bh = NULL;
- int nextkey;
- int ptype, stype;
+ s32 nextkey;
+ s32 ptype, stype;
int retval;
nextkey = startino->i_ino;
@@ -87,14 +90,14 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
|| ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR &&
stype != ST_LINKFILE && stype != ST_LINKDIR &&
stype != ST_ROOT && stype != ST_SOFTLINK)) {
- printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n",
- ptype,stype);
+ affs_error(startino->i_sb,"affs_fix_hash_pred",
+ "Bad block in link chain (ptype=%d, stype=%d)",ptype,stype);
affs_brelse(bh);
break;
}
- nextkey = htonl(((__u32 *)bh->b_data)[startoffset]);
+ nextkey = htonl(((s32 *)bh->b_data)[startoffset]);
if (nextkey == key) {
- ((__u32 *)bh->b_data)[startoffset] = newkey;
+ ((s32 *)bh->b_data)[startoffset] = newkey;
affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
mark_buffer_dirty(bh,1);
affs_brelse(bh);
@@ -112,13 +115,13 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
/* Remove inode from link chain */
int
-affs_fix_link_pred(struct inode *startino, int key, int newkey)
+affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey)
{
struct buffer_head *bh = NULL;
- int nextkey;
+ s32 nextkey;
int offset;
- int etype = 0;
- int ptype, stype;
+ s32 etype = 0;
+ s32 ptype, stype;
int retval;
offset = AFFS_I2BSIZE(startino) / 4 - 10;
@@ -150,7 +153,7 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey)
retval = -EPERM;
break;
}
- nextkey = htonl(((__u32 *)bh->b_data)[offset]);
+ nextkey = htonl(((s32 *)bh->b_data)[offset]);
if (nextkey == key) {
FILE_END(bh->b_data,startino)->link_chain = newkey;
affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
@@ -172,17 +175,17 @@ affs_fix_link_pred(struct inode *startino, int key, int newkey)
(which lets us calculate the block size).
Returns non-zero if the block is not consistent. */
-__u32
-affs_checksum_block(int bsize, void *data, int *ptype, int *stype)
+u32
+affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype)
{
- __u32 sum;
- __u32 *p;
+ u32 sum;
+ u32 *p;
bsize /= 4;
if (ptype)
- *ptype = htonl(((__s32 *)data)[0]);
+ *ptype = htonl(((s32 *)data)[0]);
if (stype)
- *stype = htonl(((__s32 *)data)[bsize - 1]);
+ *stype = htonl(((s32 *)data)[bsize - 1]);
sum = 0;
p = data;
@@ -194,20 +197,20 @@ affs_checksum_block(int bsize, void *data, int *ptype, int *stype)
void
affs_fix_checksum(int bsize, void *data, int cspos)
{
- __u32 ocs;
- __u32 cs;
+ u32 ocs;
+ u32 cs;
cs = affs_checksum_block(bsize,data,NULL,NULL);
- ocs = htonl (((__u32 *)data)[cspos]);
+ ocs = htonl (((u32 *)data)[cspos]);
ocs -= cs;
- ((__u32 *)data)[cspos] = htonl(ocs);
+ ((u32 *)data)[cspos] = htonl(ocs);
}
void
-secs_to_datestamp(int secs, struct DateStamp *ds)
+secs_to_datestamp(time_t secs, struct DateStamp *ds)
{
- __u32 days;
- __u32 minute;
+ u32 days;
+ u32 minute;
secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60);
if (secs < 0)
@@ -223,7 +226,7 @@ secs_to_datestamp(int secs, struct DateStamp *ds)
}
int
-prot_to_mode(__u32 prot)
+prot_to_mode(u32 prot)
{
int mode = 0;
@@ -249,10 +252,10 @@ prot_to_mode(__u32 prot)
return mode;
}
-unsigned int
+u32
mode_to_prot(int mode)
{
- unsigned int prot = 0;
+ u32 prot = 0;
if (mode & S_IXUSR)
prot |= FIBF_SCRIPT;
@@ -271,3 +274,32 @@ mode_to_prot(int mode)
return prot;
}
+
+void
+affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args,fmt);
+ vsprintf(ErrorBuffer,fmt,args);
+ va_end(args);
+
+ printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev),
+ function,ErrorBuffer);
+ if (!(sb->s_flags & MS_RDONLY))
+ printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
+ sb->s_flags |= MS_RDONLY;
+}
+
+void
+affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args,fmt);
+ vsprintf(ErrorBuffer,fmt,args);
+ va_end(args);
+
+ printk(KERN_WARNING "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev),
+ function,ErrorBuffer);
+}
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index 1d69d5a3d..a7382db4c 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -3,7 +3,6 @@
*
* (c) 1996 Hans-Joachim Widmaier
*
- *
* bitmap.c contains the code that handles all bitmap related stuff -
* block allocation, deallocation, calculation of free space.
*/
@@ -54,7 +53,7 @@ affs_count_free_blocks(struct super_block *s)
}
void
-affs_free_block(struct super_block *sb, int block)
+affs_free_block(struct super_block *sb, s32 block)
{
int bmap;
int bit;
@@ -70,7 +69,7 @@ affs_free_block(struct super_block *sb, int block)
zone_no = (bmap << (sb->s_blocksize_bits - 7)) + bit / 1024;
bm = &sb->u.affs_sb.s_bitmap[bmap];
if (bmap >= sb->u.affs_sb.s_bm_count) {
- printk("AFFS: free_block(): block %d outside partition.\n",block);
+ affs_error(sb,"affs_free_block","Block %d outside partition",block);
return;
}
blk = 0;
@@ -83,15 +82,16 @@ affs_free_block(struct super_block *sb, int block)
if (!bm->bm_bh) {
bm->bm_count--;
unlock_super(sb);
- printk("AFFS: free_block(): Cannot read bitmap block %d\n",bm->bm_key);
+ affs_error(sb,"affs_free_block","Cannot read bitmap block %d",bm->bm_key);
return;
}
}
- if (set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4))
- printk("AFFS: free_block(): block %d is already free.\n",block);
+ if (test_and_set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4))
+ affs_warning(sb,"affs_free_block","Trying to free block %d which is already free",
+ block);
else {
sb->u.affs_sb.s_alloc[zone_no].az_free++;
- ((__u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((__u32 *)bm->bm_bh->b_data)[0]) - blk);
+ ((u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((u32 *)bm->bm_bh->b_data)[0]) - blk);
mark_buffer_dirty(bm->bm_bh,1);
sb->s_dirt = 1;
}
@@ -102,15 +102,15 @@ affs_free_block(struct super_block *sb, int block)
unlock_super(sb);
}
-static int
+static s32
affs_balloc(struct inode *inode, int zone_no)
{
- __u32 w;
- __u32 *bm;
+ u32 w;
+ u32 *bm;
int fb;
int i;
int fwb;
- int block;
+ s32 block;
struct affs_zone *zone;
struct affs_alloc_zone *az;
struct super_block *sb;
@@ -124,7 +124,7 @@ affs_balloc(struct inode *inode, int zone_no)
pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no);
az = &sb->u.affs_sb.s_alloc[zone->z_az_no];
- bm = (__u32 *)zone->z_bm->bm_bh->b_data;
+ bm = (u32 *)zone->z_bm->bm_bh->b_data;
repeat:
for (i = zone->z_start; i < zone->z_end; i++) {
if (bm[i])
@@ -138,9 +138,9 @@ found:
zone->z_start = i;
w = ~htonl(bm[i]);
fb = find_first_zero_bit(&w,32);
- if (fb > 31 || !clear_bit(fb ^ BO_EXBITS,&bm[i])) {
+ if (fb > 31 || !test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) {
unlock_super(sb);
- printk("AFFS: balloc(): empty block disappeared somehow\n");
+ affs_warning(sb,"balloc","Empty block disappeared somehow");
goto repeat;
}
block = fwb + fb;
@@ -153,8 +153,8 @@ found:
fb = find_next_zero_bit(&w,32,fb);
if (fb > 31)
break;
- if (!clear_bit(fb ^ BO_EXBITS,&bm[i])) {
- printk("AFFS: balloc(): empty block disappeared\n");
+ if (!test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) {
+ affs_warning(sb,"balloc","Empty block disappeared somehow");
break;
}
inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb;
@@ -204,7 +204,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no)
if (az->az_count)
az->az_count--;
else
- printk("AFFS: find_new_zone(): az_count=0, but bm used\n");
+ affs_error(sb,"find_new_zone","az_count=0, but bm used");
}
while (1) {
@@ -247,7 +247,7 @@ affs_find_new_zone(struct super_block *sb, int zone_no)
bm->bm_count--;
az->az_count--;
unlock_super(sb);
- printk("AFFS: find_new_zone(): Cannot read bitmap\n");
+ affs_error(sb,"find_new_zone","Cannot read bitmap");
return 0;
}
zone->z_bm = bm;
@@ -261,16 +261,16 @@ affs_find_new_zone(struct super_block *sb, int zone_no)
return az->az_free;
}
-int
+s32
affs_new_header(struct inode *inode)
{
- int block;
+ s32 block;
struct buffer_head *bh;
pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino);
if (!(block = affs_balloc(inode,0))) {
- while(affs_find_new_zone(inode->i_sb,0)) {
+ while (affs_find_new_zone(inode->i_sb,0)) {
if ((block = affs_balloc(inode,0)))
goto init_block;
schedule();
@@ -279,7 +279,7 @@ affs_new_header(struct inode *inode)
}
init_block:
if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: balloc(): cannot read block %d\n",block);
+ affs_error(inode->i_sb,"new_header","Cannot read block %d",block);
return 0;
}
memset(bh->b_data,0,AFFS_I2BSIZE(inode));
@@ -290,7 +290,7 @@ init_block:
return block;
}
-int
+s32
affs_new_data(struct inode *inode)
{
int empty, old;
@@ -299,7 +299,7 @@ affs_new_data(struct inode *inode)
struct super_block *sb;
struct buffer_head *bh;
int i = 0;
- int block;
+ s32 block;
pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino);
@@ -345,7 +345,7 @@ affs_new_data(struct inode *inode)
found:
zone = &sb->u.affs_sb.s_zones[i];
if (!(block = affs_balloc(inode,i))) { /* No data zones left */
- while(affs_find_new_zone(sb,i)) {
+ while (affs_find_new_zone(sb,i)) {
if ((block = affs_balloc(inode,i)))
goto init_block;
schedule();
@@ -357,7 +357,7 @@ found:
init_block:
if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) {
- printk("AFFS: balloc(): cannot read block %u\n",block);
+ affs_error(inode->i_sb,"new_data","Cannot read block %d",block);
return 0;
}
memset(bh->b_data,0,sb->s_blocksize);
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index f7ec42ede..8ae71e5bd 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -64,7 +64,7 @@ struct inode_operations affs_dir_inode_operations = {
};
static long
-affs_dir_read(struct inode * inode, struct file * filp, char * buf, unsigned long count)
+affs_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count)
{
return -EISDIR;
}
@@ -73,19 +73,18 @@ static int
affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir)
{
int j, namelen;
- int i;
+ s32 i;
int hash_pos;
int chain_pos;
unsigned long ino;
unsigned long old;
- int stored;
- char *name;
- struct buffer_head *dir_bh;
- struct buffer_head *fh_bh;
- struct inode *dir;
+ int stored;
+ char *name;
+ struct buffer_head *dir_bh;
+ struct buffer_head *fh_bh;
+ struct inode *dir;
pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos);
-
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
@@ -122,7 +121,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil
chain_pos = (filp->f_pos - 2) & 0xffff;
hash_pos = (filp->f_pos - 2) >> 16;
if (chain_pos == 0xffff) {
- printk("AFFS: more than 65535 entries in chain\n");
+ affs_warning(inode->i_sb,"readdir","More than 65535 entries in chain");
chain_pos = 0;
hash_pos++;
filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
@@ -143,15 +142,15 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil
* we can jump directly to where we left off.
*/
if (filp->private_data && filp->f_version == dir->i_version) {
- i = (int)filp->private_data;
+ i = (s32)filp->private_data;
j = 0;
pr_debug("AFFS: readdir() left off=%d\n",i);
}
filp->f_version = dir->i_version;
- pr_debug("AFFS: hash_pos=%lu chain_pos=%lu\n", hash_pos, chain_pos);
+ pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos,chain_pos);
while (i) {
if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: readdir: Can't get block %d\n",i);
+ affs_error(inode->i_sb,"readdir","Cannot read block %d",i);
goto readdir_done;
}
ino = i;
@@ -164,7 +163,7 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t fil
}
if (fh_bh) {
namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name);
- pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%lu\n",
+ pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%d\n",
namelen,name,ino,i);
filp->private_data = (void *)ino;
if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0)
diff --git a/fs/affs/file.c b/fs/affs/file.c
index a450dffce..0fffbf41e 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -35,6 +35,8 @@
#error PAGE_SIZE must be at least 4096
#endif
+static int affs_bmap(struct inode *inode, int block);
+static struct buffer_head * affs_getblock(struct inode *inode, s32 block);
static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf,
unsigned long count);
static long affs_file_write(struct inode *inode, struct file *filp, const char *buf,
@@ -200,7 +202,7 @@ index_to_seqnum(int index)
return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + 64 * 256 + (index << 9);
}
-static int __inline__
+static s32 __inline__
calc_key(struct inode *inode, int *ext)
{
int index;
@@ -226,28 +228,30 @@ calc_key(struct inode *inode, int *ext)
return inode->u.affs_i.i_ec->ec[index];
}
-int
+static int
affs_bmap(struct inode *inode, int block)
{
struct buffer_head *bh;
- int ext, key, nkey;
- int ptype, stype;
+ s32 key, nkey;
+ s32 ptype, stype;
+ int ext;
int index;
int keycount;
struct key_cache *kc;
struct key_cache *tkc;
struct timeval tv;
- __s32 *keyp;
+ s32 *keyp;
int i;
pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block);
if (block < 0) {
- printk("affs_bmap: block < 0\n");
+ affs_error(inode->i_sb,"bmap","Block < 0");
return 0;
}
if (!inode->u.affs_i.i_ec) {
- printk("affs_bmap(): No ext_cache!?\n");
+ affs_error(inode->i_sb,"bmap","No extension cache for open file (inode=%lu)",
+ inode->i_ino);
return 0;
}
@@ -334,14 +338,14 @@ affs_bmap(struct inode *inode, int block)
return key;
}
-struct buffer_head *
-affs_getblock(struct inode *inode, int block)
+static struct buffer_head *
+affs_getblock(struct inode *inode, s32 block)
{
struct buffer_head *bh;
struct buffer_head *ebh;
struct buffer_head *pbh;
struct key_cache *kc;
- int key, nkey;
+ s32 key, nkey;
int ext;
int cf, j, pt;
int index;
@@ -372,7 +376,7 @@ affs_getblock(struct inode *inode, int block)
return NULL;
if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j) ||
cf != pt || j != ST_FILE) {
- printk("AFFS: getblock(): inode %d is not a valid %s\n",key,
+ affs_error(inode->i_sb,"getblock","Inode %d is not a valid %s",key,
pt == T_SHORT ? "file header" : "extension block");
affs_brelse(bh);
return NULL;
@@ -387,7 +391,8 @@ affs_getblock(struct inode *inode, int block)
else
pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock);
if (!pbh) {
- printk("AFFS: getblock(): cannot get last block in file\n");
+ affs_error(inode->i_sb,"getblock",
+ "Cannot get last block in file");
break;
}
}
@@ -397,7 +402,7 @@ affs_getblock(struct inode *inode, int block)
lock_super(inode->i_sb);
if (AFFS_BLOCK(bh->b_data,inode,j)) {
unlock_super(inode->i_sb);
- printk("AFFS: getblock(): block already allocated\n");
+ affs_warning(inode->i_sb,"getblock","Block already allocated");
affs_free_block(inode->i_sb,nkey);
j++;
continue;
@@ -407,7 +412,8 @@ affs_getblock(struct inode *inode, int block)
if (ofs) {
ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode));
if (!ebh) {
- printk("AFFS: getblock(): cannot get block %d\n",nkey);
+ affs_error(inode->i_sb,"getblock",
+ "Cannot get block %d",nkey);
affs_free_block(inode->i_sb,nkey);
AFFS_BLOCK(bh->b_data,inode,j) = 0;
break;
@@ -492,10 +498,6 @@ affs_getblock(struct inode *inode, int block)
return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
}
-/* This could be made static, regardless of what the former comment said.
- * You cannot directly read affs directories.
- */
-
static long
affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count)
{
@@ -508,12 +510,12 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l
pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,(long)filp->f_pos,count);
if (!inode) {
- printk("affs_file_read: inode = NULL\n");
+ affs_error(inode->i_sb,"file_read_ofs","Inode = NULL");
return -EINVAL;
}
blocksize = AFFS_I2BSIZE(inode) - 24;
if (!(S_ISREG(inode->i_mode))) {
- pr_debug("affs_file_read: mode = %07o\n",inode->i_mode);
+ pr_debug("affs_file_read: mode = %07o",inode->i_mode);
return -EINVAL;
}
if (filp->f_pos >= inode->i_size || count <= 0)
@@ -524,10 +526,10 @@ affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned l
left = MIN (inode->i_size - filp->f_pos,count - (buf - start));
if (!left)
break;
- sector = affs_bmap(inode,(__u32)filp->f_pos / blocksize);
+ sector = affs_bmap(inode,(u32)filp->f_pos / blocksize);
if (!sector)
break;
- offset = (__u32)filp->f_pos % blocksize;
+ offset = (u32)filp->f_pos % blocksize;
bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode));
if (!bh)
break;
@@ -554,25 +556,31 @@ affs_file_write(struct inode *inode, struct file *filp, const char *buf, unsigne
struct inode *ino;
char *p;
+ /* Not that I wanted to be POSIX compliant ... */
+ if (!count)
+ return 0;
pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
(unsigned long)filp->f_pos,count);
ino = NULL;
if (!inode) {
- printk("AFFS: file_write(): inode=NULL\n");
+ affs_error(inode->i_sb,"file_write","Inode = NULL");
return -EINVAL;
}
if (inode->u.affs_i.i_original) {
ino = iget(inode->i_sb,inode->u.affs_i.i_original);
if (!ino) {
- printk("AFFS: could not follow link from inode %lu to %d\n",
- inode->i_ino,inode->u.affs_i.i_original);
+ affs_error(inode->i_sb,"file_write",
+ "Could not follow link from inode %lu to %d",
+ inode->i_ino,inode->u.affs_i.i_original);
return -EINVAL;
}
inode = ino;
}
if (!S_ISREG(inode->i_mode)) {
- printk("AFFS: file_write(): mode=%07o\n",inode->i_mode);
+ affs_error(inode->i_sb,"file_write",
+ "Trying to write to non-regular file (mode=%07o)",
+ inode->i_mode);
iput(inode);
return -EINVAL;
}
@@ -636,22 +644,27 @@ affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, uns
pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
(unsigned long)filp->f_pos,count);
+ if (!count)
+ return 0;
if (!inode) {
- printk("AFFS: file_write_ofs(): inode=NULL\n");
+ affs_error(inode->i_sb,"file_write_ofs","Inode = NULL");
return -EINVAL;
}
ino = NULL;
if (inode->u.affs_i.i_original) {
ino = iget(inode->i_sb,inode->u.affs_i.i_original);
if (!ino) {
- printk("AFFS: could not follow link from inode %lu to %d\n",
- inode->i_ino,inode->u.affs_i.i_original);
+ affs_error(inode->i_sb,"file_write_ofs",
+ "Could not follow link from inode %lu to %d",
+ inode->i_ino,inode->u.affs_i.i_original);
return -EINVAL;
}
inode = ino;
}
if (!S_ISREG(inode->i_mode)) {
- printk("AFFS: file_write_ofs(): mode=%07o\n",inode->i_mode);
+ affs_error(inode->i_sb,"file_write_ofs",
+ "Trying to write to non-regular file (mode=%07o)",
+ inode->i_mode);
iput(inode);
return -EINVAL;
}
@@ -714,10 +727,10 @@ affs_truncate(struct inode *inode)
struct affs_zone *zone;
int first;
int block;
- int key;
- int *keyp;
- int ekey;
- int ptype, stype;
+ s32 key;
+ s32 *keyp;
+ s32 ekey;
+ s32 ptype, stype;
int freethis;
int blocksize;
int rem;
@@ -729,8 +742,8 @@ affs_truncate(struct inode *inode)
if (inode->u.affs_i.i_original) {
ino = iget(inode->i_sb,inode->u.affs_i.i_original);
if (!ino) {
- printk("AFFS: truncate(): cannot follow link from %lu to %u\n",
- inode->i_ino,inode->u.affs_i.i_original);
+ affs_error(inode->i_sb,"truncate","Cannot follow link from %lu to %d",
+ inode->i_ino,inode->u.affs_i.i_original);
return;
}
inode = ino;
@@ -754,7 +767,7 @@ affs_truncate(struct inode *inode)
unlock_super(inode->i_sb);
}
if (!bh) {
- printk("AFFS: truncate(): Cannot extend file\n");
+ affs_error(inode->i_sb,"truncate","Cannot extend file");
inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1);
} else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
rem = inode->i_size % blocksize;
@@ -771,7 +784,7 @@ affs_truncate(struct inode *inode)
while (ekey) {
if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: truncate(): Can't read block %d\n",ekey);
+ affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey);
break;
}
ptype = htonl(((struct file_front *)bh->b_data)->primary_type);
@@ -783,14 +796,14 @@ affs_truncate(struct inode *inode)
break;
}
if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
- printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n",
- ptype,stype);
+ affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)",
+ ptype,stype);
affs_brelse(bh);
break;
}
/* Do not throw away file header */
freethis = first == 0 && ekey != inode->i_ino;
- for ( block = first; block < AFFS_I2HSIZE(inode); block++) {
+ for (block = first; block < AFFS_I2HSIZE(inode); block++) {
keyp = &AFFS_BLOCK(bh->b_data,inode,block);
key = htonl(*keyp);
if (key) {
@@ -853,7 +866,7 @@ static int
affs_open_file(struct inode *inode, struct file *filp)
{
int error;
- int key;
+ u32 key;
int i;
pr_debug("AFFS: open_file(ino=%lu)\n",inode->i_ino);
@@ -864,7 +877,7 @@ affs_open_file(struct inode *inode, struct file *filp)
if (!inode->u.affs_i.i_ec) {
inode->u.affs_i.i_ec = (struct ext_cache *)get_free_page(GFP_KERNEL);
if (!inode->u.affs_i.i_ec) {
- printk("AFFS: cache allocation failed\n");
+ affs_error(inode->i_sb,"open_file","Cache allocation failed");
error = ENOMEM;
} else {
/* We only have to initialize non-zero values.
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 9b6626f7d..654a8ca61 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -30,12 +30,26 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+/* AmigaOS allows file names with up to 30 characters length.
+ * Names longer than that will be silently truncated. If you
+ * want to disallow this, comment out the following #define.
+ * Creating filesystem objects with longer names will then
+ * result in an error (ENAMETOOLONG).
+ */
+/*#define NO_TRUNCATE */
+
extern int *blk_size[];
extern struct timezone sys_tz;
#define MIN(a,b) (((a)<(b))?(a):(b))
-void
+static int affs_notify_change(struct inode *inode, struct iattr *attr);
+static void affs_put_inode(struct inode *inode);
+static void affs_read_inode(struct inode *inode);
+static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static void affs_write_inode(struct inode *inode);
+
+static void
affs_put_super(struct super_block *sb)
{
int i;
@@ -110,13 +124,13 @@ static struct super_operations affs_sops = {
NULL /* remount */
};
-int
+unsigned long
affs_parent_ino(struct inode *dir)
{
int root_ino = (dir->i_sb->u.affs_sb.s_root_block);
if (!S_ISDIR (dir->i_mode)) {
- printk ("affs_parent_ino: argument is not a directory\n");
+ affs_error(dir->i_sb,"parent_ino","Trying to get parent of non-directory");
return root_ino;
}
if (dir->i_ino == root_ino)
@@ -125,7 +139,7 @@ affs_parent_ino(struct inode *dir)
}
static int
-parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root,
+parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
{
char *this_char, *value;
@@ -150,14 +164,14 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
*value++ = 0;
if (!strcmp(this_char,"protect")) {
if (value) {
- printk("AFFS: option protect does not take an argument\n");
+ printk("AFFS: Option protect does not take an argument\n");
return 0;
}
*mount_opts |= SF_IMMUTABLE;
}
else if (!strcmp(this_char,"verbose")) {
if (value) {
- printk("AFFS: option verbose does not take an argument\n");
+ printk("AFFS: Option verbose does not take an argument\n");
return 0;
}
*mount_opts |= SF_VERBOSE;
@@ -166,7 +180,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
if (!value)
*uid = current->uid;
else if (!*value) {
- printk("AFFS: argument for uid option missing\n");
+ printk("AFFS: Argument for uid option missing\n");
return 0;
} else {
*uid = simple_strtoul(value,&value,0);
@@ -180,7 +194,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
if (!value)
*gid = current->gid;
else if (!*value) {
- printk("AFFS: argument for gid option missing\n");
+ printk("AFFS: Argument for gid option missing\n");
return 0;
} else {
*gid = simple_strtoul(value,&value,0);
@@ -248,7 +262,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
return 0;
if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048
&& *blocksize != 4096) {
- printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n");
+ printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
return 0;
}
}
@@ -270,21 +284,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
* hopefully have the guts to do so. Until then: sorry for the mess.
*/
-struct super_block *
+static struct super_block *
affs_read_super(struct super_block *s,void *data, int silent)
{
struct buffer_head *bh = NULL;
struct buffer_head *bb;
kdev_t dev = s->s_dev;
- int root_block;
+ s32 root_block;
int size;
- __u32 chksum;
- __u32 *bm;
- int ptype, stype;
+ u32 chksum;
+ u32 *bm;
+ s32 ptype, stype;
int mapidx;
int num_bm;
int i, j;
- int key;
+ s32 key;
int blocksize;
uid_t uid;
gid_t gid;
@@ -300,7 +314,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
&blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) {
s->s_dev = 0;
- printk("AFFS: error parsing options.\n");
+ printk(KERN_ERR "AFFS: Error parsing options\n");
MOD_DEC_USE_COUNT;
return NULL;
}
@@ -324,13 +338,13 @@ affs_read_super(struct super_block *s,void *data, int silent)
if (size == 0) {
s->s_dev = 0;
unlock_super(s);
- printk("affs_read_super: could not determine device size\n");
+ printk(KERN_ERR "AFFS: Could not determine device size\n");
goto out;
}
s->u.affs_sb.s_partition_size = size;
s->u.affs_sb.s_reserved = reserved;
- /* Try to find root block. Its location may depend on the block size. */
+ /* Try to find root block. Its location depends on the block size. */
s->u.affs_sb.s_hashsize = 0;
if (blocksize > 0) {
@@ -358,12 +372,12 @@ affs_read_super(struct super_block *s,void *data, int silent)
* block behind the calculated one. So we check this one, too.
*/
for (num_bm = 0; num_bm < 2; num_bm++) {
- pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, "
+ pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %u, "
"size=%d blocks, %d reserved\n",kdevname(dev),blocksize,
s->u.affs_sb.s_root_block + num_bm,size,reserved);
bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize);
if (!bh) {
- printk("AFFS: unable to read root block\n");
+ printk(KERN_ERR "AFFS: Cannot read root block\n");
goto out;
}
if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&
@@ -383,7 +397,8 @@ affs_read_super(struct super_block *s,void *data, int silent)
if (!key) {
affs_brelse(bh);
if (!silent)
- printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev));
+ printk(KERN_ERR "AFFS: Cannot find a valid root block on device %s\n",
+ kdevname(dev));
goto out;
}
root_block = s->u.affs_sb.s_root_block;
@@ -396,7 +411,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
/* Find out which kind of FS we have */
bb = affs_bread(dev,0,s->s_blocksize);
if (bb) {
- chksum = htonl(*(__u32 *)bb->b_data);
+ chksum = htonl(*(u32 *)bb->b_data);
/* Dircache filesystems are compatible with non-dircache ones
* when reading. As long as they aren't supported, writing is
@@ -404,7 +419,8 @@ affs_read_super(struct super_block *s,void *data, int silent)
*/
if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
|| chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {
- printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev));
+ printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
+ kdevname(dev));
s->s_flags |= MS_RDONLY;
}
switch (chksum) {
@@ -436,22 +452,22 @@ affs_read_super(struct super_block *s,void *data, int silent)
s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
break;
default:
- printk("AFFS: Unknown filesystem on device %s: %08X\n",
- kdevname(dev),chksum);
+ printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
+ kdevname(dev),chksum);
affs_brelse(bb);
goto out;
}
affs_brelse(bb);
} else {
- printk("AFFS: Can't get boot block.\n");
+ printk(KERN_ERR "AFFS: Cannot read boot block\n");
goto out;
}
if (mount_flags & SF_VERBOSE) {
chksum = ntohl(chksum);
- printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
- GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
- &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
- (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
+ printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
+ GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
+ &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
+ (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
}
s->s_magic = AFFS_SUPER_MAGIC;
@@ -459,7 +475,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
/* Keep super block in cache */
if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) {
- printk("AFFS: Can't read root block a second time\n");
+ printk(KERN_ERR "AFFS: Cannot read root block\n");
goto out;
}
@@ -473,7 +489,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
MAX_ZONES * sizeof(struct affs_zone);
pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) {
- printk("AFFS: Not enough memory.\n");
+ printk(KERN_ERR "AFFS: Not enough memory\n");
goto out;
}
memset(s->u.affs_sb.s_bitmap,0,ptype);
@@ -486,7 +502,8 @@ affs_read_super(struct super_block *s,void *data, int silent)
if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) {
if (!(s->s_flags & MS_RDONLY)) {
- printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev));
+ printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
+ kdevname(dev));
s->s_flags |= MS_RDONLY;
}
affs_brelse(bh);
@@ -504,17 +521,17 @@ affs_read_super(struct super_block *s,void *data, int silent)
offset = s->u.affs_sb.s_reserved;
az_no = 0;
while (bh) {
- bm = (__u32 *)bh->b_data;
+ bm = (u32 *)bh->b_data;
for (i = ptype; i < stype && bm[i]; i++, mapidx++) {
if (mapidx >= num_bm) {
- printk("AFFS: Not enough bitmap space!?\n");
+ printk(KERN_ERR "AFFS: Not enough bitmap space!?\n");
goto out;
}
bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize);
if (bb) {
if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) &&
!(s->s_flags & MS_RDONLY)) {
- printk("AFFS: Bitmap (%d,key=%lu) invalid - "
+ printk(KERN_WARNING "AFFS: Bitmap (%d,key=%lu) invalid - "
"mounting %s read only.\n",mapidx,htonl(bm[i]),
kdevname(dev));
s->s_flags |= MS_RDONLY;
@@ -525,7 +542,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
key = size & 0x1F; /* used bits */
if (key) {
chksum = ntohl(0x7FFFFFFF >> (31 - key));
- ((__u32 *)bb->b_data)[ptype] &= chksum;
+ ((u32 *)bb->b_data)[ptype] &= chksum;
affs_fix_checksum(s->s_blocksize,bb->b_data,0);
mark_buffer_dirty(bb,1);
}
@@ -551,7 +568,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
}
affs_brelse(bb);
} else {
- printk("AFFS: Can't read bitmap.\n");
+ printk(KERN_ERR "AFFS: Cannot read bitmap\n");
goto out;
}
}
@@ -561,14 +578,14 @@ affs_read_super(struct super_block *s,void *data, int silent)
affs_brelse(bh);
if (key) {
if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) {
- printk("AFFS: Can't read bitmap extension.\n");
+ printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
goto out;
}
} else
bh = NULL;
}
if (mapidx != num_bm) {
- printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm);
+ printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm);
goto out;
}
nobitmap:
@@ -584,7 +601,7 @@ nobitmap:
if (!(s->s_mounted)) {
s->s_dev = 0;
- printk("AFFS: get root inode failed\n");
+ printk(KERN_ERR "AFFS: get root inode failed\n");
MOD_DEC_USE_COUNT;
return NULL;
}
@@ -615,7 +632,7 @@ nobitmap:
return NULL;
}
-void
+static void
affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
int free;
@@ -635,15 +652,15 @@ affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
copy_to_user(buf,&tmp,bufsiz);
}
-void
+static void
affs_read_inode(struct inode *inode)
{
struct buffer_head *bh, *lbh;
struct file_front *file_front;
struct file_end *file_end;
- int block;
+ s32 block;
unsigned long prot;
- int ptype, stype;
+ s32 ptype, stype;
unsigned short id;
pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino);
@@ -651,12 +668,12 @@ affs_read_inode(struct inode *inode)
lbh = NULL;
block = inode->i_ino;
if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: unable to read i-node block %d\n",block);
+ affs_error(inode->i_sb,"read_inode","Cannot read block %d",block);
return;
}
if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) {
- printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n",
- ptype,block);
+ affs_error(inode->i_sb,"read_inode",
+ "Checksum or type (ptype=%d) error on inode %d",ptype,block);
affs_brelse(bh);
return;
}
@@ -735,7 +752,8 @@ affs_read_inode(struct inode *inode)
if (!(lbh = affs_bread(inode->i_dev,inode->u.affs_i.i_original,
AFFS_I2BSIZE(inode)))) {
affs_brelse(bh);
- printk("AFFS: unable to read i-node block %ld\n",inode->i_ino);
+ affs_error(inode->i_sb,"read_inode","Cannot read block %lu",
+ inode->i_ino);
return;
}
file_end = GET_END_PTR(struct file_end,lbh->b_data,AFFS_I2BSIZE(inode));
@@ -776,12 +794,13 @@ affs_read_inode(struct inode *inode)
inode->i_op = &affs_symlink_inode_operations;
}
-void
+static void
affs_write_inode(struct inode *inode)
{
- struct buffer_head *bh;
- struct file_end *file_end;
- short uid, gid;
+ struct buffer_head *bh;
+ struct file_end *file_end;
+ uid_t uid;
+ gid_t gid;
pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);
@@ -789,8 +808,7 @@ affs_write_inode(struct inode *inode)
if (!inode->i_nlink)
return;
if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: Unable to read block of inode %ld on %s\n",
- inode->i_ino,kdevname(inode->i_dev));
+ affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino);
return;
}
file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));
@@ -820,7 +838,7 @@ affs_write_inode(struct inode *inode)
brelse(bh);
}
-int
+static int
affs_notify_change(struct inode *inode, struct iattr *attr)
{
int error;
@@ -848,7 +866,7 @@ affs_notify_change(struct inode *inode, struct iattr *attr)
return 0;
}
-void
+static void
affs_put_inode(struct inode *inode)
{
pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink);
@@ -867,7 +885,7 @@ affs_new_inode(const struct inode *dir)
{
struct inode *inode;
struct super_block *sb;
- int block;
+ s32 block;
if (!dir || !(inode = get_empty_inode()))
return NULL;
@@ -918,7 +936,10 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
struct buffer_head *dir_bh;
struct buffer_head *inode_bh;
struct buffer_head *link_bh;
- int hash;
+ struct buffer_head *ibh;
+ int retval;
+ int i;
+ s32 next;
pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d\n",dir->i_ino,inode->i_ino,
len,name,type);
@@ -926,34 +947,60 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
dir_bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
link_bh = NULL;
- if (!dir_bh || !inode_bh) {
- affs_brelse(dir_bh);
- affs_brelse(inode_bh);
- return -ENOSPC;
- }
+ retval = -EIO;
+ if (!dir_bh || !inode_bh)
+ goto addentry_done;
if (link) {
link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link));
- if (!link_bh) {
- affs_brelse(dir_bh);
- affs_brelse(inode_bh);
- return -EINVAL;
- }
+ if (!link_bh)
+ goto addentry_done;
}
((struct dir_front *)inode_bh->b_data)->primary_type = ntohl(T_SHORT);
((struct dir_front *)inode_bh->b_data)->own_key = ntohl(inode->i_ino);
- if (len > 30) /* truncate name quietly */
+ retval = -ENAMETOOLONG;
+ if (len > 30)
+#ifdef NO_TRUNCATE
+ goto addentry_done;
+#else
len = 30;
+#endif
+
+ /* Check if name is valid */
+ retval = -EINVAL;
+ for (i = 0; i < len; i++) {
+ if (name[i] < ' ' || name[i] == ':'
+ || ((unsigned char)name[i] > 0x7e && (unsigned char)name[i] < 0xa0))
+ goto addentry_done;
+ }
+ retval = 0;
DIR_END(inode_bh->b_data,inode)->dir_name[0] = len;
strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len);
DIR_END(inode_bh->b_data,inode)->secondary_type = ntohl(type);
DIR_END(inode_bh->b_data,inode)->parent = ntohl(dir->i_ino);
- hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir));
+
+ i = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)) + 6;
+ next = dir->i_ino;
+
+ /* Alas, we have to search the insertion point with a locked sb */
lock_super(inode->i_sb);
- DIR_END(inode_bh->b_data,inode)->hash_chain =
- ((struct dir_front *)dir_bh->b_data)->hashtable[hash];
- ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino);
+ while (1) {
+ if (!(ibh = affs_bread(dir->i_dev,next,AFFS_I2BSIZE(dir))))
+ goto addentry_done;
+ next = htonl(((s32 *)ibh->b_data)[i]);
+ if (!next || next > inode->i_ino)
+ break;
+ i = AFFS_I2BSIZE(dir) / 4 - 4;
+ affs_brelse(ibh);
+ }
+
+ DIR_END(inode_bh->b_data,inode)->hash_chain = next;
+ ((s32 *)ibh->b_data)[i] = ntohl(inode->i_ino);
+ affs_fix_checksum(AFFS_I2BSIZE(dir),ibh->b_data,5);
+ mark_buffer_dirty(ibh,1);
+ affs_brelse(ibh);
+
if (link_bh) {
LINK_END(inode_bh->b_data,inode)->original = ntohl(link->i_ino);
LINK_END(inode_bh->b_data,inode)->link_chain =
@@ -974,11 +1021,13 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
inode->i_dirt = 1;
mark_buffer_dirty(dir_bh,1);
mark_buffer_dirty(inode_bh,1);
+
+addentry_done:
affs_brelse(dir_bh);
affs_brelse(inode_bh);
affs_brelse(link_bh);
- return 0;
+ return retval;
}
static struct file_system_type affs_fs_type = {
@@ -999,7 +1048,7 @@ EXPORT_NO_SYMBOLS;
int
init_module(void)
{
- return init_affs_fs();
+ return register_filesystem(&affs_fs_type);
}
void
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 0f4bced43..6a9b02bac 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -20,6 +20,8 @@
#include <linux/errno.h>
+static int affs_fixup(struct buffer_head *bh, struct inode *inode);
+
/* Simple toupper() for DOS\1 */
static inline unsigned int
@@ -100,7 +102,7 @@ affs_find_entry(struct inode *dir, const char *name, int namelen,
{
struct buffer_head *bh;
int intl;
- int key;
+ s32 key;
pr_debug("AFFS: find_entry(%.*s)=\n",namelen,name);
@@ -222,9 +224,7 @@ affs_create(struct inode *dir, const char *name, int len, int mode, struct inode
pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,len,name,mode);
-
*result = NULL;
-
if (!dir || !dir->i_sb) {
iput(dir);
return -EINVAL;
@@ -472,7 +472,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len)
iput(oldinode);
oldinode = iget(dir->i_sb,i);
if (!oldinode) {
- printk("AFFS: link(): original does not exist.\n");
+ affs_error(oldinode->i_sb,"link","Cannot get original from link");
iput(dir);
return -ENOENT;
}
@@ -507,7 +507,7 @@ affs_link(struct inode *oldinode, struct inode *dir, const char *name, int len)
}
static int
-subdir(struct inode * new_inode, struct inode * old_inode)
+subdir(struct inode *new_inode, struct inode *old_inode)
{
int ino;
int result;
@@ -650,11 +650,11 @@ end_rename:
return retval;
}
-int
+static int
affs_fixup(struct buffer_head *bh, struct inode *inode)
{
- int key, link_key;
- int type;
+ s32 key, link_key;
+ s32 type;
struct buffer_head *nbh;
struct inode *ofinode;
@@ -663,7 +663,8 @@ affs_fixup(struct buffer_head *bh, struct inode *inode)
key = htonl(LINK_END(bh->b_data,inode)->original);
LINK_END(bh->b_data,inode)->original = 0;
if (!key) {
- printk("AFFS: fixup(): hard link without original: ino=%lu\n",inode->i_ino);
+ affs_error(inode->i_sb,"fixup","Hard link without original: ino=%lu",
+ inode->i_ino);
return -ENOENT;
}
if (!(ofinode = iget(inode->i_sb,key)))
@@ -676,17 +677,18 @@ affs_fixup(struct buffer_head *bh, struct inode *inode)
if ((key = htonl(FILE_END(bh->b_data,inode)->link_chain))) {
/* Get first link, turn it to a file */
if (!(ofinode = iget(inode->i_sb,key))) {
- printk("AFFS: fixup(): cannot read inode %u\n",key);
+ affs_error(inode->i_sb,"fixup","Cannot read block %d",key);
return -ENOENT;
}
if (!ofinode->u.affs_i.i_hlink) {
- printk("AFFS: fixup(): first link to %lu (%u) is not a link?\n",
- inode->i_ino,key);
+ affs_error(inode->i_sb,"fixup",
+ "First link to %lu (%d) is not a link",
+ inode->i_ino,key);
iput(ofinode);
return -ENOENT;
}
if (!(nbh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)))) {
- printk("AFFS: fixup(): cannot read block %u\n",key);
+ affs_error(inode->i_sb,"fixup","Cannot read block %d",key);
iput(ofinode);
return -ENOENT;
}
@@ -719,13 +721,14 @@ affs_fixup(struct buffer_head *bh, struct inode *inode)
break;
if ((ofinode = iget(inode->i_sb,key))) {
if (!ofinode->u.affs_i.i_hlink)
- printk("AFFS: fixup() inode %u in link chain is "
- "not a link\n",key);
+ affs_error(inode->i_sb,"fixup",
+ "Inode %d in link chain is not a link",
+ key);
ofinode->u.affs_i.i_original = link_key;
ofinode->i_dirt = 1;
FILE_END(nbh->b_data,inode)->original = htonl(link_key);
} else
- printk("AFFS: fixup(): cannot get inode %u\n",key);
+ affs_error(inode->i_sb,"fixup","Cannot read block %d",key);
}
/* Turn old inode to a link */
inode->u.affs_i.i_hlink = 1;
@@ -735,7 +738,7 @@ affs_fixup(struct buffer_head *bh, struct inode *inode)
} else if (type == ST_SOFTLINK) {
return 0;
} else {
- printk("AFFS: fixup(): secondary type=%d\n",type);
+ affs_error(inode->i_sb,"fixup","Bad secondary type (%d)",type);
return -EBADF;
}
}
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index 734df0780..de93eac5c 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -82,7 +82,7 @@ affs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode,
i = 0;
j = 0;
if (!bh) {
- printk("AFFS: unable to read i-node block %lu\n",inode->i_ino);
+ affs_error(inode->i_sb,"follow_link","Cannot read block %lu\n",inode->i_ino);
kfree(buffer);
iput(inode);
iput(dir);
@@ -138,7 +138,7 @@ affs_readlink(struct inode *inode, char *buffer, int buflen)
i = 0;
j = 0;
if (!bh) {
- printk("AFFS: unable to read i-node block %lu\n",inode->i_ino);
+ affs_error(inode->i_sb,"readlink","Cannot read block %lu\n",inode->i_ino);
goto symlink_end;
}
lf = (struct slink_front *)bh->b_data;