[PATCH] ufs: directory and page cache: from blocks to pages
Change function in fs/ufs/dir.c and fs/ufs/namei.c to work with pages instead of straight work with blocks. It fixed such bugs: * for i in `seq 1 1000`; do touch $i; done - crash system * mkdir create directory without "." and ".." entries Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
826843a347
commit
b71034e5e6
999
fs/ufs/dir.c
999
fs/ufs/dir.c
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* linux/fs/ufs/namei.c
|
* linux/fs/ufs/namei.c
|
||||||
*
|
*
|
||||||
|
* Migration to usage of "page cache" on May 2006 by
|
||||||
|
* Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
|
||||||
|
*
|
||||||
* Copyright (C) 1998
|
* Copyright (C) 1998
|
||||||
* Daniel Pirkl <daniel.pirkl@email.cz>
|
* Daniel Pirkl <daniel.pirkl@email.cz>
|
||||||
* Charles University, Faculty of Mathematics and Physics
|
* Charles University, Faculty of Mathematics and Physics
|
||||||
|
@ -28,7 +31,6 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/ufs_fs.h>
|
#include <linux/ufs_fs.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include "swab.h" /* will go away - see comment in mknod() */
|
#include "swab.h" /* will go away - see comment in mknod() */
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -232,19 +234,18 @@ out_dir:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ufs_unlink(struct inode * dir, struct dentry *dentry)
|
static int ufs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode * inode = dentry->d_inode;
|
struct inode * inode = dentry->d_inode;
|
||||||
struct buffer_head * bh;
|
struct ufs_dir_entry *de;
|
||||||
struct ufs_dir_entry * de;
|
struct page *page;
|
||||||
int err = -ENOENT;
|
int err = -ENOENT;
|
||||||
|
|
||||||
lock_kernel();
|
de = ufs_find_entry(dir, dentry, &page);
|
||||||
de = ufs_find_entry (dentry, &bh);
|
|
||||||
if (!de)
|
if (!de)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = ufs_delete_entry (dir, de, bh);
|
err = ufs_delete_entry(dir, de, page);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -252,7 +253,6 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry)
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
err = 0;
|
err = 0;
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,42 +274,42 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
|
static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||||
struct inode * new_dir, struct dentry * new_dentry )
|
struct inode *new_dir, struct dentry *new_dentry)
|
||||||
{
|
{
|
||||||
struct inode *old_inode = old_dentry->d_inode;
|
struct inode *old_inode = old_dentry->d_inode;
|
||||||
struct inode *new_inode = new_dentry->d_inode;
|
struct inode *new_inode = new_dentry->d_inode;
|
||||||
struct buffer_head *dir_bh = NULL;
|
struct page *dir_page = NULL;
|
||||||
struct ufs_dir_entry *dir_de = NULL;
|
struct ufs_dir_entry * dir_de = NULL;
|
||||||
struct buffer_head *old_bh;
|
struct page *old_page;
|
||||||
struct ufs_dir_entry *old_de;
|
struct ufs_dir_entry *old_de;
|
||||||
int err = -ENOENT;
|
int err = -ENOENT;
|
||||||
|
|
||||||
lock_kernel();
|
old_de = ufs_find_entry(old_dir, old_dentry, &old_page);
|
||||||
old_de = ufs_find_entry (old_dentry, &old_bh);
|
|
||||||
if (!old_de)
|
if (!old_de)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (S_ISDIR(old_inode->i_mode)) {
|
if (S_ISDIR(old_inode->i_mode)) {
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
dir_de = ufs_dotdot(old_inode, &dir_bh);
|
dir_de = ufs_dotdot(old_inode, &dir_page);
|
||||||
if (!dir_de)
|
if (!dir_de)
|
||||||
goto out_old;
|
goto out_old;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_inode) {
|
if (new_inode) {
|
||||||
struct buffer_head *new_bh;
|
struct page *new_page;
|
||||||
struct ufs_dir_entry *new_de;
|
struct ufs_dir_entry *new_de;
|
||||||
|
|
||||||
err = -ENOTEMPTY;
|
err = -ENOTEMPTY;
|
||||||
if (dir_de && !ufs_empty_dir (new_inode))
|
if (dir_de && !ufs_empty_dir(new_inode))
|
||||||
goto out_dir;
|
goto out_dir;
|
||||||
|
|
||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
new_de = ufs_find_entry (new_dentry, &new_bh);
|
new_de = ufs_find_entry(new_dir, new_dentry, &new_page);
|
||||||
if (!new_de)
|
if (!new_de)
|
||||||
goto out_dir;
|
goto out_dir;
|
||||||
inode_inc_link_count(old_inode);
|
inode_inc_link_count(old_inode);
|
||||||
ufs_set_link(new_dir, new_de, new_bh, old_inode);
|
ufs_set_link(new_dir, new_de, new_page, old_inode);
|
||||||
new_inode->i_ctime = CURRENT_TIME_SEC;
|
new_inode->i_ctime = CURRENT_TIME_SEC;
|
||||||
if (dir_de)
|
if (dir_de)
|
||||||
new_inode->i_nlink--;
|
new_inode->i_nlink--;
|
||||||
|
@ -330,24 +330,32 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
|
||||||
inode_inc_link_count(new_dir);
|
inode_inc_link_count(new_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
ufs_delete_entry (old_dir, old_de, old_bh);
|
/*
|
||||||
|
* Like most other Unix systems, set the ctime for inodes on a
|
||||||
|
* rename.
|
||||||
|
* inode_dec_link_count() will mark the inode dirty.
|
||||||
|
*/
|
||||||
|
old_inode->i_ctime = CURRENT_TIME_SEC;
|
||||||
|
|
||||||
|
ufs_delete_entry(old_dir, old_de, old_page);
|
||||||
inode_dec_link_count(old_inode);
|
inode_dec_link_count(old_inode);
|
||||||
|
|
||||||
if (dir_de) {
|
if (dir_de) {
|
||||||
ufs_set_link(old_inode, dir_de, dir_bh, new_dir);
|
ufs_set_link(old_inode, dir_de, dir_page, new_dir);
|
||||||
inode_dec_link_count(old_dir);
|
inode_dec_link_count(old_dir);
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
out_dir:
|
out_dir:
|
||||||
if (dir_de)
|
if (dir_de) {
|
||||||
brelse(dir_bh);
|
kunmap(dir_page);
|
||||||
|
page_cache_release(dir_page);
|
||||||
|
}
|
||||||
out_old:
|
out_old:
|
||||||
brelse (old_bh);
|
kunmap(old_page);
|
||||||
|
page_cache_release(old_page);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -887,11 +887,12 @@ extern struct inode_operations ufs_dir_inode_operations;
|
||||||
extern int ufs_add_link (struct dentry *, struct inode *);
|
extern int ufs_add_link (struct dentry *, struct inode *);
|
||||||
extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
|
extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
|
||||||
extern int ufs_make_empty(struct inode *, struct inode *);
|
extern int ufs_make_empty(struct inode *, struct inode *);
|
||||||
extern struct ufs_dir_entry * ufs_find_entry (struct dentry *, struct buffer_head **);
|
extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **);
|
||||||
extern int ufs_delete_entry (struct inode *, struct ufs_dir_entry *, struct buffer_head *);
|
extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
|
||||||
extern int ufs_empty_dir (struct inode *);
|
extern int ufs_empty_dir (struct inode *);
|
||||||
extern struct ufs_dir_entry * ufs_dotdot (struct inode *, struct buffer_head **);
|
extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
|
||||||
extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_head *, struct inode *);
|
extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
|
||||||
|
struct page *page, struct inode *inode);
|
||||||
|
|
||||||
/* file.c */
|
/* file.c */
|
||||||
extern struct inode_operations ufs_file_inode_operations;
|
extern struct inode_operations ufs_file_inode_operations;
|
||||||
|
|
Loading…
Reference in New Issue