diff options
Diffstat (limited to 'fs/jfs')
-rw-r--r-- | fs/jfs/file.c | 5 | ||||
-rw-r--r-- | fs/jfs/inode.c | 20 | ||||
-rw-r--r-- | fs/jfs/ioctl.c | 31 | ||||
-rw-r--r-- | fs/jfs/jfs_dinode.h | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_inode.h | 6 | ||||
-rw-r--r-- | fs/jfs/namei.c | 39 | ||||
-rw-r--r-- | fs/jfs/super.c | 15 |
7 files changed, 80 insertions, 38 deletions
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 87eb93694af7..7f6063acaa3b 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -112,5 +112,8 @@ const struct file_operations jfs_file_operations = { .splice_write = generic_file_splice_write, .fsync = jfs_fsync, .release = jfs_release, - .ioctl = jfs_ioctl, + .unlocked_ioctl = jfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = jfs_compat_ioctl, +#endif }; diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 4672013802e1..210339784b56 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -31,11 +31,21 @@ #include "jfs_debug.h" -void jfs_read_inode(struct inode *inode) +struct inode *jfs_iget(struct super_block *sb, unsigned long ino) { - if (diRead(inode)) { - make_bad_inode(inode); - return; + struct inode *inode; + int ret; + + inode = iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + if (!(inode->i_state & I_NEW)) + return inode; + + ret = diRead(inode); + if (ret < 0) { + iget_failed(inode); + return ERR_PTR(ret); } if (S_ISREG(inode->i_mode)) { @@ -55,6 +65,8 @@ void jfs_read_inode(struct inode *inode) inode->i_op = &jfs_file_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); } + unlock_new_inode(inode); + return inode; } /* diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index dfda12a073e1..a1f8e375ad21 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c @@ -51,9 +51,9 @@ static long jfs_map_ext2(unsigned long flags, int from) } -int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, - unsigned long arg) +long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + struct inode *inode = filp->f_dentry->d_inode; struct jfs_inode_info *jfs_inode = JFS_IP(inode); unsigned int flags; @@ -82,6 +82,10 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, /* Is it quota file? Do not allow user to mess with it */ if (IS_NOQUOTA(inode)) return -EPERM; + + /* Lock against other parallel changes of flags */ + mutex_lock(&inode->i_mutex); + jfs_get_inode_flags(jfs_inode); oldflags = jfs_inode->mode2; @@ -92,8 +96,10 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, if ((oldflags & JFS_IMMUTABLE_FL) || ((flags ^ oldflags) & (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) { - if (!capable(CAP_LINUX_IMMUTABLE)) + if (!capable(CAP_LINUX_IMMUTABLE)) { + mutex_unlock(&inode->i_mutex); return -EPERM; + } } flags = flags & JFS_FL_USER_MODIFIABLE; @@ -101,6 +107,7 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, jfs_inode->mode2 = flags; jfs_set_inode_flags(inode); + mutex_unlock(&inode->i_mutex); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); return 0; @@ -110,3 +117,21 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, } } +#ifdef CONFIG_COMPAT +long jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + /* While these ioctl numbers defined with 'long' and have different + * numbers than the 64bit ABI, + * the actual implementation only deals with ints and is compatible. + */ + switch (cmd) { + case JFS_IOC_GETFLAGS32: + cmd = JFS_IOC_GETFLAGS; + break; + case JFS_IOC_SETFLAGS32: + cmd = JFS_IOC_SETFLAGS; + break; + } + return jfs_ioctl(filp, cmd, arg); +} +#endif diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h index c387540d3425..395c4c0d0f06 100644 --- a/fs/jfs/jfs_dinode.h +++ b/fs/jfs/jfs_dinode.h @@ -170,5 +170,7 @@ struct dinode { #define JFS_IOC_GETFLAGS _IOR('f', 1, long) #define JFS_IOC_SETFLAGS _IOW('f', 2, long) +#define JFS_IOC_GETFLAGS32 _IOR('f', 1, int) +#define JFS_IOC_SETFLAGS32 _IOW('f', 2, int) #endif /*_H_JFS_DINODE */ diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 8e2cf2cde185..adb2fafcc544 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h @@ -22,9 +22,9 @@ struct fid; extern struct inode *ialloc(struct inode *, umode_t); extern int jfs_fsync(struct file *, struct dentry *, int); -extern int jfs_ioctl(struct inode *, struct file *, - unsigned int, unsigned long); -extern void jfs_read_inode(struct inode *); +extern long jfs_ioctl(struct file *, unsigned int, unsigned long); +extern long jfs_compat_ioctl(struct file *, unsigned int, unsigned long); +extern struct inode *jfs_iget(struct super_block *, unsigned long); extern int jfs_commit_inode(struct inode *, int); extern int jfs_write_inode(struct inode*, int); extern void jfs_delete_inode(struct inode *); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index f8718de3505e..0ba6778edaa2 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1462,12 +1462,10 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc } } - ip = iget(dip->i_sb, inum); - if (ip == NULL || is_bad_inode(ip)) { + ip = jfs_iget(dip->i_sb, inum); + if (IS_ERR(ip)) { jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum); - if (ip) - iput(ip); - return ERR_PTR(-EACCES); + return ERR_CAST(ip); } dentry = d_splice_alias(ip, dentry); @@ -1485,12 +1483,11 @@ static struct inode *jfs_nfs_get_inode(struct super_block *sb, if (ino == 0) return ERR_PTR(-ESTALE); - inode = iget(sb, ino); - if (inode == NULL) - return ERR_PTR(-ENOMEM); + inode = jfs_iget(sb, ino); + if (IS_ERR(inode)) + return ERR_CAST(inode); - if (is_bad_inode(inode) || - (generation && inode->i_generation != generation)) { + if (generation && inode->i_generation != generation) { iput(inode); return ERR_PTR(-ESTALE); } @@ -1521,17 +1518,14 @@ struct dentry *jfs_get_parent(struct dentry *dentry) parent_ino = le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot); - inode = iget(sb, parent_ino); - if (inode) { - if (is_bad_inode(inode)) { + inode = jfs_iget(sb, parent_ino); + if (IS_ERR(inode)) { + parent = ERR_CAST(inode); + } else { + parent = d_alloc_anon(inode); + if (!parent) { + parent = ERR_PTR(-ENOMEM); iput(inode); - parent = ERR_PTR(-EACCES); - } else { - parent = d_alloc_anon(inode); - if (!parent) { - parent = ERR_PTR(-ENOMEM); - iput(inode); - } } } @@ -1562,7 +1556,10 @@ const struct file_operations jfs_dir_operations = { .read = generic_read_dir, .readdir = jfs_readdir, .fsync = jfs_fsync, - .ioctl = jfs_ioctl, + .unlocked_ioctl = jfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = jfs_compat_ioctl, +#endif }; static int jfs_ci_hash(struct dentry *dir, struct qstr *this) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 70a14001c98f..50ea65451732 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -414,7 +414,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; int rc; s64 newLVSize = 0; - int flag; + int flag, ret = -EINVAL; jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags); @@ -461,8 +461,10 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) * Initialize direct-mapping inode/address-space */ inode = new_inode(sb); - if (inode == NULL) + if (inode == NULL) { + ret = -ENOMEM; goto out_kfree; + } inode->i_ino = 0; inode->i_nlink = 1; inode->i_size = sb->s_bdev->bd_inode->i_size; @@ -494,9 +496,11 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_magic = JFS_SUPER_MAGIC; - inode = iget(sb, ROOT_I); - if (!inode || is_bad_inode(inode)) + inode = jfs_iget(sb, ROOT_I); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); goto out_no_root; + } sb->s_root = d_alloc_root(inode); if (!sb->s_root) goto out_no_root; @@ -536,7 +540,7 @@ out_kfree: if (sbi->nls_tab) unload_nls(sbi->nls_tab); kfree(sbi); - return -EINVAL; + return ret; } static void jfs_write_super_lockfs(struct super_block *sb) @@ -726,7 +730,6 @@ out: static const struct super_operations jfs_super_operations = { .alloc_inode = jfs_alloc_inode, .destroy_inode = jfs_destroy_inode, - .read_inode = jfs_read_inode, .dirty_inode = jfs_dirty_inode, .write_inode = jfs_write_inode, .delete_inode = jfs_delete_inode, |