summaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/balloc.c5
-rw-r--r--fs/ext2/dir.c14
-rw-r--r--fs/ext2/file.c1
-rw-r--r--fs/ext2/ialloc.c6
-rw-r--r--fs/ext2/namei.c38
-rw-r--r--fs/ext2/super.c12
-rw-r--r--fs/ext2/symlink.c57
7 files changed, 34 insertions, 99 deletions
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 171de1cf5..4d2b561ee 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -291,6 +291,7 @@ int ext2_new_block (const struct inode * inode, unsigned long goal,
printk ("ext2_new_block: nonexistent device");
return 0;
}
+retry:
lock_super (sb);
es = sb->u.ext2_sb.s_es;
if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
@@ -298,6 +299,8 @@ int ext2_new_block (const struct inode * inode, unsigned long goal,
(sb->u.ext2_sb.s_resgid == 0 ||
!in_group_p (sb->u.ext2_sb.s_resgid)))) {
unlock_super (sb);
+ if(sb->s_ibasket && free_ibasket(sb))
+ goto retry;
return 0;
}
@@ -389,6 +392,8 @@ repeat:
}
if (k >= sb->u.ext2_sb.s_groups_count) {
unlock_super (sb);
+ if(sb->s_ibasket && free_ibasket(sb))
+ goto retry;
return 0;
}
bitmap_nr = load_block_bitmap (sb, i);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index fce6fc4c8..d9b1957e3 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -65,7 +65,6 @@ struct inode_operations ext2_dir_inode_operations = {
ext2_mknod, /* mknod */
ext2_rename, /* rename */
NULL, /* readlink */
- NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
@@ -194,12 +193,13 @@ revalidate:
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
- * during the copy operation. */
- unsigned long version;
- dcache_add(inode, de->name, le16_to_cpu(de->name_len),
- le32_to_cpu(de->inode));
- version = inode->i_version;
- error = filldir(dirent, de->name, le16_to_cpu(de->name_len), filp->f_pos, le32_to_cpu(de->inode));
+ * during the copy operation.
+ */
+ unsigned long version = inode->i_version;
+
+ error = filldir(dirent, de->name,
+ le16_to_cpu(de->name_len),
+ filp->f_pos, le32_to_cpu(de->inode));
if (error)
break;
if (version != inode->i_version)
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 274dc31fd..1627f5cee 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -72,7 +72,6 @@ struct inode_operations ext2_file_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
- NULL, /* follow_link */
generic_readpage, /* readpage */
NULL, /* writepage */
ext2_bmap, /* bmap */
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 16751329e..a486679f9 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -171,9 +171,9 @@ void ext2_free_inode (struct inode * inode)
printk ("ext2_free_inode: inode has no device\n");
return;
}
- if (inode->i_count > 1) {
+ if (atomic_read(&inode->i_count) > 1) {
printk ("ext2_free_inode: inode has count=%d\n",
- inode->i_count);
+ atomic_read(&inode->i_count));
return;
}
if (inode->i_nlink) {
@@ -404,7 +404,7 @@ repeat:
sb->s_dirt = 1;
inode->i_mode = mode;
inode->i_sb = sb;
- inode->i_count = 1;
+ atomic_set(&inode->i_count, 1);
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 39716678a..421393581 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -172,27 +172,12 @@ int ext2_lookup (struct inode * dir, const char * name, int len,
iput (dir);
return -ENAMETOOLONG;
}
- if (dcache_lookup(dir, name, len, &ino)) {
- if (!ino) {
- iput(dir);
- return -ENOENT;
- }
- if (!(*result = iget (dir->i_sb, ino))) {
- iput (dir);
- return -EACCES;
- }
- iput (dir);
- return 0;
- }
ino = dir->i_version;
if (!(bh = ext2_find_entry (dir, name, len, &de))) {
- if (ino == dir->i_version)
- dcache_add(dir, name, len, 0);
iput (dir);
return -ENOENT;
}
ino = le32_to_cpu(de->inode);
- dcache_add(dir, name, len, ino);
brelse (bh);
if (!(*result = iget (dir->i_sb, ino))) {
iput (dir);
@@ -391,7 +376,6 @@ int ext2_create (struct inode * dir,const char * name, int len, int mode,
}
de->inode = cpu_to_le32(inode->i_ino);
dir->i_version = ++event;
- dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
@@ -460,7 +444,6 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
}
de->inode = cpu_to_le32(inode->i_ino);
dir->i_version = ++event;
- dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
@@ -538,7 +521,6 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
}
de->inode = cpu_to_le32(inode->i_ino);
dir->i_version = ++event;
- dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
@@ -662,7 +644,7 @@ repeat:
else if (le32_to_cpu(de->inode) != inode->i_ino)
retval = -ENOENT;
else {
- if (inode->i_count > 1) {
+ if (atomic_read(&inode->i_count) > 1) {
/*
* Are we deleting the last instance of a busy directory?
* Better clean up if so.
@@ -836,7 +818,6 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
}
de->inode = cpu_to_le32(inode->i_ino);
dir->i_version = ++event;
- dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
@@ -885,7 +866,6 @@ int ext2_link (struct inode * oldinode, struct inode * dir,
}
de->inode = cpu_to_le32(oldinode->i_ino);
dir->i_version = ++event;
- dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
@@ -905,7 +885,7 @@ static int subdir (struct inode * new_inode, struct inode * old_inode)
int ino;
int result;
- new_inode->i_count++;
+ atomic_inc(&new_inode->i_count);
result = 0;
for (;;) {
if (new_inode == old_inode) {
@@ -945,8 +925,7 @@ static int subdir (struct inode * new_inode, struct inode * old_inode)
*/
static int do_ext2_rename (struct inode * old_dir, const char * old_name,
int old_len, struct inode * new_dir,
- const char * new_name, int new_len,
- int must_be_dir)
+ const char * new_name, int new_len)
{
struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh;
@@ -981,8 +960,6 @@ start_up:
old_inode = __iget (old_dir->i_sb, le32_to_cpu(old_de->inode), 0); /* don't cross mnt-points */
if (!old_inode)
goto end_rename;
- if (must_be_dir && !S_ISDIR(old_inode->i_mode))
- goto end_rename;
retval = -EPERM;
if ((old_dir->i_mode & S_ISVTX) &&
current->fsuid != old_inode->i_uid &&
@@ -1016,7 +993,7 @@ start_up:
if (!empty_dir (new_inode))
goto end_rename;
retval = -EBUSY;
- if (new_inode->i_count > 1)
+ if (atomic_read(&new_inode->i_count) > 1)
goto end_rename;
}
retval = -EPERM;
@@ -1059,7 +1036,6 @@ start_up:
* ok, that's it
*/
new_de->inode = le32_to_cpu(old_inode->i_ino);
- dcache_add(new_dir, new_de->name, le16_to_cpu(new_de->name_len), le32_to_cpu(new_de->inode));
retval = ext2_delete_entry (old_de, old_bh);
if (retval == -ENOENT)
goto try_again;
@@ -1075,7 +1051,6 @@ start_up:
old_dir->i_dirt = 1;
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
- dcache_add(old_inode, "..", 2, new_dir->i_ino);
mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
@@ -1123,8 +1098,7 @@ end_rename:
* on the same file system
*/
int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len,
- int must_be_dir)
+ struct inode * new_dir, const char * new_name, int new_len)
{
int result;
@@ -1132,7 +1106,7 @@ int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
- new_name, new_len, must_be_dir);
+ new_name, new_len);
old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
return result;
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 5885e3067..635a45692 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -319,6 +319,13 @@ static void ext2_setup_super (struct super_block * sb,
ext2_check_inodes_bitmap (sb);
}
}
+#if 0 /* ibasket's still have unresolved bugs... -DaveM */
+
+ /* [T. Schoebel-Theuer] This limit should be maintained on disk.
+ * This is just provisionary.
+ */
+ sb->s_ibasket_max = 100;
+#endif
}
static int ext2_check_descriptors (struct super_block * sb)
@@ -728,7 +735,10 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
}
static struct file_system_type ext2_fs_type = {
- ext2_read_super, "ext2", 1, NULL
+ "ext2",
+ FS_REQUIRES_DEV /* | FS_IBASKET */, /* ibaskets have unresolved bugs */
+ ext2_read_super,
+ NULL
};
__initfunc(int init_ext2_fs(void))
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 31f8276b0..4d5a5cada 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -25,8 +25,6 @@
#include <linux/stat.h>
static int ext2_readlink (struct inode *, char *, int);
-static int ext2_follow_link (struct inode *, struct inode *, int, int,
- struct inode **);
/*
* symlinks can't do much...
@@ -43,7 +41,6 @@ struct inode_operations ext2_symlink_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
ext2_readlink, /* readlink */
- ext2_follow_link, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
@@ -52,70 +49,20 @@ struct inode_operations ext2_symlink_inode_operations = {
NULL /* smap */
};
-static int ext2_follow_link(struct inode * dir, struct inode * inode,
- int flag, int mode, struct inode ** res_inode)
-{
- int error;
- struct buffer_head * bh = NULL;
- char * link;
-
- *res_inode = NULL;
- if (!dir) {
- dir = current->fs->root;
- dir->i_count++;
- }
- if (!inode) {
- iput (dir);
- return -ENOENT;
- }
- if (!S_ISLNK(inode->i_mode)) {
- iput (dir);
- *res_inode = inode;
- return 0;
- }
- if (current->link_count > 5) {
- iput (dir);
- iput (inode);
- return -ELOOP;
- }
- if (inode->i_blocks) {
- if (!(bh = ext2_bread (inode, 0, 0, &error))) {
- iput (dir);
- iput (inode);
- return -EIO;
- }
- link = bh->b_data;
- } else
- link = (char *) inode->u.ext2_i.i_data;
- if (DO_UPDATE_ATIME(inode)) {
- inode->i_atime = CURRENT_TIME;
- inode->i_dirt = 1;
- }
- current->link_count++;
- error = open_namei (link, flag, mode, res_inode, dir);
- current->link_count--;
- iput (inode);
- if (bh)
- brelse (bh);
- return error;
-}
-
static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
{
struct buffer_head * bh = NULL;
char * link;
int i, err;
- if (!S_ISLNK(inode->i_mode)) {
- iput (inode);
- return -EINVAL;
- }
if (buflen > inode->i_sb->s_blocksize - 1)
buflen = inode->i_sb->s_blocksize - 1;
if (inode->i_blocks) {
bh = ext2_bread (inode, 0, 0, &err);
if (!bh) {
iput (inode);
+ if(err < 0) /* indicate type of error */
+ return err;
return 0;
}
link = bh->b_data;