diff options
Diffstat (limited to 'fs/sysv')
-rw-r--r-- | fs/sysv/dir.c | 1 | ||||
-rw-r--r-- | fs/sysv/file.c | 7 | ||||
-rw-r--r-- | fs/sysv/ialloc.c | 11 | ||||
-rw-r--r-- | fs/sysv/inode.c | 15 | ||||
-rw-r--r-- | fs/sysv/namei.c | 81 | ||||
-rw-r--r-- | fs/sysv/symlink.c | 18 | ||||
-rw-r--r-- | fs/sysv/truncate.c | 12 |
7 files changed, 82 insertions, 63 deletions
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 8b942a5b1..3dd0931cf 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -57,6 +57,7 @@ struct inode_operations sysv_dir_inode_operations = { sysv_mknod, /* mknod */ sysv_rename, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff --git a/fs/sysv/file.c b/fs/sysv/file.c index da07ef7a8..1a28e4c2a 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -64,6 +64,7 @@ struct inode_operations sysv_file_inode_operations = { NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ generic_readpage, /* readpage */ NULL, /* writepage */ sysv_bmap, /* bmap */ @@ -194,7 +195,7 @@ long sysv_file_read(struct inode * inode, struct file * filp, filp->f_reada = 1; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } return read; } @@ -255,7 +256,7 @@ static long sysv_file_write(struct inode * inode, struct file * filp, pos += c; if (pos > inode->i_size) { inode->i_size = pos; - inode->i_dirt = 1; + mark_inode_dirty(inode); } written += c; buf += c; @@ -265,6 +266,6 @@ static long sysv_file_write(struct inode * inode, struct file * filp, } inode->i_mtime = inode->i_ctime = CURRENT_TIME; filp->f_pos = pos; - inode->i_dirt = 1; + mark_inode_dirty(inode); return written; } diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 97bc7284f..fa0b3cf95 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -62,9 +62,8 @@ void sysv_free_inode(struct inode * inode) printk("sysv_free_inode: inode has no device\n"); return; } - if (atomic_read(&inode->i_count) != 1) { - printk("sysv_free_inode: inode has count=%d\n", - atomic_read(&inode->i_count)); + if (inode->i_count != 1) { + printk("sysv_free_inode: inode has count=%d\n", inode->i_count); return; } if (inode->i_nlink) { @@ -150,12 +149,12 @@ struct inode * sysv_new_inode(const struct inode * dir) mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); sb->s_dirt = 1; /* and needs time stamp */ - atomic_set(&inode->i_count, 1); + inode->i_count = 1; inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - inode->i_dirt = 1; + mark_inode_dirty(inode); inode->i_ino = ino; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_op = NULL; @@ -166,7 +165,7 @@ struct inode * sysv_new_inode(const struct inode * dir) inode->i_size = 0; /* ditto */ sysv_write_inode(inode); /* ensure inode not allocated again */ /* FIXME: caller may call this too. */ - inode->i_dirt = 1; /* cleared by sysv_write_inode() */ + mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ /* That's it. */ (*sb->sv_sb_total_free_inodes)--; mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */ diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index f8c6a1b38..b2d7edfbc 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -344,6 +344,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, struct buffer_head *bh; const char *found; kdev_t dev = sb->s_dev; + struct inode *root_inode; if (1024 != sizeof (struct xenix_super_block)) panic("Xenix FS: bad super-block size"); @@ -483,9 +484,10 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, /* set up enough so that it can read an inode */ sb->s_dev = dev; sb->s_op = &sysv_sops; - sb->s_mounted = iget(sb,SYSV_ROOT_INO); + root_inode = iget(sb,SYSV_ROOT_INO); + sb->s_root = d_alloc_root(root_inode, NULL); unlock_super(sb); - if (!sb->s_mounted) { + if (!sb->s_root) { printk("SysV FS: get root inode failed\n"); sysv_put_super(sb); return NULL; @@ -534,7 +536,7 @@ void sysv_put_super(struct super_block *sb) MOD_DEC_USE_COUNT; } -void sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { struct statfs tmp; @@ -547,7 +549,7 @@ void sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) tmp.f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ tmp.f_namelen = SYSV_NAMELEN; /* Don't know what value to put in tmp.f_fsid */ /* file system id */ - copy_to_user(buf, &tmp, bufsiz); + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } @@ -667,7 +669,7 @@ repeat: } *p = tmp; inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); return result; } @@ -900,13 +902,11 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); - inode->i_dirt = 0; return 0; } block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits); if (!(bh = sv_bread(sb,inode->i_dev,block))) { printk("unable to read i-node block\n"); - inode->i_dirt = 0; return 0; } raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1); @@ -937,7 +937,6 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) else for (block = 0; block < 10+1+1+1; block++) write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]); - inode->i_dirt=0; mark_buffer_dirty(bh, 1); return bh; } diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index d1b67ab5f..b3586b58f 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -175,7 +175,7 @@ static int sysv_add_entry(struct inode * dir, if (pos > dir->i_size) { de->inode = 0; dir->i_size = pos; - dir->i_dirt = 1; + mark_inode_dirty(dir); } if (de->inode) { if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) { @@ -184,7 +184,7 @@ static int sysv_add_entry(struct inode * dir, } } else { dir->i_mtime = dir->i_ctime = CURRENT_TIME; - dir->i_dirt = 1; + mark_inode_dirty(dir); for (i = 0; i < SYSV_NAMELEN ; i++) de->name[i] = (i < namelen) ? name[i] : 0; mark_buffer_dirty(bh, 1); @@ -219,11 +219,11 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode, } inode->i_op = &sysv_file_inode_operations; inode->i_mode = mode; - inode->i_dirt = 1; + mark_inode_dirty(inode); error = sysv_add_entry(dir,name,len, &bh ,&de); if (error) { inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); iput(dir); return error; @@ -276,11 +276,11 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde init_fifo(inode); if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); - inode->i_dirt = 1; + mark_inode_dirty(inode); error = sysv_add_entry(dir, name, len, &bh, &de); if (error) { inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); iput(dir); return error; @@ -325,7 +325,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) if (!dir_block) { iput(dir); inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -ENOSPC; } @@ -341,7 +341,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask); if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; - inode->i_dirt = 1; + mark_inode_dirty(inode); error = sysv_add_entry(dir, name, len, &bh, &de); if (error) { iput(dir); @@ -352,7 +352,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) de->inode = inode->i_ino; mark_buffer_dirty(bh, 1); dir->i_nlink++; - dir->i_dirt = 1; + mark_inode_dirty(dir); iput(dir); iput(inode); brelse(bh); @@ -454,7 +454,7 @@ int sysv_rmdir(struct inode * dir, const char * name, int len) retval = -ENOENT; goto end_rmdir; } - if (atomic_read(&inode->i_count) > 1) { + if (inode->i_count > 1) { retval = -EBUSY; goto end_rmdir; } @@ -463,10 +463,10 @@ int sysv_rmdir(struct inode * dir, const char * name, int len) de->inode = 0; mark_buffer_dirty(bh, 1); inode->i_nlink=0; - inode->i_dirt=1; + mark_inode_dirty(inode); dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt=1; + mark_inode_dirty(dir); retval = 0; end_rmdir: iput(dir); @@ -517,10 +517,10 @@ repeat: de->inode = 0; mark_buffer_dirty(bh, 1); dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt = 1; + mark_inode_dirty(dir); inode->i_nlink--; inode->i_ctime = dir->i_ctime; - inode->i_dirt = 1; + mark_inode_dirty(inode); retval = 0; end_unlink: brelse(bh); @@ -550,7 +550,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy if (!name_block) { iput(dir); inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -ENOSPC; } @@ -563,11 +563,11 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy mark_buffer_dirty(name_block, 1); brelse(name_block); inode->i_size = i; - inode->i_dirt = 1; + mark_inode_dirty(inode); bh = sysv_find_entry(dir,name,len,&de); if (bh) { inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); brelse(bh); iput(dir); @@ -576,7 +576,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy i = sysv_add_entry(dir, name, len, &bh, &de); if (i) { inode->i_nlink--; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); iput(dir); return i; @@ -624,7 +624,7 @@ int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, in iput(dir); oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; - oldinode->i_dirt = 1; + mark_inode_dirty(oldinode); iput(oldinode); return 0; } @@ -635,7 +635,7 @@ static int subdir(struct inode * new_inode, struct inode * old_inode) int ino; int result; - atomic_inc(&new_inode->i_count); + new_inode->i_count++; result = 0; for (;;) { if (new_inode == old_inode) { @@ -667,8 +667,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 * higher-level routines. */ -static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len) +static int do_sysv_rename(struct inode * old_dir, struct dentry * old_dentry, + struct inode * new_dir, struct dentry * new_dentry) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; @@ -687,21 +687,21 @@ try_again: start_up: old_inode = new_inode = NULL; old_bh = new_bh = dir_bh = NULL; - old_bh = sysv_find_entry(old_dir,old_name,old_len,&old_de); + old_bh = sysv_find_entry(old_dir,old_dentry->d_name.name, + old_dentry->d_name.len,&old_de); retval = -ENOENT; if (!old_bh) goto end_rename; - old_inode = __iget(old_dir->i_sb, old_de->inode, 0); /* don't cross mnt-points */ - if (!old_inode) - goto end_rename; + old_inode = old_dentry->d_inode;/* don't cross mnt-points */ retval = -EPERM; if ((old_dir->i_mode & S_ISVTX) && current->fsuid != old_inode->i_uid && current->fsuid != old_dir->i_uid && !fsuser()) goto end_rename; - new_bh = sysv_find_entry(new_dir,new_name,new_len,&new_de); + new_inode = new_dentry->d_inode; + new_bh = sysv_find_entry(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len,&new_de); if (new_bh) { - new_inode = __iget(new_dir->i_sb, new_de->inode, 0); if (!new_inode) { brelse(new_bh); new_bh = NULL; @@ -722,7 +722,7 @@ start_up: if (!empty_dir(new_inode)) goto end_rename; retval = -EBUSY; - if (atomic_read(&new_inode->i_count) > 1) + if (new_inode->i_count > 1) goto end_rename; } retval = -EPERM; @@ -748,7 +748,8 @@ start_up: goto end_rename; } if (!new_bh) { - retval = sysv_add_entry(new_dir,new_name,new_len,&new_bh,&new_de); + retval = sysv_add_entry(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len,&new_bh,&new_de); if (retval) goto end_rename; } @@ -763,13 +764,13 @@ start_up: old_de->inode = 0; new_de->inode = old_inode->i_ino; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - old_dir->i_dirt = 1; + mark_inode_dirty(old_dir); new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; - new_dir->i_dirt = 1; + mark_inode_dirty(new_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; - new_inode->i_dirt = 1; + mark_inode_dirty(new_inode); } mark_buffer_dirty(old_bh, 1); mark_buffer_dirty(new_bh, 1); @@ -777,13 +778,13 @@ start_up: PARENT_INO(dir_bh->b_data) = new_dir->i_ino; mark_buffer_dirty(dir_bh, 1); old_dir->i_nlink--; - old_dir->i_dirt = 1; + mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; - new_inode->i_dirt = 1; + mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; - new_dir->i_dirt = 1; + mark_inode_dirty(new_dir); } } retval = 0; @@ -807,8 +808,8 @@ end_rename: * the same device that races occur: many renames can happen at once, as long * as they are on different partitions. */ -int sysv_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len) +int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, + struct inode * new_dir, struct dentry * new_dentry) { static struct wait_queue * wait = NULL; static int lock = 0; @@ -817,8 +818,8 @@ int sysv_rename(struct inode * old_dir, const char * old_name, int old_len, while (lock) sleep_on(&wait); lock = 1; - result = do_sysv_rename(old_dir, old_name, old_len, - new_dir, new_name, new_len); + result = do_sysv_rename(old_dir, old_dentry, + new_dir, new_dentry); lock = 0; wake_up(&wait); return result; diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c index 4e8a5e349..d76c3fa66 100644 --- a/fs/sysv/symlink.c +++ b/fs/sysv/symlink.c @@ -21,6 +21,7 @@ #include <asm/uaccess.h> static int sysv_readlink(struct inode *, char *, int); +static struct dentry *sysv_follow_link(struct inode *, struct dentry *); /* * symlinks can't do much... @@ -37,6 +38,7 @@ struct inode_operations sysv_symlink_inode_operations = { NULL, /* mknod */ NULL, /* rename */ sysv_readlink, /* readlink */ + sysv_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -44,6 +46,21 @@ struct inode_operations sysv_symlink_inode_operations = { NULL /* permission */ }; +static struct dentry *sysv_follow_link(struct inode * inode, struct dentry * base) +{ + struct buffer_head * bh; + + bh = sysv_file_bread(inode, 0, 0); + if (!bh) { + dput(base); + return ERR_PTR(-EIO); + } + UPDATE_ATIME(inode); + base = lookup_dentry(bh->b_data, base, 1); + brelse(bh); + return base; +} + static int sysv_readlink(struct inode * inode, char * buffer, int buflen) { struct buffer_head * bh; @@ -54,7 +71,6 @@ static int sysv_readlink(struct inode * inode, char * buffer, int buflen) if (buflen > inode->i_sb->sv_block_size_1) buflen = inode->i_sb->sv_block_size_1; bh = sysv_file_bread(inode, 0, 0); - iput(inode); if (!bh) return 0; bh_data = bh->b_data; diff --git a/fs/sysv/truncate.c b/fs/sysv/truncate.c index 0eeb10d30..433c39cae 100644 --- a/fs/sysv/truncate.c +++ b/fs/sysv/truncate.c @@ -64,7 +64,7 @@ repeat: continue; } *p = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); brelse(bh); sysv_free_block(sb,block); } @@ -257,12 +257,14 @@ done: static int trunc_all(struct inode * inode) { struct super_block * sb; + char * res; sb = inode->i_sb; + res = (char *)test_bit(I_DIRTY,&inode->i_state); return trunc_direct(inode) - | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt) - | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt) - | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&inode->i_dirt); + | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,res) + | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,res) + | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,res); } @@ -285,5 +287,5 @@ void sysv_truncate(struct inode * inode) schedule(); } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } |