summaryrefslogtreecommitdiffstats
path: root/fs/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysv')
-rw-r--r--fs/sysv/dir.c1
-rw-r--r--fs/sysv/file.c7
-rw-r--r--fs/sysv/ialloc.c11
-rw-r--r--fs/sysv/inode.c15
-rw-r--r--fs/sysv/namei.c81
-rw-r--r--fs/sysv/symlink.c18
-rw-r--r--fs/sysv/truncate.c12
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);
}