Commit 1b081ced authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.45pre7

parent 13e551b9
......@@ -173,7 +173,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
}
if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
d_delete(s->s_root);
dput(s->s_root);
s->s_dev = 0;
kfree(sbi);
printk("autofs: called with bogus options\n");
......@@ -182,7 +182,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
}
if ( minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION ) {
d_delete(s->s_root);
dput(s->s_root);
s->s_dev = 0;
kfree(sbi);
printk("autofs: kernel does not match daemon version\n");
......@@ -199,7 +199,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
} else {
printk("autofs: could not open pipe file descriptor\n");
}
d_delete(s->s_root);
dput(s->s_root);
s->s_dev = 0;
kfree(sbi);
MOD_DEC_USE_COUNT;
......
......@@ -213,6 +213,17 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
return 0;
}
/*
* NOTE!
*
* Normal filesystems would do a "d_delete()" to tell the VFS dcache
* that the file no longer exists. However, doing that means that the
* VFS layer can turn the dentry into a negative dentry, which we
* obviously do not want (we're dropping the entry not because it
* doesn't exist, but because it has timed out).
*
* Also see autofs_root_rmdir()..
*/
static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
......@@ -234,7 +245,7 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
autofs_hash_delete(ent);
clear_bit(n,sbi->symlink_bitmap);
kfree(sbi->symlink[n].data);
d_delete(dentry);
d_drop(dentry);
return 0;
}
......@@ -257,7 +268,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
autofs_hash_delete(ent);
dir->i_nlink--;
d_delete(dentry);
d_drop(dentry);
return 0;
}
......
......@@ -158,6 +158,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_name.name = str;
dentry->d_name.len = name->len;
dentry->d_name.hash = name->hash;
dentry->d_revalidate = NULL;
return dentry;
}
......@@ -239,6 +240,7 @@ static inline void d_remove_from_parent(struct dentry * dentry, struct dentry *
dput(parent);
}
/*
* When a file is deleted, we have two options:
* - turn this dentry into a negative dentry
......@@ -266,12 +268,10 @@ void d_delete(struct dentry * dentry)
}
/*
* If not, just unhash us and wait for dput()
* to pick up the tab..
* If not, just drop the dentry and let dput
* pick up the tab..
*/
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
d_drop(dentry);
}
void d_add(struct dentry * entry, struct inode * inode)
......
......@@ -216,7 +216,6 @@ void ext2_free_inode (struct inode * inode)
es->s_free_inodes_count =
cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
mark_inode_dirty(inode);
}
mark_buffer_dirty(bh, 1);
if (sb->s_flags & MS_SYNCHRONOUS) {
......
......@@ -319,32 +319,34 @@ struct inode * get_empty_inode(void)
{
static unsigned long last_ino = 0;
struct inode * inode;
struct list_head * tmp = inode_unused.next;
struct list_head * tmp;
spin_lock(&inode_lock);
tmp = inode_unused.next;
if (tmp != &inode_unused) {
list_del(tmp);
inode = list_entry(tmp, struct inode, i_list);
add_new_inode:
INIT_LIST_HEAD(&inode->i_list);
INIT_LIST_HEAD(&inode->i_hash);
inode->i_sb = NULL;
inode->i_ino = ++last_ino;
atomic_set(&inode->i_count, 1);
list_add(&inode->i_list, &inode_in_use);
inode->i_state = 0;
spin_unlock(&inode_lock);
clean_inode(inode);
return inode;
}
/*
* Warning: if this succeeded, we will now
* return with the inode lock, and we need to
* unlock it.
* return with the inode lock.
*/
spin_unlock(&inode_lock);
inode = grow_inodes();
if (inode) {
spin_unlock(&inode_lock);
if (inode)
goto add_new_inode;
}
return inode;
}
......@@ -368,6 +370,13 @@ struct inode * get_pipe_inode(void)
PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
PIPE_LOCK(*inode) = 0;
/*
* Mark the inode dirty from the very beginning,
* that way it will never be moved to the dirty
* list because "make_inode_dirty()" will think
* that it already _is_ on the dirty list.
*/
inode->i_state = 1 << I_DIRTY;
inode->i_pipe = 1;
inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
inode->i_uid = current->fsuid;
......@@ -465,6 +474,12 @@ void iput(struct inode *inode)
*/
if (atomic_read(&inode->i_count) == 1) {
void (*put)(struct inode *);
if (inode->i_pipe) {
free_page((unsigned long)PIPE_BASE(*inode));
PIPE_BASE(*inode)= NULL;
}
if (inode->i_sb && inode->i_sb->s_op) {
put = inode->i_sb->s_op->put_inode;
if (put)
......@@ -507,13 +522,13 @@ int fs_may_mount(kdev_t dev)
return 1;
}
int fs_may_umount(kdev_t dev, struct dentry * root)
int fs_may_umount(struct super_block *sb, struct dentry * root)
{
shrink_dcache();
return root->d_count == 1;
}
int fs_may_remount_ro(kdev_t dev)
int fs_may_remount_ro(struct super_block *sb)
{
return 0;
return 1;
}
......@@ -280,15 +280,8 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
struct dentry * dentry = d_lookup(parent, name);
if (dentry) {
/*
* FIXME! We should have something like
dentry = dentry->revalidate(dentry);
* here - we need to ask the low-level filesystem permission
* to use the cached entry (NFS needs to time them out, and
* /proc might go away etc).
*/
if (dentry->d_revalidate)
dentry = dentry->d_revalidate(dentry);
/*
* The parent d_count _should_ be at least 2: one for the
......
......@@ -611,7 +611,7 @@ static int do_umount(kdev_t dev,int unmount_root)
* too bad there are no quotas running anymore. Turn them on again by hand.
*/
quota_off(dev, -1);
if (!fs_may_umount(dev, sb->s_root))
if (!fs_may_umount(sb, sb->s_root))
return -EBUSY;
/* clean up dcache .. */
......@@ -785,7 +785,7 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data)
/*flags |= MS_RDONLY;*/
/* If we are remounting RDONLY, make sure there are no rw files open */
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
if (!fs_may_remount_ro(sb->s_dev))
if (!fs_may_remount_ro(sb))
return -EBUSY;
sb->s_flags = (flags & ~MS_RDONLY) | (sb->s_flags & MS_RDONLY);
if (sb->s_op && sb->s_op->remount_fs) {
......
......@@ -49,8 +49,28 @@ struct dentry {
struct list_head d_alias; /* inode alias list */
struct list_head d_lru; /* d_count = 0 LRU list */
struct qstr d_name;
struct dentry * (*d_revalidate)(struct dentry *);
};
/*
* d_drop() unhashes the entry from the parent
* dentry hashes, so that it won't be found through
* a VFS lookup any more. Note that this is different
* from deleting the dentry - d_delete will try to
* mark the dentry negative if possible, giving a
* successful _negative_ lookup, while d_drop will
* just make the cache lookup fail.
*
* d_drop() is used mainly for stuff that wants
* to invalidate a dentry for some reason (NFS
* timeouts or autofs deletes).
*/
inline void d_drop(struct dentry * dentry)
{
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
}
/*
* These are the low-level FS interfaces to the dcache..
*/
......
......@@ -629,8 +629,8 @@ extern struct file_operations rdwr_pipe_fops;
extern struct file_system_type *get_fs_type(const char *name);
extern int fs_may_mount(kdev_t dev);
extern int fs_may_umount(kdev_t dev, struct dentry * root);
extern int fs_may_remount_ro(kdev_t dev);
extern int fs_may_umount(struct super_block *, struct dentry * root);
extern int fs_may_remount_ro(struct super_block *);
extern struct file *inuse_filps;
extern struct super_block super_blocks[NR_SUPER];
......
......@@ -148,6 +148,8 @@ EXPORT_SYMBOL(lookup_dentry);
EXPORT_SYMBOL(open_namei);
EXPORT_SYMBOL(sys_close);
EXPORT_SYMBOL(close_fp);
EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete);
EXPORT_SYMBOL(insert_file_free);
EXPORT_SYMBOL(check_disk_change);
EXPORT_SYMBOL(invalidate_buffers);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment