summaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/CHANGES7
-rw-r--r--fs/ext2/acl.c15
-rw-r--r--fs/ext2/balloc.c19
-rw-r--r--fs/ext2/bitmap.c7
-rw-r--r--fs/ext2/dir.c54
-rw-r--r--fs/ext2/file.c35
-rw-r--r--fs/ext2/fsync.c19
-rw-r--r--fs/ext2/ialloc.c19
-rw-r--r--fs/ext2/inode.c32
-rw-r--r--fs/ext2/ioctl.c8
-rw-r--r--fs/ext2/namei.c7
-rw-r--r--fs/ext2/super.c87
-rw-r--r--fs/ext2/symlink.c7
-rw-r--r--fs/ext2/truncate.c55
14 files changed, 218 insertions, 153 deletions
diff --git a/fs/ext2/CHANGES b/fs/ext2/CHANGES
index b760d18c7..a2495a41e 100644
--- a/fs/ext2/CHANGES
+++ b/fs/ext2/CHANGES
@@ -1,5 +1,12 @@
Changes from version 0.5 to version 0.5a
========================================
+ - Zero the partial block following the end of the file when a file
+ is truncated.
+ - Dates updated in the copyright.
+ - More checks when the filesystem is mounted: the count of blocks,
+ fragments, and inodes per group is checked against the block size.
+ - The buffers used by the error routines are now static variables, to
+ avoid using space on the kernel stack, as requested by Linus.
- Some cleanups in the error messages (some versions of syslog contain
a bug which truncates an error message if it contains '\n').
- Check that no data can be written to a file past the 2GB limit.
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 91ef7c8cc..0b2701fe6 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/acl.c
*
- * Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*/
/*
@@ -30,12 +31,12 @@ int ext2_permission (struct inode * inode, int mask)
* Nobody gets write access to an immutable file
*/
if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
- return 0;
+ return -EACCES;
/*
* Special case, access is always granted for root
*/
if (fsuser())
- return 1;
+ return 0;
/*
* If no ACL, checks using the file mode
*/
@@ -44,7 +45,7 @@ int ext2_permission (struct inode * inode, int mask)
else if (in_group_p (inode->i_gid))
mode >>= 3;
if (((mode & mask & S_IRWXO) == mask))
- return 1;
- else
return 0;
+ else
+ return -EACCES;
}
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index bc6faa7ed..c476fa2b2 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/balloc.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
*/
@@ -75,7 +76,7 @@ static void read_block_bitmap (struct super_block * sb,
ext2_panic (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %lu",
- block_group, gdp->bg_block_bitmap);
+ block_group, (unsigned long) gdp->bg_block_bitmap);
sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
}
@@ -232,7 +233,7 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
mark_buffer_dirty(bh, 1);
- if (sb->s_flags & MS_SYNC) {
+ if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
@@ -249,8 +250,8 @@ void ext2_free_blocks (struct super_block * sb, unsigned long block,
* bitmap, and then for any free bit if that fails.
*/
int ext2_new_block (struct super_block * sb, unsigned long goal,
- unsigned long * prealloc_count,
- unsigned long * prealloc_block)
+ u32 * prealloc_count,
+ u32 * prealloc_block)
{
struct buffer_head * bh;
struct buffer_head * bh2;
@@ -441,7 +442,7 @@ got_block:
j = tmp;
mark_buffer_dirty(bh, 1);
- if (sb->s_flags & MS_SYNC) {
+ if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
@@ -577,6 +578,6 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
ext2_error (sb, "ext2_check_blocks_bitmap",
"Wrong free blocks count in super block, "
"stored = %lu, counted = %lu",
- es->s_free_blocks_count, bitmap_count);
+ (unsigned long) es->s_free_blocks_count, bitmap_count);
unlock_super (sb);
}
diff --git a/fs/ext2/bitmap.c b/fs/ext2/bitmap.c
index 1084da16d..8b9b5d233 100644
--- a/fs/ext2/bitmap.c
+++ b/fs/ext2/bitmap.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/bitmap.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*/
#include <linux/fs.h>
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index c98139bc6..5b8bf9cc7 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/dir.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
@@ -22,16 +23,13 @@
#include <linux/sched.h>
#include <linux/stat.h>
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
-#define ROUND_UP(x) (((x)+3) & ~3)
-
static int ext2_dir_read (struct inode * inode, struct file * filp,
char * buf, int count)
{
return -EISDIR;
}
-static int ext2_readdir (struct inode *, struct file *, struct dirent *, int);
+static int ext2_readdir (struct inode *, struct file *, void *, filldir_t);
static struct file_operations ext2_dir_operations = {
NULL, /* lseek - default */
@@ -92,16 +90,17 @@ int ext2_check_dir_entry (char * function, struct inode * dir,
if (error_msg != NULL)
ext2_error (dir->i_sb, function, "bad directory entry: %s\n"
"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
- error_msg, offset, de->inode, de->rec_len,
+ error_msg, offset, (unsigned long) de->inode, de->rec_len,
de->name_len);
return error_msg == NULL ? 1 : 0;
}
static int ext2_readdir (struct inode * inode, struct file * filp,
- struct dirent * dirent, int count)
+ void * dirent, filldir_t filldir)
{
+ int error = 0;
unsigned long offset, blk;
- int i, num, stored, dlen;
+ int i, num, stored;
struct buffer_head * bh, * tmp, * bha[16];
struct ext2_dir_entry * de;
struct super_block * sb;
@@ -115,7 +114,7 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
bh = NULL;
offset = filp->f_pos & (sb->s_blocksize - 1);
- while (count > 0 && !stored && filp->f_pos < inode->i_size) {
+ while (!error && !stored && filp->f_pos < inode->i_size) {
blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb);
bh = ext2_bread (inode, blk, 0, &err);
if (!bh) {
@@ -167,7 +166,7 @@ revalidate:
filp->f_version = inode->i_version;
}
- while (count > 0 && filp->f_pos < inode->i_size
+ while (!error && filp->f_pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct ext2_dir_entry *) (bh->b_data + offset);
if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
@@ -179,18 +178,8 @@ revalidate:
brelse (bh);
return stored;
}
+ offset += de->rec_len;
if (de->inode) {
- dlen = ROUND_UP(NAME_OFFSET(dirent)
- + de->name_len + 1);
- /* Old libc libraries always use a
- count of 1. */
- if (count == 1 && !stored)
- count = dlen;
- if (count < dlen) {
- count = 0;
- break;
- }
-
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
@@ -198,22 +187,13 @@ revalidate:
* not the directory has been modified
* during the copy operation. */
version = inode->i_version;
- i = de->name_len;
- memcpy_tofs (dirent->d_name, de->name, i);
- put_fs_long (de->inode, &dirent->d_ino);
- put_fs_byte (0, dirent->d_name + i);
- put_fs_word (i, &dirent->d_reclen);
- put_fs_long (dlen, &dirent->d_off);
+ error = filldir(dirent, de->name, de->name_len, filp->f_pos, de->inode);
+ if (error)
+ break;
if (version != inode->i_version)
goto revalidate;
- dcache_add(inode, de->name, de->name_len,
- de->inode);
-
- stored += dlen;
- count -= dlen;
- ((char *) dirent) += dlen;
+ stored ++;
}
- offset += de->rec_len;
filp->f_pos += de->rec_len;
}
offset = 0;
@@ -223,5 +203,5 @@ revalidate:
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
- return stored;
+ return 0;
}
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 20628b349..9491942c5 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/file.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
@@ -195,9 +196,37 @@ static int ext2_file_read (struct inode * inode, struct file * filp,
left -= chars;
read += chars;
if (*bhe) {
+#if 0
+printk("ext2_file_read() #1:\n");
+printk("ext2_file_read() #1.1: ");print_sp();
+#endif
memcpy_tofs (buf, offset + (*bhe)->b_data,
chars);
+#if 0
+printk("ext2_file_read() #2: buf == %08x\n", offset+(*bhe)->b_data);
+if(!buf)
+ {
+#if 0
+ printk("Flushing caches...\n");
+ sys_cacheflush(0, ~0, 3);
+#endif
+ printk("dumping #1 at %08lx...\n", (unsigned long) buf);
+ dump16(buf);
+ printk("dumping #2 at %08lx...\n", (unsigned long) (offset+(*bhe)->b_data));
+ dump16(offset+(*bhe)->b_data);
+#if 0
+ printk("Jumping to 0x0\n");
+ __asm__ __volatile__ ("jr\t%0;nop"::"r" (0));
+ printk("Freezing ...\n");
+ while(1);
+#endif
+ }
+/*dump_list(0);*/
+#endif
brelse (*bhe);
+#if 0
+printk("ext2_file_read() #3:\n");
+#endif
buf += chars;
} else {
while (chars-- > 0)
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index 2f79c4749..dd3d992c3 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -27,7 +27,7 @@
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
+static int sync_block (struct inode * inode, u32 * block, int wait)
{
struct buffer_head * bh;
int tmp;
@@ -55,7 +55,7 @@ static int sync_block (struct inode * inode, unsigned long * block, int wait)
return 0;
}
-static int sync_iblock (struct inode * inode, unsigned long * iblock,
+static int sync_iblock (struct inode * inode, u32 * iblock,
struct buffer_head ** bh, int wait)
{
int rc, tmp;
@@ -94,8 +94,7 @@ static int sync_direct (struct inode * inode, int wait)
return err;
}
-static int sync_indirect (struct inode * inode, unsigned long * iblock,
- int wait)
+static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
{
int i;
struct buffer_head * ind_bh;
@@ -107,7 +106,7 @@ static int sync_indirect (struct inode * inode, unsigned long * iblock,
for (i = 0; i < addr_per_block; i++) {
rc = sync_block (inode,
- ((unsigned long *) ind_bh->b_data) + i,
+ ((u32 *) ind_bh->b_data) + i,
wait);
if (rc > 0)
break;
@@ -118,8 +117,7 @@ static int sync_indirect (struct inode * inode, unsigned long * iblock,
return err;
}
-static int sync_dindirect (struct inode * inode, unsigned long * diblock,
- int wait)
+static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
{
int i;
struct buffer_head * dind_bh;
@@ -131,7 +129,7 @@ static int sync_dindirect (struct inode * inode, unsigned long * diblock,
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect (inode,
- ((unsigned long *) dind_bh->b_data) + i,
+ ((u32 *) dind_bh->b_data) + i,
wait);
if (rc > 0)
break;
@@ -142,8 +140,7 @@ static int sync_dindirect (struct inode * inode, unsigned long * diblock,
return err;
}
-static int sync_tindirect (struct inode * inode, unsigned long * tiblock,
- int wait)
+static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
{
int i;
struct buffer_head * tind_bh;
@@ -155,7 +152,7 @@ static int sync_tindirect (struct inode * inode, unsigned long * tiblock,
for (i = 0; i < addr_per_block; i++) {
rc = sync_dindirect (inode,
- ((unsigned long *) tind_bh->b_data) + i,
+ ((u32 *) tind_bh->b_data) + i,
wait);
if (rc > 0)
break;
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 69c9e2224..9102d02b2 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/ialloc.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* BSD ufs-inspired inode and directory allocation by
* Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
@@ -74,7 +75,7 @@ static void read_inode_bitmap (struct super_block * sb,
ext2_panic (sb, "read_inode_bitmap",
"Cannot read inode bitmap - "
"block_group = %lu, inode_bitmap = %lu",
- block_group, gdp->bg_inode_bitmap);
+ block_group, (unsigned long) gdp->bg_inode_bitmap);
sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
}
@@ -247,7 +248,7 @@ void ext2_free_inode (struct inode * inode)
set_inode_dtime (inode, gdp);
}
mark_buffer_dirty(bh, 1);
- if (sb->s_flags & MS_SYNC) {
+ if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
@@ -358,7 +359,7 @@ repeat:
else
{
/*
- * Try to place the inode in it's parent directory
+ * Try to place the inode in its parent directory
*/
i = dir->u.ext2_i.i_block_group;
tmp = get_group_desc (sb, i, &bh2);
@@ -414,7 +415,7 @@ repeat:
goto repeat;
}
mark_buffer_dirty(bh, 1);
- if (sb->s_flags & MS_SYNC) {
+ if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
@@ -476,7 +477,7 @@ repeat:
inode->u.ext2_i.i_block_group = i;
inode->i_op = NULL;
if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
- inode->i_flags |= MS_SYNC;
+ inode->i_flags |= MS_SYNCHRONOUS;
insert_inode_hash(inode);
inc_inode_version (inode, gdp, mode);
@@ -549,6 +550,6 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
ext2_error (sb, "ext2_check_inodes_bitmap",
"Wrong free inodes count in super block, "
"stored = %lu, counted = %lu",
- es->s_free_inodes_count, bitmap_count);
+ (unsigned long) es->s_free_inodes_count, bitmap_count);
unlock_super (sb);
}
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 7a3c37b79..127f4a9cd 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/inode.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
@@ -24,6 +25,7 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/locks.h>
+#include <linux/mm.h>
void ext2_put_inode (struct inode * inode)
{
@@ -45,7 +47,7 @@ static int block_bmap (struct buffer_head * bh, int nr)
if (!bh)
return 0;
- tmp = ((unsigned long *) bh->b_data)[nr];
+ tmp = ((u32 *) bh->b_data)[nr];
brelse (bh);
return tmp;
}
@@ -99,7 +101,7 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal)
"cannot get block %lu", result);
return 0;
}
- memset (bh->b_data, 0, inode->i_sb->s_blocksize);
+ memset(bh->b_data, 0, inode->i_sb->s_blocksize);
bh->b_uptodate = 1;
mark_buffer_dirty(bh, 1);
brelse (bh);
@@ -181,8 +183,8 @@ int ext2_bmap (struct inode * inode, int block)
static struct buffer_head * inode_getblk (struct inode * inode, int nr,
int create, int new_block, int * err)
{
+ u32 * p;
int tmp, goal = 0;
- unsigned long * p;
struct buffer_head * result;
int blocks = inode->i_sb->s_blocksize / 512;
@@ -249,7 +251,7 @@ static struct buffer_head * block_getblk (struct inode * inode,
int new_block, int * err)
{
int tmp, goal = 0;
- unsigned long * p;
+ u32 * p;
struct buffer_head * result;
int blocks = inode->i_sb->s_blocksize / 512;
@@ -263,7 +265,7 @@ static struct buffer_head * block_getblk (struct inode * inode,
return NULL;
}
}
- p = (unsigned long *) bh->b_data + nr;
+ p = (u32 *) bh->b_data + nr;
repeat:
tmp = *p;
if (tmp) {
@@ -286,8 +288,8 @@ repeat:
goal = inode->u.ext2_i.i_next_alloc_goal;
if (!goal) {
for (tmp = nr - 1; tmp >= 0; tmp--) {
- if (((unsigned long *) bh->b_data)[tmp]) {
- goal = ((unsigned long *)bh->b_data)[tmp];
+ if (((u32 *) bh->b_data)[tmp]) {
+ goal = ((u32 *)bh->b_data)[tmp];
break;
}
}
@@ -324,7 +326,7 @@ static int block_getcluster (struct inode * inode, struct buffer_head * bh,
int nr,
int blocksize)
{
- unsigned long * p;
+ u32 * p;
int firstblock = 0;
int result = 0;
int i;
@@ -337,7 +339,7 @@ static int block_getcluster (struct inode * inode, struct buffer_head * bh,
if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out;
for(i=0; i< (PAGE_SIZE / inode->i_sb->s_blocksize); i++) {
- p = (unsigned long *) bh->b_data + nr + i;
+ p = (u32 *) bh->b_data + nr + i;
/* All blocks in cluster must already be allocated */
if(*p == 0) goto out;
@@ -345,9 +347,9 @@ static int block_getcluster (struct inode * inode, struct buffer_head * bh,
/* See if aligned correctly */
if(i==0) firstblock = *p;
else if(*p != firstblock + i) goto out;
- };
+ }
- p = (unsigned long *) bh->b_data + nr;
+ p = (u32 *) bh->b_data + nr;
result = generate_cluster(bh->b_dev, (int *) p, blocksize);
out:
@@ -567,7 +569,7 @@ void ext2_read_inode (struct inode * inode)
else if (S_ISFIFO(inode->i_mode))
init_fifo(inode);
if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
- inode->i_flags |= MS_SYNC;
+ inode->i_flags |= MS_SYNCHRONOUS;
if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL)
inode->i_flags |= S_APPEND;
if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 447968ef0..e0de8de11 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/ioctl.c
*
- * Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*/
#include <asm/segment.h>
@@ -13,6 +14,7 @@
#include <linux/ext2_fs.h>
#include <linux/ioctl.h>
#include <linux/sched.h>
+#include <linux/mm.h>
int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
unsigned long arg)
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index f56c5404e..6c0b277e2 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/namei.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 37fae41ad..5cd418364 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/super.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
@@ -26,10 +27,11 @@
#include <linux/string.h>
#include <linux/locks.h>
+static char error_buf[1024];
+
void ext2_error (struct super_block * sb, const char * function,
const char * fmt, ...)
{
- char buf[1024];
va_list args;
if (!(sb->s_flags & MS_RDONLY)) {
@@ -39,15 +41,15 @@ void ext2_error (struct super_block * sb, const char * function,
sb->s_dirt = 1;
}
va_start (args, fmt);
- vsprintf (buf, fmt, args);
+ vsprintf (error_buf, fmt, args);
va_end (args);
if (test_opt (sb, ERRORS_PANIC) ||
(sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_PANIC &&
!test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
printk (KERN_CRIT "EXT2-fs error (device %d/%d): %s: %s\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
if (test_opt (sb, ERRORS_RO) ||
(sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_RO &&
!test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
@@ -59,7 +61,6 @@ void ext2_error (struct super_block * sb, const char * function,
NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
const char * fmt, ...)
{
- char buf[1024];
va_list args;
if (!(sb->s_flags & MS_RDONLY)) {
@@ -69,23 +70,22 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
sb->s_dirt = 1;
}
va_start (args, fmt);
- vsprintf (buf, fmt, args);
+ vsprintf (error_buf, fmt, args);
va_end (args);
panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
}
void ext2_warning (struct super_block * sb, const char * function,
const char * fmt, ...)
{
- char buf[1024];
va_list args;
va_start (args, fmt);
- vsprintf (buf, fmt, args);
+ vsprintf (error_buf, fmt, args);
va_end (args);
printk (KERN_WARNING "EXT2-fs warning (device %d/%d): %s: %s\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
}
void ext2_put_super (struct super_block * sb)
@@ -360,7 +360,7 @@ static int ext2_check_descriptors (struct super_block * sb)
ext2_error (sb, "ext2_check_descriptors",
"Block bitmap for group %d"
" not in group (block %lu)!",
- i, gdp->bg_block_bitmap);
+ i, (unsigned long) gdp->bg_block_bitmap);
return 0;
}
if (gdp->bg_inode_bitmap < block ||
@@ -369,7 +369,7 @@ static int ext2_check_descriptors (struct super_block * sb)
ext2_error (sb, "ext2_check_descriptors",
"Inode bitmap for group %d"
" not in group (block %lu)!",
- i, gdp->bg_inode_bitmap);
+ i, (unsigned long) gdp->bg_inode_bitmap);
return 0;
}
if (gdp->bg_inode_table < block ||
@@ -379,7 +379,7 @@ static int ext2_check_descriptors (struct super_block * sb)
ext2_error (sb, "ext2_check_descriptors",
"Inode table for group %d"
" not in group (block %lu)!",
- i, gdp->bg_inode_table);
+ i, (unsigned long) gdp->bg_inode_table);
return 0;
}
block += EXT2_BLOCKS_PER_GROUP(sb);
@@ -553,6 +553,31 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
return NULL;
}
+ if (sb->u.ext2_sb.s_blocks_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #blocks per group too big: %lu\n",
+ sb->u.ext2_sb.s_blocks_per_group);
+ return NULL;
+ }
+ if (sb->u.ext2_sb.s_frags_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #fragments per group too big: %lu\n",
+ sb->u.ext2_sb.s_frags_per_group);
+ return NULL;
+ }
+ if (sb->u.ext2_sb.s_inodes_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #inodes per group too big: %lu\n",
+ sb->u.ext2_sb.s_inodes_per_group);
+ return NULL;
+ }
+
sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
es->s_first_data_block +
EXT2_BLOCKS_PER_GROUP(sb) - 1) /
@@ -716,11 +741,11 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
return 0;
}
-void ext2_statfs (struct super_block * sb, struct statfs * buf)
+void ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
{
- long tmp;
unsigned long overhead;
unsigned long overhead_per_group;
+ struct statfs tmp;
if (test_opt (sb, MINIX_DF))
overhead = 0;
@@ -737,19 +762,15 @@ void ext2_statfs (struct super_block * sb, struct statfs * buf)
sb->u.ext2_sb.s_groups_count * overhead_per_group;
}
- put_fs_long (EXT2_SUPER_MAGIC, &buf->f_type);
- put_fs_long (sb->s_blocksize, &buf->f_bsize);
- put_fs_long (sb->u.ext2_sb.s_es->s_blocks_count - overhead,
- &buf->f_blocks);
- tmp = ext2_count_free_blocks (sb);
- put_fs_long (tmp, &buf->f_bfree);
- if (tmp >= sb->u.ext2_sb.s_es->s_r_blocks_count)
- put_fs_long (tmp - sb->u.ext2_sb.s_es->s_r_blocks_count,
- &buf->f_bavail);
- else
- put_fs_long (0, &buf->f_bavail);
- put_fs_long (sb->u.ext2_sb.s_es->s_inodes_count, &buf->f_files);
- put_fs_long (ext2_count_free_inodes (sb), &buf->f_ffree);
- put_fs_long (EXT2_NAME_LEN, &buf->f_namelen);
- /* Don't know what value to put in buf->f_fsid */
+ tmp.f_type = EXT2_SUPER_MAGIC;
+ tmp.f_bsize = sb->s_blocksize;
+ tmp.f_blocks = sb->u.ext2_sb.s_es->s_blocks_count - overhead;
+ tmp.f_bfree = ext2_count_free_blocks (sb);
+ tmp.f_bavail = tmp.f_bfree - sb->u.ext2_sb.s_es->s_r_blocks_count;
+ if (tmp.f_bfree < sb->u.ext2_sb.s_es->s_r_blocks_count)
+ tmp.f_bavail = 0;
+ tmp.f_files = sb->u.ext2_sb.s_es->s_inodes_count;
+ tmp.f_ffree = ext2_count_free_inodes (sb);
+ tmp.f_namelen = EXT2_NAME_LEN;
+ memcpy_tofs(buf, &tmp, bufsiz);
}
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 7d85ed74c..66d4ab860 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/symlink.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
diff --git a/fs/ext2/truncate.c b/fs/ext2/truncate.c
index 10a1fd236..94a64f3e0 100644
--- a/fs/ext2/truncate.c
+++ b/fs/ext2/truncate.c
@@ -1,9 +1,10 @@
/*
* linux/fs/ext2/truncate.c
*
- * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
*
* from
*
@@ -45,8 +46,8 @@ static int ext2_secrm_seed = 152; /* Random generator base */
static int trunc_direct (struct inode * inode)
{
+ u32 * p;
int i, tmp;
- unsigned long * p;
struct buffer_head * bh;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
@@ -102,12 +103,12 @@ repeat:
return retry;
}
-static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
+static int trunc_indirect (struct inode * inode, int offset, u32 * p)
{
int i, tmp;
struct buffer_head * bh;
struct buffer_head * ind_bh;
- unsigned long * ind;
+ u32 * ind;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
int retry = 0;
@@ -134,7 +135,7 @@ repeat:
i = 0;
if (i < indirect_block)
goto repeat;
- ind = i + (unsigned long *) ind_bh->b_data;
+ ind = i + (u32 *) ind_bh->b_data;
tmp = *ind;
if (!tmp)
continue;
@@ -176,7 +177,7 @@ repeat:
}
if (free_count > 0)
ext2_free_blocks (inode->i_sb, block_to_free, free_count);
- ind = (unsigned long *) ind_bh->b_data;
+ ind = (u32 *) ind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
if (*(ind++))
break;
@@ -199,11 +200,11 @@ repeat:
}
static int trunc_dindirect (struct inode * inode, int offset,
- unsigned long * p)
+ u32 * p)
{
int i, tmp;
struct buffer_head * dind_bh;
- unsigned long * dind;
+ u32 * dind;
int retry = 0;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int blocks = inode->i_sb->s_blocksize / 512;
@@ -228,7 +229,7 @@ repeat:
i = 0;
if (i < dindirect_block)
goto repeat;
- dind = i + (unsigned long *) dind_bh->b_data;
+ dind = i + (u32 *) dind_bh->b_data;
tmp = *dind;
if (!tmp)
continue;
@@ -236,7 +237,7 @@ repeat:
dind);
mark_buffer_dirty(dind_bh, 1);
}
- dind = (unsigned long *) dind_bh->b_data;
+ dind = (u32 *) dind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
if (*(dind++))
break;
@@ -262,7 +263,7 @@ static int trunc_tindirect (struct inode * inode)
{
int i, tmp;
struct buffer_head * tind_bh;
- unsigned long * tind, * p;
+ u32 * tind, * p;
int retry = 0;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int blocks = inode->i_sb->s_blocksize / 512;
@@ -289,13 +290,13 @@ repeat:
i = 0;
if (i < tindirect_block)
goto repeat;
- tind = i + (unsigned long *) tind_bh->b_data;
+ tind = i + (u32 *) tind_bh->b_data;
retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
addr_per_block + (i + 1) * addr_per_block * addr_per_block,
tind);
mark_buffer_dirty(tind_bh, 1);
}
- tind = (unsigned long *) tind_bh->b_data;
+ tind = (u32 *) tind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
if (*(tind++))
break;
@@ -320,6 +321,9 @@ repeat:
void ext2_truncate (struct inode * inode)
{
int retry;
+ struct buffer_head * bh;
+ int err;
+ int offset;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
@@ -331,10 +335,10 @@ void ext2_truncate (struct inode * inode)
down(&inode->i_sem);
retry = trunc_direct(inode);
retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
- (unsigned long *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
+ (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
EXT2_ADDR_PER_BLOCK(inode->i_sb),
- (unsigned long *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
+ (u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
retry |= trunc_tindirect (inode);
up(&inode->i_sem);
if (!retry)
@@ -344,6 +348,23 @@ void ext2_truncate (struct inode * inode)
current->counter = 0;
schedule ();
}
+ /*
+ * If the file is not being truncated to a block boundary, the
+ * contents of the partial block following the end of the file must be
+ * zeroed in case it ever becomes accessible again because of
+ * subsequent file growth.
+ */
+ offset = inode->i_size % inode->i_sb->s_blocksize;
+ if (offset) {
+ bh = ext2_bread (inode, inode->i_size / inode->i_sb->s_blocksize,
+ 0, &err);
+ if (bh) {
+ memset (bh->b_data + offset, 0,
+ inode->i_sb->s_blocksize - offset);
+ mark_buffer_dirty (bh, 0);
+ brelse (bh);
+ }
+ }
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
}