Commit 0d1267fe authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.45pre1

parent fe01eea7
...@@ -1125,8 +1125,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long ...@@ -1125,8 +1125,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long
* update the access time. * update the access time.
*/ */
if (inode && count != 0) { if (inode && count != 0) {
inode->i_atime = CURRENT_TIME; UPDATE_ATIME(inode);
inode->i_dirt = 1;
} }
return (count ? count : retval); return (count ? count : retval);
...@@ -1182,7 +1181,7 @@ random_write(struct inode * inode, struct file * file, ...@@ -1182,7 +1181,7 @@ random_write(struct inode * inode, struct file * file,
} }
if ((ret > 0) && inode) { if ((ret > 0) && inode) {
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
return ret; return ret;
} }
......
...@@ -74,7 +74,7 @@ void inode_setattr(struct inode * inode, struct iattr * attr) ...@@ -74,7 +74,7 @@ void inode_setattr(struct inode * inode, struct iattr * attr)
if (!fsuser() && !in_group_p(inode->i_gid)) if (!fsuser() && !in_group_p(inode->i_gid))
inode->i_mode &= ~S_ISGID; inode->i_mode &= ~S_ISGID;
} }
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
} }
......
...@@ -274,5 +274,4 @@ static void autofs_read_inode(struct inode *inode) ...@@ -274,5 +274,4 @@ static void autofs_read_inode(struct inode *inode)
static void autofs_write_inode(struct inode *inode) static void autofs_write_inode(struct inode *inode)
{ {
inode->i_dirt = 0;
} }
...@@ -136,9 +136,10 @@ static int autofs_root_lookup(struct inode *dir, struct qstr *str, struct inode ...@@ -136,9 +136,10 @@ static int autofs_root_lookup(struct inode *dir, struct qstr *str, struct inode
return -EACCES; return -EACCES;
} }
if ( !oz_mode && S_ISDIR(res->i_mode) && res->i_sb == dir->i_sb ) { if ( !oz_mode && S_ISDIR(res->i_mode) && res->i_dentry->d_covers == res->i_dentry ) {
/* Not a mount point yet, call 1-800-DAEMON */ /* Not a mount point yet, call 1-800-DAEMON */
DPRINTK(("autofs: waiting on non-mountpoint dir, inode = %lu, pid = %u, pgrp = %u\n", res->i_ino, current->pid, current->pgrp)); DPRINTK(("autofs: waiting on non-mountpoint dir, inode = %lu, pid = %u, pgrp = %u\n", res->i_ino, current->pid, current->pgrp));
iput(res);
res = NULL; res = NULL;
up(&dir->i_sem); up(&dir->i_sem);
status = autofs_wait(sbi,str); status = autofs_wait(sbi,str);
......
...@@ -214,7 +214,6 @@ do_aout_core_dump(long signr, struct pt_regs * regs) ...@@ -214,7 +214,6 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
/* Finally dump the task struct. Not be used by gdb, but could be useful */ /* Finally dump the task struct. Not be used by gdb, but could be useful */
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
DUMP_WRITE(current,sizeof(*current)); DUMP_WRITE(current,sizeof(*current));
inode->i_status |= ST_MODIFIED;
close_coredump: close_coredump:
if (file.f_op->release) if (file.f_op->release)
file.f_op->release(inode,&file); file.f_op->release(inode,&file);
......
...@@ -884,7 +884,6 @@ static int load_elf_library(int fd) ...@@ -884,7 +884,6 @@ static int load_elf_library(int fd)
*/ */
static int dump_write(struct file *file, const void *addr, int nr) static int dump_write(struct file *file, const void *addr, int nr)
{ {
file->f_inode->i_status |= ST_MODIFIED;
return file->f_op->write(file->f_inode, file, addr, nr) == nr; return file->f_op->write(file->f_inode, file, addr, nr) == nr;
} }
......
...@@ -241,7 +241,6 @@ static void write_dquot(struct dquot *dquot) ...@@ -241,7 +241,6 @@ static void write_dquot(struct dquot *dquot)
if (filp->f_op->write(filp->f_inode, filp, if (filp->f_op->write(filp->f_inode, filp,
(char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk)) (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
dquot->dq_flags &= ~DQ_MOD; dquot->dq_flags &= ~DQ_MOD;
/* inode->i_status |= ST_MODIFIED is willingly *not* done here */
up(&dquot->dq_mnt->mnt_sem); up(&dquot->dq_mnt->mnt_sem);
set_fs(fs); set_fs(fs);
......
...@@ -212,9 +212,6 @@ static int ext2_readdir (struct inode * inode, struct file * filp, ...@@ -212,9 +212,6 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
offset = 0; offset = 0;
brelse (bh); brelse (bh);
} }
if (DO_UPDATE_ATIME(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
return 0; return 0;
} }
...@@ -122,7 +122,7 @@ static inline void remove_suid(struct inode *inode) ...@@ -122,7 +122,7 @@ static inline void remove_suid(struct inode *inode)
mode &= inode->i_mode; mode &= inode->i_mode;
if (mode && !suser()) { if (mode && !suser()) {
inode->i_mode &= ~mode; inode->i_mode &= ~mode;
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
} }
...@@ -251,7 +251,7 @@ static long ext2_file_write (struct inode * inode, struct file * filp, ...@@ -251,7 +251,7 @@ static long ext2_file_write (struct inode * inode, struct file * filp,
inode->u.ext2_i.i_osync--; inode->u.ext2_i.i_osync--;
inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_ctime = inode->i_mtime = CURRENT_TIME;
filp->f_pos = pos; filp->f_pos = pos;
inode->i_dirt = 1; mark_inode_dirty(inode);
return written; return written;
} }
......
...@@ -216,7 +216,7 @@ void ext2_free_inode (struct inode * inode) ...@@ -216,7 +216,7 @@ void ext2_free_inode (struct inode * inode)
es->s_free_inodes_count = es->s_free_inodes_count =
cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
inode->i_dirt = 0; mark_inode_dirty(inode);
} }
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
if (sb->s_flags & MS_SYNCHRONOUS) { if (sb->s_flags & MS_SYNCHRONOUS) {
...@@ -240,7 +240,7 @@ static void inc_inode_version (struct inode * inode, ...@@ -240,7 +240,7 @@ static void inc_inode_version (struct inode * inode,
int mode) int mode)
{ {
inode->u.ext2_i.i_version++; inode->u.ext2_i.i_version++;
inode->i_dirt = 1; mark_inode_dirty(inode);
return; return;
} }
...@@ -416,7 +416,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err) ...@@ -416,7 +416,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
mode |= S_ISGID; mode |= S_ISGID;
} else } else
inode->i_gid = current->fsgid; inode->i_gid = current->fsgid;
inode->i_dirt = 1; mark_inode_dirty(inode);
inode->i_ino = j; inode->i_ino = j;
inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = 0; inode->i_blocks = 0;
......
...@@ -38,7 +38,7 @@ void ext2_put_inode (struct inode * inode) ...@@ -38,7 +38,7 @@ void ext2_put_inode (struct inode * inode)
inode->i_ino == EXT2_ACL_DATA_INO) inode->i_ino == EXT2_ACL_DATA_INO)
return; return;
inode->u.ext2_i.i_dtime = CURRENT_TIME; inode->u.ext2_i.i_dtime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_update_inode(inode, IS_SYNC(inode)); ext2_update_inode(inode, IS_SYNC(inode));
inode->i_size = 0; inode->i_size = 0;
if (inode->i_blocks) if (inode->i_blocks)
...@@ -248,7 +248,7 @@ static struct buffer_head * inode_getblk (struct inode * inode, int nr, ...@@ -248,7 +248,7 @@ static struct buffer_head * inode_getblk (struct inode * inode, int nr,
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)
ext2_sync_inode (inode); ext2_sync_inode (inode);
else else
inode->i_dirt = 1; mark_inode_dirty(inode);
return result; return result;
} }
...@@ -322,7 +322,7 @@ static struct buffer_head * block_getblk (struct inode * inode, ...@@ -322,7 +322,7 @@ static struct buffer_head * block_getblk (struct inode * inode,
} }
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocks; inode->i_blocks += blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
inode->u.ext2_i.i_next_alloc_block = new_block; inode->u.ext2_i.i_next_alloc_block = new_block;
inode->u.ext2_i.i_next_alloc_goal = tmp; inode->u.ext2_i.i_next_alloc_goal = tmp;
brelse (bh); brelse (bh);
...@@ -591,7 +591,6 @@ static int ext2_update_inode(struct inode * inode, int do_sync) ...@@ -591,7 +591,6 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
else for (block = 0; block < EXT2_N_BLOCKS; block++) else for (block = 0; block < EXT2_N_BLOCKS; block++)
raw_inode->i_block[block] = cpu_to_le32(inode->u.ext2_i.i_data[block]); raw_inode->i_block[block] = cpu_to_le32(inode->u.ext2_i.i_data[block]);
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
inode->i_dirt = 0;
if (do_sync) { if (do_sync) {
ll_rw_block (WRITE, 1, &bh); ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh); wait_on_buffer (bh);
...@@ -671,7 +670,7 @@ int ext2_notify_change(struct inode *inode, struct iattr *iattr) ...@@ -671,7 +670,7 @@ int ext2_notify_change(struct inode *inode, struct iattr *iattr)
inode->i_flags &= ~S_IMMUTABLE; inode->i_flags &= ~S_IMMUTABLE;
inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL; inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
} }
inode->i_dirt = 1; mark_inode_dirty(inode);
return 0; return 0;
} }
......
...@@ -62,7 +62,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -62,7 +62,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
else else
inode->i_flags &= ~MS_NOATIME; inode->i_flags &= ~MS_NOATIME;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
return 0; return 0;
case EXT2_IOC_GETVERSION: case EXT2_IOC_GETVERSION:
return put_user(inode->u.ext2_i.i_version, (int *) arg); return put_user(inode->u.ext2_i.i_version, (int *) arg);
...@@ -74,7 +74,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -74,7 +74,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (get_user(inode->u.ext2_i.i_version, (int *) arg)) if (get_user(inode->u.ext2_i.i_version, (int *) arg))
return -EFAULT; return -EFAULT;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
return 0; return 0;
default: default:
return -ENOTTY; return -ENOTTY;
......
...@@ -252,7 +252,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, ...@@ -252,7 +252,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
de->inode = le32_to_cpu(0); de->inode = le32_to_cpu(0);
de->rec_len = le16_to_cpu(sb->s_blocksize); de->rec_len = le16_to_cpu(sb->s_blocksize);
dir->i_size = offset + sb->s_blocksize; dir->i_size = offset + sb->s_blocksize;
dir->i_dirt = 1; mark_inode_dirty(dir);
} else { } else {
ext2_debug ("skipping to next block\n"); ext2_debug ("skipping to next block\n");
...@@ -297,7 +297,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, ...@@ -297,7 +297,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
* and/or different from the directory change time. * and/or different from the directory change time.
*/ */
dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_dirt = 1; mark_inode_dirty(dir);
dir->i_version = ++event; dir->i_version = ++event;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
*res_dir = de; *res_dir = de;
...@@ -366,11 +366,11 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode) ...@@ -366,11 +366,11 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
inode->i_op = &ext2_file_inode_operations; inode->i_op = &ext2_file_inode_operations;
inode->i_mode = mode; inode->i_mode = mode;
inode->i_dirt = 1; mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh) { if (!bh) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput (inode); iput (inode);
return err; return err;
} }
...@@ -423,11 +423,11 @@ int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) ...@@ -423,11 +423,11 @@ int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
init_fifo(inode); init_fifo(inode);
if (S_ISBLK(mode) || S_ISCHR(mode)) if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = to_kdev_t(rdev); inode->i_rdev = to_kdev_t(rdev);
inode->i_dirt = 1; mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh) { if (!bh) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput(inode); iput(inode);
return err; return err;
} }
...@@ -465,7 +465,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -465,7 +465,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
dir_block = ext2_bread (inode, 0, 1, &err); dir_block = ext2_bread (inode, 0, 1, &err);
if (!dir_block) { if (!dir_block) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput (inode); iput (inode);
return err; return err;
} }
...@@ -486,11 +486,11 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -486,11 +486,11 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask); inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
if (dir->i_mode & S_ISGID) if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID; inode->i_mode |= S_ISGID;
inode->i_dirt = 1; mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh) { if (!bh) {
inode->i_nlink = 0; inode->i_nlink = 0;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput (inode); iput (inode);
return err; return err;
} }
...@@ -502,7 +502,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -502,7 +502,7 @@ int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
wait_on_buffer (bh); wait_on_buffer (bh);
} }
dir->i_nlink++; dir->i_nlink++;
dir->i_dirt = 1; mark_inode_dirty(dir);
d_instantiate(dentry, inode, D_DIR); d_instantiate(dentry, inode, D_DIR);
brelse (bh); brelse (bh);
return 0; return 0;
...@@ -640,10 +640,10 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -640,10 +640,10 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
inode->i_nlink); inode->i_nlink);
inode->i_version = ++event; inode->i_version = ++event;
inode->i_nlink = 0; inode->i_nlink = 0;
inode->i_dirt = 1; mark_inode_dirty(inode);
dir->i_nlink--; dir->i_nlink--;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1; mark_inode_dirty(dir);
d_delete(dentry); d_delete(dentry);
end_rmdir: end_rmdir:
...@@ -701,9 +701,9 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry) ...@@ -701,9 +701,9 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
wait_on_buffer (bh); wait_on_buffer (bh);
} }
dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1; mark_inode_dirty(dir);
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
retval = 0; retval = 0;
d_delete(dentry); /* This also frees the inode */ d_delete(dentry); /* This also frees the inode */
...@@ -738,7 +738,7 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam ...@@ -738,7 +738,7 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
name_block = ext2_bread (inode, 0, 1, &err); name_block = ext2_bread (inode, 0, 1, &err);
if (!name_block) { if (!name_block) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput (inode); iput (inode);
return err; return err;
} }
...@@ -758,12 +758,12 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam ...@@ -758,12 +758,12 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
brelse (name_block); brelse (name_block);
} }
inode->i_size = i; inode->i_size = i;
inode->i_dirt = 1; mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh) { if (!bh) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; mark_inode_dirty(inode);
iput (inode); iput (inode);
return err; return err;
} }
...@@ -808,7 +808,7 @@ int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry) ...@@ -808,7 +808,7 @@ int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry)
brelse (bh); brelse (bh);
inode->i_nlink++; inode->i_nlink++;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
d_instantiate(dentry, inode, 0); d_instantiate(dentry, inode, 0);
return 0; return 0;
...@@ -953,21 +953,21 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry, ...@@ -953,21 +953,21 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
if (new_inode) { if (new_inode) {
new_inode->i_nlink--; new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME; new_inode->i_ctime = CURRENT_TIME;
new_inode->i_dirt = 1; mark_inode_dirty(new_inode);
} }
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
old_dir->i_dirt = 1; mark_inode_dirty(old_dir);
if (dir_bh) { if (dir_bh) {
PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
mark_buffer_dirty(dir_bh, 1); mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--; old_dir->i_nlink--;
old_dir->i_dirt = 1; mark_inode_dirty(old_dir);
if (new_inode) { if (new_inode) {
new_inode->i_nlink--; new_inode->i_nlink--;
new_inode->i_dirt = 1; mark_inode_dirty(new_inode);
} else { } else {
new_dir->i_nlink++; new_dir->i_nlink++;
new_dir->i_dirt = 1; mark_inode_dirty(new_dir);
} }
} }
mark_buffer_dirty(old_bh, 1); mark_buffer_dirty(old_bh, 1);
......
...@@ -65,10 +65,7 @@ static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *bas ...@@ -65,10 +65,7 @@ static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *bas
} }
link = bh->b_data; link = bh->b_data;
} }
if (!IS_RDONLY(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
base = lookup_dentry(link, base, 1); base = lookup_dentry(link, base, 1);
if (bh) if (bh)
brelse(bh); brelse(bh);
...@@ -101,10 +98,7 @@ static int ext2_readlink (struct inode * inode, char * buffer, int buflen) ...@@ -101,10 +98,7 @@ static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
i++; i++;
if (copy_to_user(buffer, link, i)) if (copy_to_user(buffer, link, i))
i = -EFAULT; i = -EFAULT;
if (DO_UPDATE_ATIME(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
if (bh) if (bh)
brelse (bh); brelse (bh);
return i; return i;
......
...@@ -91,7 +91,7 @@ static int trunc_direct (struct inode * inode) ...@@ -91,7 +91,7 @@ static int trunc_direct (struct inode * inode)
} }
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
bforget(bh); bforget(bh);
if (free_count == 0) { if (free_count == 0) {
block_to_free = tmp; block_to_free = tmp;
...@@ -172,7 +172,7 @@ static int trunc_indirect (struct inode * inode, int offset, u32 * p) ...@@ -172,7 +172,7 @@ static int trunc_indirect (struct inode * inode, int offset, u32 * p)
} }
/* ext2_free_blocks (inode, tmp, 1); */ /* ext2_free_blocks (inode, tmp, 1); */
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
if (free_count > 0) if (free_count > 0)
ext2_free_blocks (inode, block_to_free, free_count); ext2_free_blocks (inode, block_to_free, free_count);
...@@ -187,7 +187,7 @@ static int trunc_indirect (struct inode * inode, int offset, u32 * p) ...@@ -187,7 +187,7 @@ static int trunc_indirect (struct inode * inode, int offset, u32 * p)
tmp = *p; tmp = *p;
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_free_blocks (inode, tmp, 1); ext2_free_blocks (inode, tmp, 1);
} }
if (IS_SYNC(inode) && buffer_dirty(ind_bh)) { if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
...@@ -259,7 +259,7 @@ static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p) ...@@ -259,7 +259,7 @@ static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p)
} }
/* ext2_free_blocks (inode, tmp, 1); */ /* ext2_free_blocks (inode, tmp, 1); */
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
if (free_count > 0) if (free_count > 0)
ext2_free_blocks (inode, block_to_free, free_count); ext2_free_blocks (inode, block_to_free, free_count);
...@@ -274,7 +274,7 @@ static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p) ...@@ -274,7 +274,7 @@ static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p)
tmp = le32_to_cpu(*p); tmp = le32_to_cpu(*p);
*p = cpu_to_le32(0); *p = cpu_to_le32(0);
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_free_blocks (inode, tmp, 1); ext2_free_blocks (inode, tmp, 1);
} }
if (IS_SYNC(inode) && buffer_dirty(ind_bh)) { if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
...@@ -334,7 +334,7 @@ static int trunc_dindirect (struct inode * inode, int offset, ...@@ -334,7 +334,7 @@ static int trunc_dindirect (struct inode * inode, int offset,
tmp = *p; tmp = *p;
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_free_blocks (inode, tmp, 1); ext2_free_blocks (inode, tmp, 1);
} }
if (IS_SYNC(inode) && buffer_dirty(dind_bh)) { if (IS_SYNC(inode) && buffer_dirty(dind_bh)) {
...@@ -393,7 +393,7 @@ static int trunc_dindirect_swab32 (struct inode * inode, int offset, ...@@ -393,7 +393,7 @@ static int trunc_dindirect_swab32 (struct inode * inode, int offset,
tmp = le32_to_cpu(*p); tmp = le32_to_cpu(*p);
*p = cpu_to_le32(0); *p = cpu_to_le32(0);
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_free_blocks (inode, tmp, 1); ext2_free_blocks (inode, tmp, 1);
} }
if (IS_SYNC(inode) && buffer_dirty(dind_bh)) { if (IS_SYNC(inode) && buffer_dirty(dind_bh)) {
...@@ -452,7 +452,7 @@ static int trunc_tindirect (struct inode * inode) ...@@ -452,7 +452,7 @@ static int trunc_tindirect (struct inode * inode)
tmp = *p; tmp = *p;
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; mark_inode_dirty(inode);
ext2_free_blocks (inode, tmp, 1); ext2_free_blocks (inode, tmp, 1);
} }
if (IS_SYNC(inode) && buffer_dirty(tind_bh)) { if (IS_SYNC(inode) && buffer_dirty(tind_bh)) {
...@@ -486,7 +486,7 @@ void ext2_truncate (struct inode * inode) ...@@ -486,7 +486,7 @@ void ext2_truncate (struct inode * inode)
retry |= trunc_tindirect (inode); retry |= trunc_tindirect (inode);
if (!retry) if (!retry)
break; break;
if (IS_SYNC(inode) && inode->i_dirt) if (IS_SYNC(inode) && test_bit(I_DIRTY, &inode->i_state))
ext2_sync_inode (inode); ext2_sync_inode (inode);
current->counter = 0; current->counter = 0;
schedule (); schedule ();
...@@ -510,5 +510,5 @@ void ext2_truncate (struct inode * inode) ...@@ -510,5 +510,5 @@ void ext2_truncate (struct inode * inode)
} }
} }
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
} }
/* /*
* fs/inode.c * linux/fs/inode.c
* *
* Complete reimplementation * (C) 1997 Linus Torvalds
* (C) 1997 Thomas Schoebel-Theuer
*/ */
/* Everything here is intended to be MP-safe. However, other parts
* of the kernel are not yet MP-safe, in particular the inode->i_count++
* that are spread over everywhere. These should be replaced by
* iinc() as soon as possible. Since I have no MP machine, I could
* not test it.
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/dlists.h>
#include <linux/dalloc.h> #include <linux/dalloc.h>
#include <linux/omirr.h> #include <linux/list.h>
/* #define DEBUG */ /*
* New inode.c implementation.
#define HASH_SIZE 1024 /* must be a power of 2 */ *
#define NR_LEVELS 4 * This implementation has the basic premise of trying
* to be extremely low-overhead and SMP-safe, yet be
#define ST_AGED 1 * simple enough to be "obviously correct".
#define ST_HASHED 2 *
#define ST_EMPTY 4 * Famous last words.
#define ST_TO_READ 8 */
#define ST_TO_WRITE 16
#define ST_TO_PUT 32 /*
#define ST_TO_DROP 64 * Inode lookup is no longer as critical as it used to be:
#define ST_IO (ST_TO_READ|ST_TO_WRITE|ST_TO_PUT|ST_TO_DROP) * most of the lookups are going to be through the dcache.
#define ST_WAITING 128 */
#define ST_FREEING 256 #define HASH_BITS 8
#define ST_IBASKET 512 #define HASH_SIZE (1UL << HASH_BITS)
#define HASH_MASK (HASH_SIZE-1)
/* The idea is to keep empty inodes in a separate list, so no search
* is required as long as empty inodes exit. /*
* All reusable inodes occurring in the hash table with i_count==0 * Each inode can be on two separate lists. One is
* are also registered in the ringlist aged_i[level], but in LRU order. * the hash list of the inode, used for lookups. The
* Used inodes with i_count>0 are kept solely in the hashtable and in * other linked list is the "type" list:
* all_i, but in no other list. * "in_use" - valid inode, hashed
* The level is used for multilevel aging to avoid thrashing; each * "dirty" - valid inode, hashed, dirty.
* time i_count decreases to 0, the inode is inserted into the next level * "unused" - ready to be re-used. Not hashed.
* ringlist. Cache reusage is simply by taking the _last_ element from the *
* lowest-level ringlist that contains inodes. * The two first versions also have a dirty list, allowing
* In contrast to the old code, there isn't any O(n) search overhead now * for low-overhead inode sync() operations.
* in iget/iput (if you make HASH_SIZE large enough). */
LIST_HEAD(inode_in_use);
LIST_HEAD(inode_dirty);
LIST_HEAD(inode_unused);
struct list_head inode_hashtable[HASH_SIZE];
/*
* A simple spinlock to protect the list manipulations
*/
spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
/*
* Statistics gathering.. Not actually done yet.
*/ */
static struct inode * hashtable[HASH_SIZE];/* linked with i_hash_{next,prev} */
static struct inode * all_i = NULL; /* linked with i_{next,prev} */
static struct inode * empty_i = NULL; /* linked with i_{next,prev} */
static struct inode * aged_i[NR_LEVELS+1]; /* linked with i_lru_{next,prev} */
static int aged_reused[NR_LEVELS+1]; /* # removals from aged_i[level] */
static int age_table[NR_LEVELS+1] = { /* You may tune this. */
1, 4, 10, 100, 1000
}; /* after which # of uses to increase to the next level */
/* This is for kernel/sysctl.c */
/* Just aligning plain ints and arrays thereof doesn't work reliably.. */
struct { struct {
int nr_inodes; int nr_inodes;
int nr_free_inodes; int nr_free_inodes;
int aged_count[NR_LEVELS+1]; /* # in each level */ int dummy[10];
} inodes_stat; } inodes_stat;
int max_inodes = NR_INODE; int max_inodes = NR_INODE;
unsigned long last_inode = 0;
void inode_init(void) void __mark_inode_dirty(struct inode *inode)
{ {
memset(hashtable, 0, sizeof(hashtable)); spin_lock(&inode_lock);
memset(aged_i, 0, sizeof(aged_i)); list_del(&inode->i_list);
memset(aged_reused, 0, sizeof(aged_reused)); list_add(&inode->i_list, &inode_dirty);
memset(&inodes_stat, 0, sizeof(inodes_stat)); spin_unlock(&inode_lock);
} }
/* Intended for short locks of the above global data structures. static inline void unlock_inode(struct inode *inode)
* Could be replaced with spinlocks completely, since there is {
* no blocking during manipulation of the static data; however the clear_bit(I_LOCK, &inode->i_state);
* lock in invalidate_inodes() may last relatively long. wake_up(&inode->i_wait);
*/ }
#ifdef __SMP__
struct semaphore vfs_sem = MUTEX;
#endif
DEF_INSERT(all,struct inode,i_next,i_prev)
DEF_REMOVE(all,struct inode,i_next,i_prev)
DEF_INSERT(lru,struct inode,i_lru_next,i_lru_prev)
DEF_REMOVE(lru,struct inode,i_lru_next,i_lru_prev)
DEF_INSERT(hash,struct inode,i_hash_next,i_hash_prev) static void __wait_on_inode(struct inode * inode)
DEF_REMOVE(hash,struct inode,i_hash_next,i_hash_prev) {
struct wait_queue wait = { current, NULL };
DEF_INSERT(ibasket,struct inode,i_basket_next,i_basket_prev) add_wait_queue(&inode->i_wait, &wait);
DEF_REMOVE(ibasket,struct inode,i_basket_next,i_basket_prev) repeat:
current->state = TASK_UNINTERRUPTIBLE;
if (test_bit(I_LOCK, &inode->i_state)) {
schedule();
goto repeat;
}
remove_wait_queue(&inode->i_wait, &wait);
current->state = TASK_RUNNING;
}
#ifdef DEBUG static inline void wait_on_inode(struct inode *inode)
extern void printpath(struct dentry * entry); {
struct inode * xtst[15000]; if (test_bit(I_LOCK, &inode->i_state))
int xcnt = 0; __wait_on_inode(inode);
}
void xcheck(char * txt, struct inode * p) /*
* These are initializations that only need to be done
* once, because the fields are idempotent across use
* of the inode..
*/
static inline void init_once(struct inode * inode)
{ {
int i; memset(inode, 0, sizeof(*inode));
for(i=xcnt-1; i>=0; i--) init_waitqueue(&inode->i_wait);
if (xtst[i] == p) sema_init(&inode->i_sem, 1);
return;
printk("Bogus inode %p in %s\n", p, txt);
} }
#else
#define xcheck(t,p) /*nothing*/
#endif
static inline struct inode * grow_inodes(void)
/*
* Look out! This returns with the inode lock held if
* it got an inode..
*/
static struct inode * grow_inodes(void)
{ {
struct inode * res; struct inode * inode = (struct inode *)__get_free_page(GFP_KERNEL);
struct inode * inode = res = (struct inode*)__get_free_page(GFP_KERNEL);
int size = PAGE_SIZE;
if (!inode)
return NULL;
if (inode) {
int size;
struct inode * tmp;
spin_lock(&inode_lock);
size = PAGE_SIZE - 2*sizeof(struct inode);
tmp = inode;
do {
tmp++;
init_once(tmp);
list_add(&tmp->i_list, &inode_unused);
size -= sizeof(struct inode); size -= sizeof(struct inode);
inode++; } while (size >= 0);
inodes_stat.nr_inodes++; init_once(inode);
#ifdef DEBUG
xtst[xcnt++]=res;
#endif
while(size >= sizeof(struct inode)) {
#ifdef DEBUG
xtst[xcnt++]=inode;
#endif
inodes_stat.nr_inodes++;
inodes_stat.nr_free_inodes++;
insert_all(&empty_i, inode);
inode->i_status = ST_EMPTY;
inode++;
size -= sizeof(struct inode);
} }
return res; return inode;
} }
static inline int hash(dev_t i_dev, unsigned long i_ino) static inline void write_inode(struct inode *inode)
{ {
return ((int)i_ino ^ ((int)i_dev << 6)) & (HASH_SIZE-1); if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode)
inode->i_sb->s_op->write_inode(inode);
} }
static inline blocking void wait_io(struct inode * inode, unsigned short flags) static inline void sync_list(struct list_head *head, struct list_head *clean)
{ {
while(inode->i_status & flags) { struct list_head * tmp;
struct wait_queue wait = {current, NULL};
inode->i_status |= ST_WAITING; while ((tmp = head->prev) != head) {
vfs_unlock(); struct inode *inode = list_entry(tmp, struct inode, i_list);
add_wait_queue(&inode->i_wait, &wait); list_del(tmp);
sleep_on(&inode->i_wait);
remove_wait_queue(&inode->i_wait, &wait); /*
vfs_lock(); * If the inode is locked, it's already being written out.
* We have to wait for it, though.
*/
if (test_bit(I_LOCK, &inode->i_state)) {
list_add(tmp, head);
spin_unlock(&inode_lock);
__wait_on_inode(inode);
} else {
list_add(tmp, clean);
clear_bit(I_DIRTY, &inode->i_state);
set_bit(I_LOCK, &inode->i_state);
spin_unlock(&inode_lock);
write_inode(inode);
unlock_inode(inode);
}
spin_lock(&inode_lock);
} }
} }
static inline blocking void set_io(struct inode * inode, /*
unsigned short waitflags, * "sync_inodes()" goes through the dirty list
unsigned short setflags) * and writes them out and puts them back on
* the normal list.
*/
void sync_inodes(kdev_t dev)
{ {
wait_io(inode, waitflags); spin_lock(&inode_lock);
inode->i_status |= setflags; sync_list(&inode_dirty, &inode_in_use);
vfs_unlock(); spin_unlock(&inode_lock);
} }
static inline blocking int release_io(struct inode * inode, unsigned short flags) /*
* This is called by the filesystem to tell us
* that the inode is no longer useful. We just
* terminate it with extreme predjudice.
*/
void clear_inode(struct inode *inode)
{ {
int res = 0; truncate_inode_pages(inode, 0);
vfs_lock(); wait_on_inode(inode);
inode->i_status &= ~flags; if (IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op)
if (inode->i_status & ST_WAITING) { inode->i_sb->dq_op->drop(inode);
inode->i_status &= ~ST_WAITING;
vfs_unlock(); spin_lock(&inode_lock);
wake_up(&inode->i_wait); inode->i_state = 0;
res = 1; list_del(&inode->i_hash);
} list_del(&inode->i_list);
return res; list_add(&inode->i_list, &inode_unused);
spin_unlock(&inode_lock);
} }
static inline blocking void _io(void (*op)(struct inode*), struct inode * inode, #define CAN_UNUSE(inode) \
unsigned short waitflags, unsigned short setflags) ((atomic_read(&(inode)->i_count) == 0) && \
{ ((inode)->i_nrpages == 0) && \
/* Do nothing if the same op is already in progress. */ (!test_bit(I_LOCK, &(inode)->i_state)))
if (op && !(inode->i_status & setflags)) {
set_io(inode, waitflags, setflags);
op(inode);
if (release_io(inode, setflags)) {
/* Somebody grabbed my inode from under me. */
#ifdef DEBUG
printk("_io grab!\n");
#endif
vfs_lock();
}
}
}
blocking void _clear_inode(struct inode * inode, int external, int verbose) static void invalidate_list(struct list_head *head, kdev_t dev)
{ {
xcheck("_clear_inode",inode); struct list_head *next;
if (inode->i_status & ST_IBASKET) {
struct super_block * sb = inode->i_sb; next = head->next;
remove_ibasket(&sb->s_ibasket, inode); for (;;) {
sb->s_ibasket_count--; struct list_head * tmp = next;
inode->i_status &= ~ST_IBASKET; struct inode * inode;
#if 0
printpath(inode->i_dentry); next = next->next;
printk(" put_inode\n"); if (tmp == head)
#endif break;
_io(sb->s_op->put_inode, inode, ST_TO_PUT|ST_TO_WRITE, ST_TO_PUT); inode = list_entry(tmp, struct inode, i_list);
if (inode->i_status & ST_EMPTY) if (inode->i_dev != dev)
return; continue;
} if (!CAN_UNUSE(inode))
if (inode->i_status & ST_HASHED) continue;
remove_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode); list_del(&inode->i_hash);
if (inode->i_status & ST_AGED) { list_del(&inode->i_list);
/* "cannot happen" when called from an fs because at least list_add(&inode->i_list, &inode_unused);
* the caller must use it. Can happen when called from
* invalidate_inodes(). */
if (verbose)
printk("VFS: clearing aged inode\n");
if (atomic_read(&inode->i_count))
printk("VFS: aged inode is in use\n");
remove_lru(&aged_i[inode->i_level], inode);
inodes_stat.aged_count[inode->i_level]--;
}
if (!external && inode->i_status & ST_IO) {
printk("VFS: clearing inode during IO operation\n");
}
if (!(inode->i_status & ST_EMPTY)) {
remove_all(&all_i, inode);
inode->i_status = ST_EMPTY;
if (inode->i_pages) {
vfs_unlock(); /* may block, can that be revised? */
truncate_inode_pages(inode, 0);
vfs_lock();
} }
insert_all(&empty_i, inode);
inodes_stat.nr_free_inodes++;
} else if(external)
printk("VFS: empty inode is unnecessarily cleared multiple "
"times by an fs\n");
else
printk("VFS: clearing empty inode\n");
inode->i_status = ST_EMPTY;
/* The inode is not really cleared any more here, but only once
* when taken from empty_i. This saves instructions and processor
* cache pollution.
*/
} }
void insert_inode_hash(struct inode * inode) void invalidate_inodes(kdev_t dev)
{ {
xcheck("insert_inode_hash",inode); spin_lock(&inode_lock);
vfs_lock(); invalidate_list(&inode_in_use, dev);
if (!(inode->i_status & ST_HASHED)) { invalidate_list(&inode_dirty, dev);
insert_hash(&hashtable[hash(inode->i_dev, inode->i_ino)], inode); spin_unlock(&inode_lock);
inode->i_status |= ST_HASHED;
} else
printk("VFS: trying to hash an inode again\n");
vfs_unlock();
} }
blocking struct inode * _get_empty_inode(void) /*
* This is called with the inode lock held. It just looks at the last
* inode on the in-use list, and if the inode is trivially freeable
* we just move it to the unused list.
*
* Otherwise we just move the inode to be the first inode and expect to
* get back to the problem later..
*/
static void try_to_free_inodes(void)
{ {
struct list_head * tmp;
struct list_head *head = &inode_in_use;
tmp = head->prev;
if (tmp != head) {
struct inode * inode; struct inode * inode;
int retry = 0;
retry: list_del(tmp);
inode = empty_i; inode = list_entry(tmp, struct inode, i_list);
if (inode) { if (CAN_UNUSE(inode)) {
remove_all(&empty_i, inode); list_del(&inode->i_hash);
inodes_stat.nr_free_inodes--; head = &inode_unused;
} else if(inodes_stat.nr_inodes < max_inodes || retry > 2) {
inode = grow_inodes();
}
if (!inode) {
int level;
int usable = 0;
for(level = 0; level <= NR_LEVELS; level++)
if (aged_i[level]) {
inode = aged_i[level]->i_lru_prev;
/* Here is the picking strategy, tune this */
if (aged_reused[level] < (usable++ ?
inodes_stat.aged_count[level] :
2))
break;
aged_reused[level] = 0;
}
if (inode) {
if (!(inode->i_status & ST_AGED))
printk("VFS: inode aging inconsistency\n");
if (atomic_read(&inode->i_count))
printk("VFS: i_count of aged inode is not zero\n");
if (inode->i_dirt)
printk("VFS: Hey, somebody made my aged inode dirty\n");
_clear_inode(inode, 0, 0);
goto retry;
} }
list_add(tmp, head);
} }
if (!inode) {
vfs_unlock();
schedule();
if (retry > 10)
panic("VFS: cannot repair inode shortage");
if (retry > 2)
printk("VFS: no free inodes\n");
retry++;
vfs_lock();
goto retry;
}
xcheck("get_empty_inode",inode);
memset(inode, 0, sizeof(struct inode));
atomic_set(&inode->i_count, 1);
inode->i_nlink = 1;
sema_init(&inode->i_sem, 1);
inode->i_ino = ++last_inode;
inode->i_version = ++event;
insert_all(&all_i, inode);
return inode;
} }
static inline blocking struct inode * _get_empty_inode_hashed(dev_t i_dev,
unsigned long i_ino) static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head)
{ {
struct inode ** base = &hashtable[hash(i_dev, i_ino)]; struct list_head *tmp;
struct inode * inode = *base; struct inode * inode;
if (inode) do {
if (inode->i_ino == i_ino && inode->i_dev == i_dev) { tmp = head;
for (;;) {
tmp = tmp->next;
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
if (inode->i_sb != sb)
continue;
if (inode->i_ino != ino)
continue;
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
printk("VFS: inode %lx is already in use\n", i_ino); break;
return inode;
} }
inode = inode->i_hash_next;
} while(inode != *base);
inode = _get_empty_inode();
inode->i_dev = i_dev;
inode->i_ino = i_ino;
insert_hash(base, inode);
inode->i_status |= ST_HASHED;
return inode; return inode;
} }
blocking struct inode * get_empty_inode_hashed(dev_t i_dev, unsigned long i_ino) /*
* This just initializes the inode fields
* to known values before returning the inode..
*
* i_sb, i_ino, i_count, i_state and the lists have
* been initialized elsewhere..
*/
void clean_inode(struct inode *inode)
{ {
struct inode * inode; memset(&inode->u, 0, sizeof(inode->u));
inode->i_pipe = 0;
vfs_lock(); inode->i_sock = 0;
inode = _get_empty_inode_hashed(i_dev, i_ino); inode->i_op = NULL;
vfs_unlock(); inode->i_nlink = 1;
return inode; memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
sema_init(&inode->i_sem, 1);
} }
void _get_inode(struct inode * inode) /*
* This gets called with I_LOCK held: it needs
* to read the inode and then unlock it
*/
static inline void read_inode(struct inode *inode, struct super_block *sb)
{ {
if (inode->i_status & ST_IBASKET) { sb->s_op->read_inode(inode);
inode->i_status &= ~ST_IBASKET; unlock_inode(inode);
remove_ibasket(&inode->i_sb->s_ibasket, inode);
inode->i_sb->s_ibasket_count--;
}
if (inode->i_status & ST_AGED) {
inode->i_status &= ~ST_AGED;
remove_lru(&aged_i[inode->i_level], inode);
inodes_stat.aged_count[inode->i_level]--;
aged_reused[inode->i_level]++;
if (S_ISDIR(inode->i_mode))
/* make dirs less thrashable */
inode->i_level = NR_LEVELS-1;
else if(inode->i_nlink > 1)
/* keep hardlinks totally separate */
inode->i_level = NR_LEVELS;
else if(++inode->i_reuse_count >= age_table[inode->i_level]
&& inode->i_level < NR_LEVELS-1)
inode->i_level++;
if (atomic_read(&inode->i_count) != 1)
printk("VFS: inode count was not zero (%d after ++)\n", atomic_read(&inode->i_count));
} else if(inode->i_status & ST_EMPTY)
printk("VFS: invalid reuse of empty inode\n");
} }
blocking struct inode * iget(struct super_block * sb, unsigned long i_ino) struct inode * get_empty_inode(void)
{ {
struct inode ** base; static unsigned long last_ino = 0;
struct inode * inode; struct inode * inode;
dev_t i_dev; struct list_head * tmp = inode_unused.next;
if (!sb) if (tmp != &inode_unused) {
panic("VFS: iget with sb == NULL"); list_del(tmp);
i_dev = sb->s_dev; inode = list_entry(tmp, struct inode, i_list);
if (!i_dev) add_new_inode:
panic("VFS: sb->s_dev is NULL\n"); INIT_LIST_HEAD(&inode->i_list);
base = &hashtable[hash(i_dev, i_ino)]; INIT_LIST_HEAD(&inode->i_hash);
vfs_lock(); inode->i_sb = NULL;
inode = *base; inode->i_ino = ++last_ino;
if (inode) do { atomic_set(&inode->i_count, 1);
if (inode->i_ino == i_ino && inode->i_dev == i_dev) { inode->i_state = 0;
atomic_inc(&inode->i_count); clean_inode(inode);
_get_inode(inode); return inode;
/* Allow concurrent writes/puts. This is in particular
* useful e.g. when syncing large chunks.
* I hope the i_dirty flag is everywhere set as soon
* as _any_ modifcation is made and _before_
* giving up control, so no harm should occur if data
* is modified during writes, because it will be
* rewritten again (does a short inconsistency on the
* disk harm?)
*/
wait_io(inode, ST_TO_READ);
vfs_unlock();
goto done;
} }
inode = inode->i_hash_next;
} while(inode != *base); /*
inode = _get_empty_inode_hashed(i_dev, i_ino); * Warning: if this succeeded, we will now
inode->i_sb = sb; * return with the inode lock, and we need to
inode->i_flags = sb->s_flags; * unlock it.
if (sb->s_op && sb->s_op->read_inode) { */
set_io(inode, 0, ST_TO_READ); /* do not wait at all */ inode = grow_inodes();
sb->s_op->read_inode(inode); if (inode) {
if (release_io(inode, ST_TO_READ)) spin_unlock(&inode_lock);
goto done; goto add_new_inode;
} }
vfs_unlock();
done:
return inode; return inode;
} }
blocking void __iput(struct inode * inode) struct inode * get_pipe_inode(void)
{ {
struct super_block * sb; extern struct inode_operations pipe_inode_operations;
xcheck("_iput",inode); struct inode *inode = get_empty_inode();
if (atomic_read(&inode->i_count) < 0)
printk("VFS: i_count is negative\n");
if (atomic_read(&inode->i_count) || (inode->i_status & ST_FREEING)) if (inode) {
return; unsigned long page = __get_free_page(GFP_USER);
inode->i_status |= ST_FREEING; if (!page) {
if (inode->i_pipe) { iput(inode);
free_page((unsigned long)PIPE_BASE(*inode)); inode = NULL;
PIPE_BASE(*inode)= NULL; } else {
} PIPE_BASE(*inode) = (char *) page;
if ((sb = inode->i_sb)) { inode->i_op = &pipe_inode_operations;
if (sb->s_op) { atomic_set(&inode->i_count, 1);
if (inode->i_nlink <= 0 && PIPE_WAIT(*inode) = NULL;
!(inode->i_status & (ST_EMPTY|ST_IBASKET))) { PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
_clear_inode(inode, 0, 1); PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
goto done; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
} PIPE_LOCK(*inode) = 0;
if (inode->i_dirt) { inode->i_pipe = 1;
inode->i_dirt = 0; inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
_io(sb->s_op->write_inode, inode, inode->i_uid = current->fsuid;
ST_TO_PUT|ST_TO_WRITE, ST_TO_WRITE); inode->i_gid = current->fsgid;
if (atomic_read(&inode->i_count)) inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
goto done; inode->i_blksize = PAGE_SIZE;
}
}
if (IS_WRITABLE(inode) && sb->dq_op) {
/* can operate in parallel to other ops ? */
_io(sb->dq_op->drop, inode, 0, ST_TO_DROP);
if (atomic_read(&inode->i_count))
goto done;
}
} }
if (inode->i_mmap)
printk("VFS: inode has mappings\n");
if (inode->i_status & ST_AGED) {
printk("VFS: reaging inode\n");
#if defined(DEBUG)
printpath(inode->i_dentry);
printk("\n");
#endif
goto done;
} }
if (!(inode->i_status & (ST_HASHED|ST_EMPTY))) { return inode;
_clear_inode(inode, 0, 1); }
goto done;
/*
* This is called with the inode lock held.. Be careful.
*/
static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head)
{
struct inode * inode;
struct list_head * tmp = inode_unused.next;
if (tmp != &inode_unused) {
list_del(tmp);
inode = list_entry(tmp, struct inode, i_list);
add_new_inode:
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
inode->i_sb = sb;
inode->i_dev = sb->s_dev;
inode->i_ino = ino;
inode->i_flags = sb->s_flags;
atomic_set(&inode->i_count, 1);
inode->i_state = 1 << I_LOCK;
spin_unlock(&inode_lock);
clean_inode(inode);
read_inode(inode, sb);
return inode;
} }
if (inode->i_status & ST_EMPTY) {
printk("VFS: aging an empty inode\n"); /*
goto done; * Uhhuh.. We need to expand. Unlock for the allocation,
* but note that "grow_inodes()" will return with the
* lock held again if the allocation succeeded.
*/
spin_unlock(&inode_lock);
inode = grow_inodes();
if (inode) {
/* We released the lock, so.. */
struct inode * old = find_inode(sb, ino, head);
if (!old)
goto add_new_inode;
list_add(&inode->i_list, &inode_unused);
spin_unlock(&inode_lock);
wait_on_inode(old);
return old;
} }
insert_lru(&aged_i[inode->i_level], inode); return inode;
inodes_stat.aged_count[inode->i_level]++;
inode->i_status |= ST_AGED;
done:
inode->i_status &= ~ST_FREEING;
} }
blocking void _iput(struct inode * inode) static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
{ {
vfs_lock(); unsigned long tmp = i_ino | (unsigned long) sb;
__iput(inode); tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
vfs_unlock(); return tmp & HASH_MASK;
} }
blocking void sync_inodes(kdev_t dev) struct inode *iget(struct super_block *sb, unsigned long ino)
{ {
struct list_head * head = inode_hashtable + hash(sb,ino);
struct inode * inode; struct inode * inode;
vfs_lock();
inode = all_i; spin_lock(&inode_lock);
if (inode) do { inode = find_inode(sb, ino, head);
xcheck("sync_inodes",inode); if (!inode) {
if (inode->i_dirt && (inode->i_dev == dev || !dev)) { try_to_free_inodes();
if (inode->i_sb && inode->i_sb->s_op && return get_new_inode(sb, ino, head);
!(inode->i_status & ST_FREEING)) {
inode->i_dirt = 0;
_io(inode->i_sb->s_op->write_inode, inode,
ST_IO, ST_TO_WRITE);
}
} }
inode = inode->i_next; spin_unlock(&inode_lock);
} while(inode != all_i); wait_on_inode(inode);
vfs_unlock(); return inode;
} }
blocking int _check_inodes(kdev_t dev, int complain) void insert_inode_hash(struct inode *inode)
{ {
struct inode * inode; struct list_head *head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
int bad = 0; list_add(&inode->i_hash, head);
}
vfs_lock();
startover: void iput(struct inode *inode)
inode = all_i; {
if (inode) do { if (inode) {
struct inode * next; if (inode->i_pipe)
xcheck("_check_inodes",inode); wake_up_interruptible(&PIPE_WAIT(*inode));
next = inode->i_next;
if (inode->i_dev == dev) {
if (inode->i_dirt || atomic_read(&inode->i_count)) {
bad++;
} else {
_clear_inode(inode, 0, 0);
/* _clear_inode() may recursively clear other /*
* inodes, probably also the next one. * Last user dropping the inode?
*/ */
if (next->i_status & ST_EMPTY) if (atomic_read(&inode->i_count) == 1) {
goto startover; void (*put)(struct inode *);
if (inode->i_sb && inode->i_sb->s_op) {
put = inode->i_sb->s_op->put_inode;
if (put)
put(inode);
}
} }
atomic_dec(&inode->i_count);
} }
inode = next;
} while(inode != all_i);
vfs_unlock();
if (complain && bad)
printk("VFS: %d inode(s) busy on removed device `%s'\n",
bad, kdevname(dev));
return (bad == 0);
} }
/*inline*/ void invalidate_inodes(kdev_t dev) int bmap(struct inode * inode, int block)
{ {
/* Requires two passes, because of the new dcache holding if (inode->i_op && inode->i_op->bmap)
* directories with i_count > 1. return inode->i_op->bmap(inode, block);
*/ return 0;
(void)_check_inodes(dev, 0);
(void)_check_inodes(dev, 1);
} }
/*inline*/ int fs_may_mount(kdev_t dev) /*
* Initialize the hash tables
*/
void inode_init(void)
{ {
return _check_inodes(dev, 0); int i;
struct list_head *head = inode_hashtable;
i = HASH_SIZE;
do {
INIT_LIST_HEAD(head);
head++;
i--;
} while (i);
} }
int fs_may_remount_ro(kdev_t dev) /*
* FIXME! These need to go through the in-use inodes to
* check whether we can mount/umount/remount.
*/
int fs_may_mount(kdev_t dev)
{ {
(void)dev; return 1;
return 1; /* not checked any more */
} }
int fs_may_umount(kdev_t dev, struct dentry * root) int fs_may_umount(kdev_t dev, struct dentry * root)
{ {
struct inode * inode;
vfs_lock();
inode = all_i;
if (inode) do {
if (inode->i_dev == dev && atomic_read(&inode->i_count))
if (inode != root->d_inode) {
vfs_unlock();
return 0; return 0;
}
inode = inode->i_next;
} while(inode != all_i);
vfs_unlock();
return 1;
}
extern struct inode_operations pipe_inode_operations;
blocking struct inode * get_pipe_inode(void)
{
struct inode * inode = get_empty_inode();
PIPE_BASE(*inode) = (char*)__get_free_page(GFP_USER);
if (!(PIPE_BASE(*inode))) {
iput(inode);
return NULL;
}
inode->i_blksize = PAGE_SIZE;
inode->i_pipe = 1;
inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
atomic_inc(&inode->i_count);
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &pipe_inode_operations;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
return inode;
} }
int bmap(struct inode * inode, int block) int fs_may_remount_ro(kdev_t dev)
{ {
if (inode->i_op && inode->i_op->bmap)
return inode->i_op->bmap(inode, block);
return 0; return 0;
} }
...@@ -54,6 +54,7 @@ struct inode_operations isofs_dir_inode_operations = ...@@ -54,6 +54,7 @@ struct inode_operations isofs_dir_inode_operations =
NULL, /* mknod */ NULL, /* mknod */
NULL, /* rename */ NULL, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
isofs_bmap, /* bmap */ isofs_bmap, /* bmap */
......
...@@ -47,6 +47,7 @@ struct inode_operations isofs_file_inode_operations = { ...@@ -47,6 +47,7 @@ struct inode_operations isofs_file_inode_operations = {
NULL, /* mknod */ NULL, /* mknod */
NULL, /* rename */ NULL, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */ generic_readpage, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
isofs_bmap, /* bmap */ isofs_bmap, /* bmap */
......
...@@ -481,12 +481,12 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, ...@@ -481,12 +481,12 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s->u.isofs_sb.s_mode = opt.mode & 0777; s->u.isofs_sb.s_mode = opt.mode & 0777;
s->s_blocksize = opt.blocksize; s->s_blocksize = opt.blocksize;
s->s_blocksize_bits = blocksize_bits; s->s_blocksize_bits = blocksize_bits;
s->s_mounted = iget(s, (isonum_733(rootp->extent) + s->s_root = d_alloc_root(iget(s, (isonum_733(rootp->extent) +
isonum_711(rootp->ext_attr_length)) isonum_711(rootp->ext_attr_length))
<< s -> u.isofs_sb.s_log_zone_size); << s -> u.isofs_sb.s_log_zone_size), NULL);
unlock_super(s); unlock_super(s);
if (!(s->s_mounted)) { if (!(s->s_root)) {
s->s_dev = 0; s->s_dev = 0;
printk("get root inode failed\n"); printk("get root inode failed\n");
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
......
...@@ -201,62 +201,60 @@ static struct buffer_head * isofs_find_entry(struct inode * dir, ...@@ -201,62 +201,60 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
return NULL; return NULL;
} }
int isofs_lookup(struct inode * dir,const char * name, int len, int isofs_lookup(struct inode * dir, struct qstr *name,
struct inode ** result) struct inode ** result)
{ {
unsigned long ino, ino_back; unsigned long ino, ino_back;
struct buffer_head * bh; struct buffer_head * bh;
char *lcname; char *lcname;
struct inode *inode;
#ifdef DEBUG #ifdef DEBUG
printk("lookup: %x %d\n",dir->i_ino, len); printk("lookup: %x %d\n",dir->i_ino, name->len);
#endif #endif
*result = NULL;
if (!dir) if (!dir)
return -ENOENT; return -ENOENT;
if (!S_ISDIR(dir->i_mode)) { if (!S_ISDIR(dir->i_mode))
iput(dir);
return -ENOENT; return -ENOENT;
}
/* If mounted with check=relaxed (and most likely norock), /* If mounted with check=relaxed (and most likely norock),
* then first convert this name to lower case. * then first convert this name to lower case.
*/ */
if (dir->i_sb->u.isofs_sb.s_name_check == 'r' && if (dir->i_sb->u.isofs_sb.s_name_check == 'r' &&
(lcname = kmalloc(len, GFP_KERNEL)) != NULL) { (lcname = kmalloc(name->len, GFP_KERNEL)) != NULL) {
int i; int i;
char c; char c;
for (i=0; i<len; i++) { for (i=0; i<name->len; i++) {
c = name[i]; c = name->name[i];
if (c >= 'A' && c <= 'Z') c |= 0x20; if (c >= 'A' && c <= 'Z') c |= 0x20;
lcname[i] = c; lcname[i] = c;
} }
bh = isofs_find_entry(dir,lcname,len, &ino, &ino_back); bh = isofs_find_entry(dir, lcname, name->len,
&ino, &ino_back);
kfree(lcname); kfree(lcname);
} else } else
bh = isofs_find_entry(dir,name,len, &ino, &ino_back); bh = isofs_find_entry(dir, name->name,
name->len, &ino, &ino_back);
if (!bh) { if (!bh)
iput(dir);
return -ENOENT; return -ENOENT;
}
brelse(bh); brelse(bh);
if (!(*result = iget(dir->i_sb,ino))) { inode = iget(dir->i_sb,ino);
iput(dir); if (!inode)
return -EACCES; return -EACCES;
}
/* We need this backlink for the ".." entry unless the name that we /* We need this backlink for the ".." entry unless the name that we
* are looking up traversed a mount point (in which case the inode * are looking up traversed a mount point (in which case the inode
* may not even be on an iso9660 filesystem, and writing to * may not even be on an iso9660 filesystem, and writing to
* u.isofs_i would only cause memory corruption). * u.isofs_i would only cause memory corruption).
*/ */
if (ino_back && !(*result)->i_pipe && (*result)->i_sb == dir->i_sb) if (ino_back && !inode->i_pipe && inode->i_sb == dir->i_sb)
(*result)->u.isofs_i.i_backlink = ino_back; inode->u.isofs_i.i_backlink = ino_back;
*result = inode;
iput(dir);
return 0; return 0;
} }
...@@ -50,6 +50,7 @@ struct inode_operations minix_dir_inode_operations = { ...@@ -50,6 +50,7 @@ struct inode_operations minix_dir_inode_operations = {
minix_mknod, /* mknod */ minix_mknod, /* mknod */
minix_rename, /* rename */ minix_rename, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */ NULL, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
NULL, /* bmap */ NULL, /* bmap */
......
...@@ -58,6 +58,7 @@ struct inode_operations minix_file_inode_operations = { ...@@ -58,6 +58,7 @@ struct inode_operations minix_file_inode_operations = {
NULL, /* mknod */ NULL, /* mknod */
NULL, /* rename */ NULL, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */ generic_readpage, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
minix_bmap, /* bmap */ minix_bmap, /* bmap */
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/dalloc.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -125,15 +126,13 @@ int minix_remount (struct super_block * sb, int * flags, char * data) ...@@ -125,15 +126,13 @@ int minix_remount (struct super_block * sb, int * flags, char * data)
* it really _is_ a minix filesystem, and to check the size * it really _is_ a minix filesystem, and to check the size
* of the directory entry. * of the directory entry.
*/ */
static const char * minix_checkroot(struct super_block *s) static const char * minix_checkroot(struct super_block *s, struct inode *dir)
{ {
struct inode * dir;
struct buffer_head *bh; struct buffer_head *bh;
struct minix_dir_entry *de; struct minix_dir_entry *de;
const char * errmsg; const char * errmsg;
int dirsize; int dirsize;
dir = s->s_mounted;
if (!S_ISDIR(dir->i_mode)) if (!S_ISDIR(dir->i_mode))
return "root directory is not a directory"; return "root directory is not a directory";
...@@ -172,6 +171,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data, ...@@ -172,6 +171,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
int i, block; int i, block;
kdev_t dev = s->s_dev; kdev_t dev = s->s_dev;
const char * errmsg; const char * errmsg;
struct inode *root_inode;
if (32 != sizeof (struct minix_inode)) if (32 != sizeof (struct minix_inode))
panic("bad V1 i-node size"); panic("bad V1 i-node size");
...@@ -272,8 +272,9 @@ struct super_block *minix_read_super(struct super_block *s,void *data, ...@@ -272,8 +272,9 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
/* set up enough so that it can read an inode */ /* set up enough so that it can read an inode */
s->s_dev = dev; s->s_dev = dev;
s->s_op = &minix_sops; s->s_op = &minix_sops;
s->s_mounted = iget(s,MINIX_ROOT_INO); root_inode = iget(s,MINIX_ROOT_INO);
if (!s->s_mounted) { s->s_root = d_alloc_root(root_inode, NULL);
if (!s->s_root) {
s->s_dev = 0; s->s_dev = 0;
brelse(bh); brelse(bh);
if (!silent) if (!silent)
...@@ -282,11 +283,11 @@ struct super_block *minix_read_super(struct super_block *s,void *data, ...@@ -282,11 +283,11 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
return NULL; return NULL;
} }
errmsg = minix_checkroot(s); errmsg = minix_checkroot(s, root_inode);
if (errmsg) { if (errmsg) {
if (!silent) if (!silent)
printk("MINIX-fs: %s\n", errmsg); printk("MINIX-fs: %s\n", errmsg);
iput (s->s_mounted); d_delete(s->s_root); /* XXX Is this enough? */
s->s_dev = 0; s->s_dev = 0;
brelse (bh); brelse (bh);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
......
...@@ -104,7 +104,7 @@ static struct buffer_head * minix_find_entry(struct inode * dir, ...@@ -104,7 +104,7 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
return NULL; return NULL;
} }
int minix_lookup(struct inode * dir,const char * name, int len, int minix_lookup(struct inode * dir, struct qstr *name,
struct inode ** result) struct inode ** result)
{ {
int ino; int ino;
...@@ -114,21 +114,14 @@ int minix_lookup(struct inode * dir,const char * name, int len, ...@@ -114,21 +114,14 @@ int minix_lookup(struct inode * dir,const char * name, int len,
*result = NULL; *result = NULL;
if (!dir) if (!dir)
return -ENOENT; return -ENOENT;
if (!S_ISDIR(dir->i_mode)) { if (!S_ISDIR(dir->i_mode))
iput(dir);
return -ENOENT; return -ENOENT;
} if (!(bh = minix_find_entry(dir, name->name, name->len, &de)))
if (!(bh = minix_find_entry(dir,name,len,&de))) {
iput(dir);
return -ENOENT; return -ENOENT;
}
ino = de->inode; ino = de->inode;
brelse(bh); brelse(bh);
if (!(*result = iget(dir->i_sb,ino))) { if (!(*result = iget(dir->i_sb,ino)))
iput(dir);
return -EACCES; return -EACCES;
}
iput(dir);
return 0; return 0;
} }
...@@ -208,42 +201,37 @@ static int minix_add_entry(struct inode * dir, ...@@ -208,42 +201,37 @@ static int minix_add_entry(struct inode * dir,
return 0; return 0;
} }
int minix_create(struct inode * dir,const char * name, int len, int mode, int minix_create(struct inode * dir, struct dentry *dentry, int mode)
struct inode ** result)
{ {
int error; int error;
struct inode * inode; struct inode * inode;
struct buffer_head * bh; struct buffer_head * bh;
struct minix_dir_entry * de; struct minix_dir_entry * de;
*result = NULL;
if (!dir) if (!dir)
return -ENOENT; return -ENOENT;
inode = minix_new_inode(dir); inode = minix_new_inode(dir);
if (!inode) { if (!inode)
iput(dir);
return -ENOSPC; return -ENOSPC;
}
inode->i_op = &minix_file_inode_operations; inode->i_op = &minix_file_inode_operations;
inode->i_mode = mode; inode->i_mode = mode;
inode->i_dirt = 1; inode->i_dirt = 1;
error = minix_add_entry(dir,name,len, &bh ,&de); error = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh ,&de);
if (error) { if (error) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
iput(dir);
return error; return error;
} }
de->inode = inode->i_ino; de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
iput(dir); d_instantiate(dentry, inode, 0);
*result = inode;
return 0; return 0;
} }
int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev) int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
{ {
int error; int error;
struct inode * inode; struct inode * inode;
...@@ -252,17 +240,15 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd ...@@ -252,17 +240,15 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
if (!dir) if (!dir)
return -ENOENT; return -ENOENT;
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (bh) { if (bh) {
brelse(bh); brelse(bh);
iput(dir);
return -EEXIST; return -EEXIST;
} }
inode = minix_new_inode(dir); inode = minix_new_inode(dir);
if (!inode) { if (!inode)
iput(dir);
return -ENOSPC; return -ENOSPC;
}
inode->i_uid = current->fsuid; inode->i_uid = current->fsuid;
inode->i_mode = mode; inode->i_mode = mode;
inode->i_op = NULL; inode->i_op = NULL;
...@@ -284,23 +270,21 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd ...@@ -284,23 +270,21 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
if (S_ISBLK(mode) || S_ISCHR(mode)) if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = to_kdev_t(rdev); inode->i_rdev = to_kdev_t(rdev);
inode->i_dirt = 1; inode->i_dirt = 1;
error = minix_add_entry(dir, name, len, &bh, &de); error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
if (error) { if (error) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
iput(dir);
return error; return error;
} }
de->inode = inode->i_ino; de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
iput(dir); d_instantiate(dentry, inode, 0);
iput(inode);
return 0; return 0;
} }
int minix_mkdir(struct inode * dir, const char * name, int len, int mode) int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
{ {
int error; int error;
struct inode * inode; struct inode * inode;
...@@ -308,31 +292,24 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -308,31 +292,24 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
struct minix_dir_entry * de; struct minix_dir_entry * de;
struct minix_sb_info * info; struct minix_sb_info * info;
if (!dir || !dir->i_sb) { if (!dir || !dir->i_sb)
iput(dir);
return -EINVAL; return -EINVAL;
}
info = &dir->i_sb->u.minix_sb; info = &dir->i_sb->u.minix_sb;
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (bh) { if (bh) {
brelse(bh); brelse(bh);
iput(dir);
return -EEXIST; return -EEXIST;
} }
if (dir->i_nlink >= MINIX_LINK_MAX) { if (dir->i_nlink >= MINIX_LINK_MAX)
iput(dir);
return -EMLINK; return -EMLINK;
}
inode = minix_new_inode(dir); inode = minix_new_inode(dir);
if (!inode) { if (!inode)
iput(dir);
return -ENOSPC; return -ENOSPC;
}
inode->i_op = &minix_dir_inode_operations; inode->i_op = &minix_dir_inode_operations;
inode->i_size = 2 * info->s_dirsize; inode->i_size = 2 * info->s_dirsize;
dir_block = minix_bread(inode,0,1); dir_block = minix_bread(inode,0,1);
if (!dir_block) { if (!dir_block) {
iput(dir);
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
...@@ -351,9 +328,9 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -351,9 +328,9 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
if (dir->i_mode & S_ISGID) if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID; inode->i_mode |= S_ISGID;
inode->i_dirt = 1; inode->i_dirt = 1;
error = minix_add_entry(dir, name, len, &bh, &de); error = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
if (error) { if (error) {
iput(dir);
inode->i_nlink=0; inode->i_nlink=0;
iput(inode); iput(inode);
return error; return error;
...@@ -362,9 +339,8 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -362,9 +339,8 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
dir->i_nlink++; dir->i_nlink++;
dir->i_dirt = 1; dir->i_dirt = 1;
iput(dir);
iput(inode);
brelse(bh); brelse(bh);
d_instantiate(dentry, inode, D_DIR);
return 0; return 0;
} }
...@@ -427,7 +403,7 @@ static int empty_dir(struct inode * inode) ...@@ -427,7 +403,7 @@ static int empty_dir(struct inode * inode)
return 1; return 1;
} }
int minix_rmdir(struct inode * dir, const char * name, int len) int minix_rmdir(struct inode * dir, struct dentry *dentry)
{ {
int retval; int retval;
struct inode * inode; struct inode * inode;
...@@ -435,13 +411,14 @@ int minix_rmdir(struct inode * dir, const char * name, int len) ...@@ -435,13 +411,14 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
struct minix_dir_entry * de; struct minix_dir_entry * de;
inode = NULL; inode = NULL;
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
retval = -ENOENT; retval = -ENOENT;
if (!bh) if (!bh)
goto end_rmdir; goto end_rmdir;
retval = -EPERM; retval = -EPERM;
if (!(inode = iget(dir->i_sb, de->inode))) inode = dentry->d_inode;
goto end_rmdir;
if ((dir->i_mode & S_ISVTX) && !fsuser() && if ((dir->i_mode & S_ISVTX) && !fsuser() &&
current->fsuid != inode->i_uid && current->fsuid != inode->i_uid &&
current->fsuid != dir->i_uid) current->fsuid != dir->i_uid)
...@@ -476,15 +453,14 @@ int minix_rmdir(struct inode * dir, const char * name, int len) ...@@ -476,15 +453,14 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_nlink--; dir->i_nlink--;
dir->i_dirt=1; dir->i_dirt=1;
d_delete(dentry);
retval = 0; retval = 0;
end_rmdir: end_rmdir:
iput(dir);
iput(inode);
brelse(bh); brelse(bh);
return retval; return retval;
} }
int minix_unlink(struct inode * dir, const char * name, int len) int minix_unlink(struct inode * dir, struct dentry *dentry)
{ {
int retval; int retval;
struct inode * inode; struct inode * inode;
...@@ -494,16 +470,16 @@ int minix_unlink(struct inode * dir, const char * name, int len) ...@@ -494,16 +470,16 @@ int minix_unlink(struct inode * dir, const char * name, int len)
repeat: repeat:
retval = -ENOENT; retval = -ENOENT;
inode = NULL; inode = NULL;
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (!bh) if (!bh)
goto end_unlink; goto end_unlink;
if (!(inode = iget(dir->i_sb, de->inode))) inode = dentry->d_inode;
goto end_unlink;
retval = -EPERM; retval = -EPERM;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
goto end_unlink; goto end_unlink;
if (de->inode != inode->i_ino) { if (de->inode != inode->i_ino) {
iput(inode);
brelse(bh); brelse(bh);
current->counter = 0; current->counter = 0;
schedule(); schedule();
...@@ -531,15 +507,15 @@ int minix_unlink(struct inode * dir, const char * name, int len) ...@@ -531,15 +507,15 @@ int minix_unlink(struct inode * dir, const char * name, int len)
inode->i_nlink--; inode->i_nlink--;
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
inode->i_dirt = 1; inode->i_dirt = 1;
d_delete(dentry); /* This also frees the inode */
retval = 0; retval = 0;
end_unlink: end_unlink:
brelse(bh); brelse(bh);
iput(inode);
iput(dir);
return retval; return retval;
} }
int minix_symlink(struct inode * dir, const char * name, int len, const char * symname) int minix_symlink(struct inode * dir, struct dentry *dentry,
const char * symname)
{ {
struct minix_dir_entry * de; struct minix_dir_entry * de;
struct inode * inode = NULL; struct inode * inode = NULL;
...@@ -547,15 +523,13 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s ...@@ -547,15 +523,13 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
int i; int i;
char c; char c;
if (!(inode = minix_new_inode(dir))) { if (!(inode = minix_new_inode(dir)))
iput(dir);
return -ENOSPC; return -ENOSPC;
}
inode->i_mode = S_IFLNK | 0777; inode->i_mode = S_IFLNK | 0777;
inode->i_op = &minix_symlink_inode_operations; inode->i_op = &minix_symlink_inode_operations;
name_block = minix_bread(inode,0,1); name_block = minix_bread(inode,0,1);
if (!name_block) { if (!name_block) {
iput(dir);
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
...@@ -569,68 +543,62 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s ...@@ -569,68 +543,62 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
brelse(name_block); brelse(name_block);
inode->i_size = i; inode->i_size = i;
inode->i_dirt = 1; inode->i_dirt = 1;
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (bh) { if (bh) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
brelse(bh); brelse(bh);
iput(dir);
return -EEXIST; return -EEXIST;
} }
i = minix_add_entry(dir, name, len, &bh, &de); i = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
if (i) { if (i) {
inode->i_nlink--; inode->i_nlink--;
inode->i_dirt = 1; inode->i_dirt = 1;
iput(inode); iput(inode);
iput(dir);
return i; return i;
} }
de->inode = inode->i_ino; de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
iput(dir); d_instantiate(dentry, inode, 0);
iput(inode);
return 0; return 0;
} }
int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len) int minix_link(struct inode * inode, struct inode * dir,
struct dentry *dentry)
{ {
int error; int error;
struct minix_dir_entry * de; struct minix_dir_entry * de;
struct buffer_head * bh; struct buffer_head * bh;
if (S_ISDIR(oldinode->i_mode)) { if (S_ISDIR(inode->i_mode))
iput(oldinode);
iput(dir);
return -EPERM; return -EPERM;
}
if (oldinode->i_nlink >= MINIX_LINK_MAX) { if (inode->i_nlink >= MINIX_LINK_MAX)
iput(oldinode);
iput(dir);
return -EMLINK; return -EMLINK;
}
bh = minix_find_entry(dir,name,len,&de); bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (bh) { if (bh) {
brelse(bh); brelse(bh);
iput(dir);
iput(oldinode);
return -EEXIST; return -EEXIST;
} }
error = minix_add_entry(dir, name, len, &bh, &de); error = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
if (error) { if (error) {
iput(dir); brelse(bh);
iput(oldinode);
return error; return error;
} }
de->inode = oldinode->i_ino; de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
brelse(bh); brelse(bh);
iput(dir); inode->i_nlink++;
oldinode->i_nlink++; inode->i_ctime = CURRENT_TIME;
oldinode->i_ctime = CURRENT_TIME; inode->i_dirt = 1;
oldinode->i_dirt = 1; d_instantiate(dentry, inode, 0);
iput(oldinode);
return 0; return 0;
} }
...@@ -649,7 +617,9 @@ static int subdir(struct inode * new_inode, struct inode * old_inode) ...@@ -649,7 +617,9 @@ static int subdir(struct inode * new_inode, struct inode * old_inode)
if (new_inode->i_dev != old_inode->i_dev) if (new_inode->i_dev != old_inode->i_dev)
break; break;
ino = new_inode->i_ino; ino = new_inode->i_ino;
if (minix_lookup(new_inode,"..",2,&new_inode)) if (minix_lookup(new_inode,
&(struct qstr) { "..", 2, 0 },
&new_inode))
break; break;
if (new_inode->i_ino == ino) if (new_inode->i_ino == ino)
break; break;
...@@ -671,8 +641,8 @@ static int subdir(struct inode * new_inode, struct inode * old_inode) ...@@ -671,8 +641,8 @@ static int subdir(struct inode * new_inode, struct inode * old_inode)
* Anybody can rename anything with this: the permission checks are left to the * Anybody can rename anything with this: the permission checks are left to the
* higher-level routines. * higher-level routines.
*/ */
static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len, static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct inode * new_dir, const char * new_name, int new_len) struct inode * new_dir, struct dentry *new_dentry)
{ {
struct inode * old_inode, * new_inode; struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh; struct buffer_head * old_bh, * new_bh, * dir_bh;
...@@ -686,28 +656,26 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol ...@@ -686,28 +656,26 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
brelse(old_bh); brelse(old_bh);
brelse(new_bh); brelse(new_bh);
brelse(dir_bh); brelse(dir_bh);
iput(old_inode);
iput(new_inode);
current->counter = 0; current->counter = 0;
schedule(); schedule();
start_up: start_up:
old_inode = new_inode = NULL; old_inode = new_inode = NULL;
old_bh = new_bh = dir_bh = NULL; old_bh = new_bh = dir_bh = NULL;
old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de); old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
old_dentry->d_name.len, &old_de);
retval = -ENOENT; retval = -ENOENT;
if (!old_bh) if (!old_bh)
goto end_rename; goto end_rename;
old_inode = __iget(old_dir->i_sb, old_de->inode); old_inode = old_dentry->d_inode;
if (!old_inode)
goto end_rename;
retval = -EPERM; retval = -EPERM;
if ((old_dir->i_mode & S_ISVTX) && if ((old_dir->i_mode & S_ISVTX) &&
current->fsuid != old_inode->i_uid && current->fsuid != old_inode->i_uid &&
current->fsuid != old_dir->i_uid && !fsuser()) current->fsuid != old_dir->i_uid && !fsuser())
goto end_rename; goto end_rename;
new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de); new_inode = new_dentry->d_inode;
new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
new_dentry->d_name.len, &new_de);
if (new_bh) { if (new_bh) {
new_inode = __iget(new_dir->i_sb, new_de->inode);
if (!new_inode) { if (!new_inode) {
brelse(new_bh); brelse(new_bh);
new_bh = NULL; new_bh = NULL;
...@@ -754,7 +722,10 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol ...@@ -754,7 +722,10 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
goto end_rename; goto end_rename;
} }
if (!new_bh) { if (!new_bh) {
retval = minix_add_entry(new_dir,new_name,new_len,&new_bh,&new_de); retval = minix_add_entry(new_dir,
new_dentry->d_name.name,
new_dentry->d_name.len,
&new_bh, &new_de);
if (retval) if (retval)
goto end_rename; goto end_rename;
} }
...@@ -794,15 +765,14 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol ...@@ -794,15 +765,14 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
new_dir->i_dirt = 1; new_dir->i_dirt = 1;
} }
} }
/* Update the dcache */
d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name);
d_delete(new_dentry);
retval = 0; retval = 0;
end_rename: end_rename:
brelse(dir_bh); brelse(dir_bh);
brelse(old_bh); brelse(old_bh);
brelse(new_bh); brelse(new_bh);
iput(old_inode);
iput(new_inode);
iput(old_dir);
iput(new_dir);
return retval; return retval;
} }
...@@ -815,8 +785,8 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol ...@@ -815,8 +785,8 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
* the same device that races occur: many renames can happen at once, as long * the same device that races occur: many renames can happen at once, as long
* as they are on different partitions. * as they are on different partitions.
*/ */
int minix_rename(struct inode * old_dir, const char * old_name, int old_len, int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct inode * new_dir, const char * new_name, int new_len) struct inode * new_dir, struct dentry *new_dentry)
{ {
static struct wait_queue * wait = NULL; static struct wait_queue * wait = NULL;
static int lock = 0; static int lock = 0;
...@@ -825,8 +795,8 @@ int minix_rename(struct inode * old_dir, const char * old_name, int old_len, ...@@ -825,8 +795,8 @@ int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
while (lock) while (lock)
sleep_on(&wait); sleep_on(&wait);
lock = 1; lock = 1;
result = do_minix_rename(old_dir, old_name, old_len, result = do_minix_rename(old_dir, old_dentry,
new_dir, new_name, new_len); new_dir, new_dentry);
lock = 0; lock = 0;
wake_up(&wait); wake_up(&wait);
return result; return result;
......
...@@ -363,7 +363,6 @@ nfs_notify_change(struct inode *inode, struct iattr *attr) ...@@ -363,7 +363,6 @@ nfs_notify_change(struct inode *inode, struct iattr *attr)
nfs_truncate_dirty_pages(inode, sattr.size); nfs_truncate_dirty_pages(inode, sattr.size);
nfs_refresh_inode(inode, &fattr); nfs_refresh_inode(inode, &fattr);
} }
inode->i_dirt = 0;
return error; return error;
} }
......
...@@ -90,7 +90,6 @@ int do_truncate(struct inode *inode, unsigned long length) ...@@ -90,7 +90,6 @@ int do_truncate(struct inode *inode, unsigned long length)
vmtruncate(inode, length); vmtruncate(inode, length);
if (inode->i_op && inode->i_op->truncate) if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
inode->i_status |= ST_MODIFIED;
} }
up(&inode->i_sem); up(&inode->i_sem);
return error; return error;
...@@ -436,12 +435,7 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode) ...@@ -436,12 +435,7 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
inode->i_dirt = 1;
err = notify_change(inode, &newattrs); err = notify_change(inode, &newattrs);
#ifdef CONFIG_OMIRR
if(!err)
omirr_printall(inode, " M %ld %ld ", CURRENT_TIME, newattrs.ia_mode);
#endif
out: out:
unlock_kernel(); unlock_kernel();
return err; return err;
...@@ -471,12 +465,7 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode) ...@@ -471,12 +465,7 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
inode->i_dirt = 1;
error = notify_change(inode, &newattrs); error = notify_change(inode, &newattrs);
#ifdef CONFIG_OMIRR
if(!error)
omirr_printall(inode, " M %ld %ld ", CURRENT_TIME, newattrs.ia_mode);
#endif
iput_and_out: iput_and_out:
iput(inode); iput(inode);
out: out:
...@@ -528,7 +517,6 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -528,7 +517,6 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
newattrs.ia_mode &= ~S_ISGID; newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
inode->i_dirt = 1;
if (inode->i_sb && inode->i_sb->dq_op) { if (inode->i_sb && inode->i_sb->dq_op) {
inode->i_sb->dq_op->initialize(inode, -1); inode->i_sb->dq_op->initialize(inode, -1);
error = -EDQUOT; error = -EDQUOT;
...@@ -539,11 +527,6 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -539,11 +527,6 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1); inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else } else
error = notify_change(inode, &newattrs); error = notify_change(inode, &newattrs);
#ifdef CONFIG_OMIRR
if(!error)
omirr_printall(inode, " O %d %d ", CURRENT_TIME,
newattrs.ia_uid, newattrs.ia_gid);
#endif
out: out:
unlock_kernel(); unlock_kernel();
return error; return error;
...@@ -590,7 +573,6 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -590,7 +573,6 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
newattrs.ia_mode &= ~S_ISGID; newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
inode->i_dirt = 1;
if (inode->i_sb->dq_op) { if (inode->i_sb->dq_op) {
inode->i_sb->dq_op->initialize(inode, -1); inode->i_sb->dq_op->initialize(inode, -1);
error = -EDQUOT; error = -EDQUOT;
...@@ -601,11 +583,6 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -601,11 +583,6 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1); inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else } else
error = notify_change(inode, &newattrs); error = notify_change(inode, &newattrs);
#ifdef CONFIG_OMIRR
if(!error)
omirr_printall(inode, " O %d %d ", CURRENT_TIME,
newattrs.ia_uid, newattrs.ia_gid);
#endif
iput_and_out: iput_and_out:
iput(inode); iput(inode);
out: out:
......
...@@ -75,10 +75,7 @@ static long pipe_read(struct inode * inode, struct file * filp, ...@@ -75,10 +75,7 @@ static long pipe_read(struct inode * inode, struct file * filp,
PIPE_LOCK(*inode)--; PIPE_LOCK(*inode)--;
wake_up_interruptible(&PIPE_WAIT(*inode)); wake_up_interruptible(&PIPE_WAIT(*inode));
if (read) { if (read) {
if (DO_UPDATE_ATIME(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
return read; return read;
} }
if (PIPE_WRITERS(*inode)) if (PIPE_WRITERS(*inode))
...@@ -132,7 +129,7 @@ static long pipe_write(struct inode * inode, struct file * filp, ...@@ -132,7 +129,7 @@ static long pipe_write(struct inode * inode, struct file * filp,
free = 1; free = 1;
} }
inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_ctime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1; mark_inode_dirty(inode);
return written; return written;
} }
...@@ -423,11 +420,13 @@ int do_pipe(int *fd) ...@@ -423,11 +420,13 @@ int do_pipe(int *fd)
j = error; j = error;
f1->f_inode = f2->f_inode = inode; f1->f_inode = f2->f_inode = inode;
/* read file */ /* read file */
f1->f_pos = f2->f_pos = 0; f1->f_pos = f2->f_pos = 0;
f1->f_flags = O_RDONLY; f1->f_flags = O_RDONLY;
f1->f_op = &read_pipe_fops; f1->f_op = &read_pipe_fops;
f1->f_mode = 1; f1->f_mode = 1;
/* write file */ /* write file */
f2->f_flags = O_WRONLY; f2->f_flags = O_WRONLY;
f2->f_op = &write_pipe_fops; f2->f_op = &write_pipe_fops;
......
...@@ -201,5 +201,4 @@ void proc_read_inode(struct inode * inode) ...@@ -201,5 +201,4 @@ void proc_read_inode(struct inode * inode)
void proc_write_inode(struct inode * inode) void proc_write_inode(struct inode * inode)
{ {
inode->i_dirt=0;
} }
...@@ -168,7 +168,6 @@ asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count ...@@ -168,7 +168,6 @@ asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count
goto out; goto out;
down(&inode->i_sem); down(&inode->i_sem);
error = write(inode,file,buf,count); error = write(inode,file,buf,count);
inode->i_status |= ST_MODIFIED;
up(&inode->i_sem); up(&inode->i_sem);
out: out:
fput(file, inode); fput(file, inode);
...@@ -264,8 +263,6 @@ static long do_readv_writev(int type, struct inode * inode, struct file * file, ...@@ -264,8 +263,6 @@ static long do_readv_writev(int type, struct inode * inode, struct file * file,
if (nr != len) if (nr != len)
break; break;
} }
if(fn == (IO_fn_t) file->f_op->write)
inode->i_status |= ST_MODIFIED;
if (iov != iovstack) if (iov != iovstack)
kfree(iov); kfree(iov);
return retval; return retval;
......
...@@ -256,10 +256,7 @@ asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz) ...@@ -256,10 +256,7 @@ asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
iput(inode); iput(inode);
goto out; goto out;
} }
if (!IS_RDONLY(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
error = inode->i_op->readlink(inode,buf,bufsiz); error = inode->i_op->readlink(inode,buf,bufsiz);
iput(inode); iput(inode);
out: out:
......
...@@ -41,6 +41,7 @@ struct inode_operations ufs_file_inode_operations = { ...@@ -41,6 +41,7 @@ struct inode_operations ufs_file_inode_operations = {
NULL, /* mknod */ NULL, /* mknod */
NULL, /* rename */ NULL, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */ generic_readpage, /* readpage */
NULL, /* writepage */ NULL, /* writepage */
ufs_bmap, /* bmap */ ufs_bmap, /* bmap */
......
...@@ -35,12 +35,14 @@ static int ufs_match (int len, const char * const name, struct ufs_direct * d) ...@@ -35,12 +35,14 @@ static int ufs_match (int len, const char * const name, struct ufs_direct * d)
} }
/* XXX - this is a mess, especially for endianity */ /* XXX - this is a mess, especially for endianity */
int ufs_lookup (struct inode * dir, const char * name, int len, int ufs_lookup (struct inode * dir, struct qstr *qname,
struct inode ** result) struct inode ** result)
{ {
unsigned long int lfragno, fragno; unsigned long int lfragno, fragno;
struct buffer_head * bh; struct buffer_head * bh;
struct ufs_direct * d; struct ufs_direct * d;
const char *name = qname->name;
int len = qname->len;
if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG)
printk("Passed name: %s\nPassed length: %d\n", name, len); printk("Passed name: %s\nPassed length: %d\n", name, len);
......
...@@ -254,7 +254,7 @@ ufs_read_super(struct super_block * sb, void * data, int silent) ...@@ -254,7 +254,7 @@ ufs_read_super(struct super_block * sb, void * data, int silent)
sb->u.ufs_sb.s_lmask = ~((ufs_swab32(usb->fs_fmask) - ufs_swab32(usb->fs_bmask)) sb->u.ufs_sb.s_lmask = ~((ufs_swab32(usb->fs_fmask) - ufs_swab32(usb->fs_bmask))
>> ufs_swab32(usb->fs_fshift)); >> ufs_swab32(usb->fs_fshift));
sb->u.ufs_sb.s_fsfrag = ufs_swab32(usb->fs_frag); /* XXX - rename this later */ sb->u.ufs_sb.s_fsfrag = ufs_swab32(usb->fs_frag); /* XXX - rename this later */
sb->s_mounted = iget(sb, UFS_ROOTINO); sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL);
#ifdef DEBUG_UFS_SUPER #ifdef DEBUG_UFS_SUPER
printk("ufs_read_super: inopb %u\n", sb->u.ufs_sb.s_inopb); printk("ufs_read_super: inopb %u\n", sb->u.ufs_sb.s_inopb);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/list.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -78,9 +79,6 @@ extern int max_files, nr_files; ...@@ -78,9 +79,6 @@ extern int max_files, nr_files;
*/ */
#define FS_IBASKET 8 /* FS does callback to free_ibasket() if space gets low. */ #define FS_IBASKET 8 /* FS does callback to free_ibasket() if space gets low. */
/* public flags for i_status */
#define ST_MODIFIED 1024
/* /*
* These are the fs-independent mount-flags: up to 16 flags are supported * These are the fs-independent mount-flags: up to 16 flags are supported
*/ */
...@@ -126,7 +124,12 @@ extern int max_files, nr_files; ...@@ -126,7 +124,12 @@ extern int max_files, nr_files;
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME) #define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME)
#define DO_UPDATE_ATIME(inode) (!IS_NOATIME(inode) && !IS_RDONLY(inode))
#define UPDATE_ATIME(inode) \
if (!IS_NOATIME(inode) && !IS_RDONLY(inode)) { \
inode->i_atime = CURRENT_TIME; \
mark_inode_dirty(inode); \
}
/* the read-only stuff doesn't really belong here, but any other place is /* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */ probably as bad and I don't want to create yet another include file. */
...@@ -300,10 +303,8 @@ struct iattr { ...@@ -300,10 +303,8 @@ struct iattr {
#include <linux/quota.h> #include <linux/quota.h>
struct inode { struct inode {
struct inode *i_hash_next; struct list_head i_hash;
struct inode *i_hash_prev; struct list_head i_list;
struct inode *i_next;
struct inode *i_prev;
unsigned long i_ino; unsigned long i_ino;
kdev_t i_dev; kdev_t i_dev;
...@@ -330,25 +331,14 @@ struct inode { ...@@ -330,25 +331,14 @@ struct inode {
struct page *i_pages; struct page *i_pages;
struct dquot *i_dquot[MAXQUOTAS]; struct dquot *i_dquot[MAXQUOTAS];
struct inode *i_lru_next;
struct inode *i_lru_prev;
struct inode *i_basket_next;
struct inode *i_basket_prev;
struct dentry *i_dentry; struct dentry *i_dentry;
unsigned short i_status; unsigned int i_state;
unsigned short i_reuse_count;
unsigned int i_flags; unsigned int i_flags;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe; unsigned char i_pipe;
unsigned char i_sock; unsigned char i_sock;
unsigned char i_level;
unsigned short i_fill;
int i_writecount; int i_writecount;
unsigned int i_attr_flags; unsigned int i_attr_flags;
union { union {
...@@ -369,6 +359,17 @@ struct inode { ...@@ -369,6 +359,17 @@ struct inode {
} u; } u;
}; };
/* Inode state bits.. */
#define I_DIRTY 0
#define I_LOCK 1
extern void __mark_inode_dirty(struct inode *);
static inline void mark_inode_dirty(struct inode *inode)
{
if (!test_and_set_bit(I_DIRTY, &inode->i_state))
__mark_inode_dirty(inode);
}
struct file { struct file {
struct file *f_next, **f_pprev; struct file *f_next, **f_pprev;
struct inode *f_inode; struct inode *f_inode;
...@@ -735,42 +736,12 @@ extern inline void vfs_unlock(void) ...@@ -735,42 +736,12 @@ extern inline void vfs_unlock(void)
/* Not to be used by ordinary vfs users */ /* Not to be used by ordinary vfs users */
extern void _get_inode(struct inode * inode); extern void _get_inode(struct inode * inode);
extern blocking void __iput(struct inode * inode); extern void iput(struct inode * inode);
extern blocking void _iput(struct inode * inode);
extern inline blocking void iput(struct inode * inode)
{
if (inode) {
extern void wake_up_interruptible(struct wait_queue **q);
if (inode->i_pipe)
wake_up_interruptible(&inode->u.pipe_i.wait);
/* It does not matter if somebody re-increments it in between,
* only the _last_ user needs to call _iput().
*/
if (atomic_dec_and_test(&inode->i_count))
_iput(inode);
}
}
extern blocking struct inode * iget(struct super_block * sb, unsigned long nr); extern blocking struct inode * iget(struct super_block * sb, unsigned long nr);
extern blocking void _clear_inode(struct inode * inode, int external, int verbose); extern blocking void clear_inode(struct inode * inode);
extern blocking inline void clear_inode(struct inode * inode) extern blocking struct inode * get_empty_inode(void);
{
vfs_lock();
_clear_inode(inode, 1, 1);
vfs_unlock();
}
extern blocking struct inode * _get_empty_inode(void);
extern inline blocking struct inode * get_empty_inode(void)
{
struct inode * inode;
vfs_lock();
inode = _get_empty_inode();
vfs_unlock();
return inode;
}
/* Please prefer to use this function in future, instead of using /* Please prefer to use this function in future, instead of using
* a get_empty_inode()/insert_inode_hash() combination. * a get_empty_inode()/insert_inode_hash() combination.
* It allows for better checking and less race conditions. * It allows for better checking and less race conditions.
......
...@@ -152,7 +152,7 @@ extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inod ...@@ -152,7 +152,7 @@ extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inod
extern int isofs_open(struct inode * inode, struct file * filp); extern int isofs_open(struct inode * inode, struct file * filp);
extern void isofs_release(struct inode * inode, struct file * filp); extern void isofs_release(struct inode * inode, struct file * filp);
extern int isofs_lookup(struct inode * dir,const char * name, int len, extern int isofs_lookup(struct inode * dir, struct qstr *dentry,
struct inode ** result); struct inode ** result);
extern unsigned long isofs_count_free_inodes(struct super_block *sb); extern unsigned long isofs_count_free_inodes(struct super_block *sb);
extern int isofs_new_block(int dev); extern int isofs_new_block(int dev);
......
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
/*
* Simple doubly linked list implementation.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD(name) \
struct list_head name = { &name, &name }
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
static inline void list_add(struct list_head *new, struct list_head *head)
{
struct list_head *next = head->next;
next->prev = new;
new->next = next;
new->prev = head;
head->next = new;
}
static inline void list_del(struct list_head *entry)
{
struct list_head *next, *prev;
next = entry->next;
prev = entry->prev;
next->prev = prev;
prev->next = next;
}
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
#endif
...@@ -88,19 +88,18 @@ struct minix_dir_entry { ...@@ -88,19 +88,18 @@ struct minix_dir_entry {
#ifdef __KERNEL__ #ifdef __KERNEL__
extern int minix_lookup(struct inode * dir,const char * name, int len, extern int minix_lookup(struct inode * dir, struct qstr *name,
struct inode ** result); struct inode ** result);
extern int minix_create(struct inode * dir,const char * name, int len, int mode, extern int minix_create(struct inode * dir, struct dentry *dentry, int mode);
struct inode ** result); extern int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode);
extern int minix_mkdir(struct inode * dir, const char * name, int len, int mode); extern int minix_rmdir(struct inode * dir, struct dentry *dentry);
extern int minix_rmdir(struct inode * dir, const char * name, int len); extern int minix_unlink(struct inode * dir, struct dentry *dentry);
extern int minix_unlink(struct inode * dir, const char * name, int len); extern int minix_symlink(struct inode * inode, struct dentry *dentry,
extern int minix_symlink(struct inode * inode, const char * name, int len,
const char * symname); const char * symname);
extern int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len); extern int minix_link(struct inode * oldinode, struct inode * dir, struct dentry *dentry);
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev); extern int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len, extern int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct inode * new_dir, const char * new_name, int new_len); struct inode * new_dir, struct dentry *new_dentry);
extern struct inode * minix_new_inode(const struct inode * dir); extern struct inode * minix_new_inode(const struct inode * dir);
extern void minix_free_inode(struct inode * inode); extern void minix_free_inode(struct inode * inode);
extern unsigned long minix_count_free_inodes(struct super_block *sb); extern unsigned long minix_count_free_inodes(struct super_block *sb);
......
...@@ -225,7 +225,7 @@ extern void ufs_put_inode(struct inode * inode); ...@@ -225,7 +225,7 @@ extern void ufs_put_inode(struct inode * inode);
extern void ufs_print_inode (struct inode *); extern void ufs_print_inode (struct inode *);
/* ufs_namei.c */ /* ufs_namei.c */
extern int ufs_lookup (struct inode *, const char *, int, struct inode **); extern int ufs_lookup (struct inode *, struct qstr *, struct inode **);
/* ufs_super.c */ /* ufs_super.c */
extern void ufs_warning (struct super_block *, const char *, const char *, ...) extern void ufs_warning (struct super_block *, const char *, const char *, ...)
......
...@@ -142,7 +142,7 @@ EXPORT_SYMBOL(getname); ...@@ -142,7 +142,7 @@ EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(putname); EXPORT_SYMBOL(putname);
EXPORT_SYMBOL(__fput); EXPORT_SYMBOL(__fput);
EXPORT_SYMBOL(iget); EXPORT_SYMBOL(iget);
EXPORT_SYMBOL(_iput); EXPORT_SYMBOL(iput);
EXPORT_SYMBOL(__namei); EXPORT_SYMBOL(__namei);
EXPORT_SYMBOL(lookup_dentry); EXPORT_SYMBOL(lookup_dentry);
EXPORT_SYMBOL(open_namei); EXPORT_SYMBOL(open_namei);
...@@ -342,7 +342,7 @@ EXPORT_SYMBOL(set_writetime); ...@@ -342,7 +342,7 @@ EXPORT_SYMBOL(set_writetime);
EXPORT_SYMBOL(sys_tz); EXPORT_SYMBOL(sys_tz);
EXPORT_SYMBOL(__wait_on_super); EXPORT_SYMBOL(__wait_on_super);
EXPORT_SYMBOL(file_fsync); EXPORT_SYMBOL(file_fsync);
EXPORT_SYMBOL(_clear_inode); EXPORT_SYMBOL(clear_inode);
EXPORT_SYMBOL(refile_buffer); EXPORT_SYMBOL(refile_buffer);
EXPORT_SYMBOL(nr_async_pages); EXPORT_SYMBOL(nr_async_pages);
EXPORT_SYMBOL(___strtok); EXPORT_SYMBOL(___strtok);
...@@ -353,7 +353,7 @@ EXPORT_SYMBOL(chrdev_inode_operations); ...@@ -353,7 +353,7 @@ EXPORT_SYMBOL(chrdev_inode_operations);
EXPORT_SYMBOL(blkdev_inode_operations); EXPORT_SYMBOL(blkdev_inode_operations);
EXPORT_SYMBOL(read_ahead); EXPORT_SYMBOL(read_ahead);
EXPORT_SYMBOL(get_hash_table); EXPORT_SYMBOL(get_hash_table);
EXPORT_SYMBOL(_get_empty_inode); EXPORT_SYMBOL(get_empty_inode);
EXPORT_SYMBOL(insert_inode_hash); EXPORT_SYMBOL(insert_inode_hash);
EXPORT_SYMBOL(event); EXPORT_SYMBOL(event);
EXPORT_SYMBOL(__down); EXPORT_SYMBOL(__down);
......
...@@ -399,8 +399,6 @@ int acct_process(long exitcode) ...@@ -399,8 +399,6 @@ int acct_process(long exitcode)
acct_file.f_op->write(acct_file.f_inode, &acct_file, acct_file.f_op->write(acct_file.f_inode, &acct_file,
(char *)&ac, sizeof(struct acct)); (char *)&ac, sizeof(struct acct));
/* inode->i_status |= ST_MODIFIED is willingly *not* done here */
set_fs(fs); set_fs(fs);
} }
return 0; return 0;
......
...@@ -753,10 +753,7 @@ long generic_file_read(struct inode * inode, struct file * filp, ...@@ -753,10 +753,7 @@ long generic_file_read(struct inode * inode, struct file * filp,
filp->f_reada = 1; filp->f_reada = 1;
if (page_cache) if (page_cache)
free_page(page_cache); free_page(page_cache);
if (DO_UPDATE_ATIME(inode)) { UPDATE_ATIME(inode)
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
if (!read) if (!read)
read = error; read = error;
return read; return read;
...@@ -919,7 +916,6 @@ static inline int do_write_page(struct inode * inode, struct file * file, ...@@ -919,7 +916,6 @@ static inline int do_write_page(struct inode * inode, struct file * file,
retval = -EIO; retval = -EIO;
if (size == file->f_op->write(inode, file, (const char *) page, size)) if (size == file->f_op->write(inode, file, (const char *) page, size))
retval = 0; retval = 0;
/* inode->i_status |= ST_MODIFIED is willingly *not* done here */
set_fs(old_fs); set_fs(old_fs);
return retval; return retval;
} }
...@@ -1189,10 +1185,7 @@ int generic_file_mmap(struct inode * inode, struct file * file, struct vm_area_s ...@@ -1189,10 +1185,7 @@ int generic_file_mmap(struct inode * inode, struct file * file, struct vm_area_s
return -EACCES; return -EACCES;
if (!inode->i_op || !inode->i_op->readpage) if (!inode->i_op || !inode->i_op->readpage)
return -ENOEXEC; return -ENOEXEC;
if (DO_UPDATE_ATIME(inode)) { UPDATE_ATIME(inode);
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
vma->vm_inode = inode; vma->vm_inode = inode;
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
vma->vm_ops = ops; vma->vm_ops = ops;
......
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