diff options
author | arter97 <qkrwngud825@gmail.com> | 2014-01-07 14:29:31 +0900 |
---|---|---|
committer | rogersb11 <brettrogers11@gmail.com> | 2016-02-13 21:04:16 -0500 |
commit | d4322cd694ca73be92c2b6f8d96226ba4734bd6a (patch) | |
tree | 80f46e6ddded2943b30961b2f7457f890d264f70 /fs | |
parent | 6307d43c25ee624ae51cd5b56c85f9fa88af3b6a (diff) | |
download | kernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.tar.gz kernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.tar.bz2 kernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.zip |
f2fs: support 3.0
Initial backporting done by nowcomputing,
(https://github.com/nowcomputing/f2fs-backports.git)
Additional patches required by upstream jaegeuk/f2fs.git/linux-3.4 done by arter97.
Change-Id: Ibbd3a608857338482f974fa4b1a8d3c02c267d9f
Signed-off-by: Park Ju Hyung <qkrwngud825@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/f2fs/acl.c | 35 | ||||
-rw-r--r-- | fs/f2fs/acl.h | 3 | ||||
-rw-r--r-- | fs/f2fs/data.c | 4 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 7 | ||||
-rw-r--r-- | fs/f2fs/file.c | 29 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 33 | ||||
-rw-r--r-- | fs/f2fs/super.c | 13 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | fs/posix_acl.c | 36 |
10 files changed, 120 insertions, 44 deletions
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index ca393aeb761..c01b4d41820 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -149,7 +149,7 @@ fail: return ERR_PTR(-EINVAL); } -struct posix_acl *f2fs_get_acl(struct inode *inode, int type) +static struct posix_acl *f2fs_get_acl(struct inode *inode, int type) { struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; @@ -189,6 +189,28 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) return acl; } +int f2fs_check_acl(struct inode *inode, int mask, unsigned int flags) +{ + int error = -EAGAIN; + + if (flags & IPERM_FLAG_RCU) { + if (!negative_cached_acl(inode, ACL_TYPE_ACCESS)) + error = -ECHILD; + } else { + struct posix_acl *acl; + + acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + error = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + } + } + + return error; +} + static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl, struct page *ipage) { @@ -208,9 +230,11 @@ static int f2fs_set_acl(struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_equiv_mode(acl, &inode->i_mode); + mode_t mode = inode->i_mode; + error = posix_acl_equiv_mode(acl, &mode); if (error < 0) return error; + inode->i_mode = mode; set_acl_inode(fi, inode->i_mode); if (error == 0) acl = NULL; @@ -264,14 +288,17 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage) if (!test_opt(sbi, POSIX_ACL) || !acl) goto cleanup; + mode_t mode = inode->i_mode; + if (S_ISDIR(inode->i_mode)) { error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage); if (error) goto cleanup; } - error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode); + error = posix_acl_create(&acl, GFP_KERNEL, &mode); if (error < 0) return error; + inode->i_mode = mode; if (error > 0) error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage); cleanup: @@ -284,7 +311,7 @@ int f2fs_acl_chmod(struct inode *inode) struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); struct posix_acl *acl; int error; - umode_t mode = get_inode_mode(inode); + mode_t mode = get_inode_mode(inode); if (!test_opt(sbi, POSIX_ACL)) return 0; diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h index 49633131e03..2a5bd7e958c 100644 --- a/fs/f2fs/acl.h +++ b/fs/f2fs/acl.h @@ -36,12 +36,11 @@ struct f2fs_acl_header { #ifdef CONFIG_F2FS_FS_POSIX_ACL -extern struct posix_acl *f2fs_get_acl(struct inode *, int); +extern int f2fs_check_acl(struct inode *inode, int mask, unsigned int flags); extern int f2fs_acl_chmod(struct inode *); extern int f2fs_init_acl(struct inode *, struct inode *, struct page *); #else #define f2fs_check_acl NULL -#define f2fs_get_acl NULL #define f2fs_set_acl NULL static inline int f2fs_acl_chmod(struct inode *inode) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d73c37fe0a2..bd241326cd7 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1028,8 +1028,8 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, if (check_direct_IO(inode, rw, iov, offset, nr_segs)) return 0; - return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, - get_data_block); + return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, get_data_block, NULL); } static void f2fs_invalidate_data_page(struct page *page, unsigned long offset) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ad47500e19f..4581644ced4 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1011,15 +1011,10 @@ static inline int f2fs_readonly(struct super_block *sb) return sb->s_flags & MS_RDONLY; } -static inline struct inode *file_inode(struct file *f) -{ - return f->f_path.dentry->d_inode; -} - /* * file.c */ -int f2fs_sync_file(struct file *, loff_t, loff_t, int); +int f2fs_sync_file(struct file *, int); void truncate_data_blocks(struct dnode_of_data *); int truncate_blocks(struct inode *, u64); void f2fs_truncate(struct inode *); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 24a363b7ddd..775f2001288 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -19,6 +19,7 @@ #include <linux/compat.h> #include <linux/uaccess.h> #include <linux/mount.h> +#include <linux/dcache.h> #include "f2fs.h" #include "node.h" @@ -91,7 +92,17 @@ static int get_parent_ino(struct inode *inode, nid_t *pino) struct dentry *dentry; inode = igrab(inode); - dentry = d_find_any_alias(inode); + + /* Alex - the following is equivalent to: dentry = d_find_any_alias(inode); */ + dentry = NULL; + spin_lock(&inode->i_lock); + if (!list_empty(&inode->i_dentry)) { + dentry = list_first_entry(&inode->i_dentry, + struct dentry, d_alias); + dget(dentry); + } + spin_unlock(&inode->i_lock); + iput(inode); if (!dentry) return 0; @@ -106,7 +117,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino) return 1; } -int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +int f2fs_sync_file(struct file *file, int datasync) { struct inode *inode = file->f_mapping->host; struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); @@ -122,17 +133,10 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) return 0; trace_f2fs_sync_file_enter(inode); - ret = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (ret) { - trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); - return ret; - } /* guarantee free sections for fsync */ f2fs_balance_fs(sbi); - mutex_lock(&inode->i_mutex); - /* * Both of fdatasync() and fsync() are able to be recovered from * sudden-power-off. @@ -178,7 +182,6 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); } out: - mutex_unlock(&inode->i_mutex); trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); return ret; } @@ -394,7 +397,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) const struct inode_operations f2fs_file_inode_operations = { .getattr = f2fs_getattr, .setattr = f2fs_setattr, - .get_acl = f2fs_get_acl, + .check_acl = f2fs_check_acl, #ifdef CONFIG_F2FS_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, @@ -598,7 +601,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int oldflags; - ret = mnt_want_write_file(filp); + ret = mnt_want_write(filp->f_path.mnt); if (ret) return ret; @@ -635,7 +638,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); out: - mnt_drop_write_file(filp); + mnt_drop_write(filp->f_path.mnt); return ret; } default: diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 06eacf39a6a..74e150c1e0f 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -108,7 +108,7 @@ static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode, } } -static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, +static int f2fs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { struct super_block *sb = dir->i_sb; @@ -155,10 +155,16 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; - struct super_block *sb = dir->i_sb; - struct f2fs_sb_info *sbi = F2FS_SB(sb); + struct super_block *sb; + struct f2fs_sb_info *sbi; int err; + if (inode->i_nlink >= F2FS_LINK_MAX) + return -EMLINK; + + sb = dir->i_sb; + sbi = F2FS_SB(sb); + f2fs_balance_fs(sbi); inode->i_ctime = CURRENT_TIME; @@ -285,12 +291,17 @@ out: return err; } -static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct f2fs_sb_info *sbi; struct inode *inode; int err; + if (dir->i_nlink >= F2FS_LINK_MAX) + return -EMLINK; + + sbi = F2FS_SB(dir->i_sb); + f2fs_balance_fs(sbi); inode = f2fs_new_inode(dir, S_IFDIR | mode); @@ -335,7 +346,7 @@ static int f2fs_rmdir(struct inode *dir, struct dentry *dentry) } static int f2fs_mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t rdev) + int mode, dev_t rdev) { struct super_block *sb = dir->i_sb; struct f2fs_sb_info *sbi = F2FS_SB(sb); @@ -439,6 +450,12 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, update_inode_page(old_inode); update_inode_page(new_inode); } else { + if (old_dir_entry) { + err = -EMLINK; + if (new_dir->i_nlink >= F2FS_LINK_MAX) + goto out_dir; + } + err = f2fs_add_link(new_dentry, old_inode); if (err) goto out_dir; @@ -497,7 +514,7 @@ const struct inode_operations f2fs_dir_inode_operations = { .rename = f2fs_rename, .getattr = f2fs_getattr, .setattr = f2fs_setattr, - .get_acl = f2fs_get_acl, + .check_acl = f2fs_check_acl, #ifdef CONFIG_F2FS_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, @@ -523,7 +540,7 @@ const struct inode_operations f2fs_symlink_inode_operations = { const struct inode_operations f2fs_special_inode_operations = { .getattr = f2fs_getattr, .setattr = f2fs_setattr, - .get_acl = f2fs_get_acl, + .check_acl = f2fs_check_acl, #ifdef CONFIG_F2FS_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index aac3d3da0e1..3194ed3ee27 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -489,11 +489,11 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static int f2fs_show_options(struct seq_file *seq, struct dentry *root) +static int f2fs_show_options(struct seq_file *seq, struct vfsmount *vfs) { - struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); + struct f2fs_sb_info *sbi = F2FS_SB(vfs->mnt_sb); - if (!(root->d_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC)) + if (!(vfs->mnt_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC)) seq_printf(seq, ",background_gc=%s", "on"); else seq_printf(seq, ",background_gc=%s", "off"); @@ -865,7 +865,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_sb_buf; sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); - sb->s_max_links = F2FS_LINK_MAX; get_random_bytes(&sbi->s_next_generation, sizeof(u32)); sb->s_op = &f2fs_sops; @@ -975,7 +974,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_root_inode; } - sb->s_root = d_make_root(root); /* allocate root dentry */ + sb->s_root = d_alloc_root(root); /* allocate root dentry */ if (!sb->s_root) { err = -ENOMEM; goto free_root_inode; @@ -1036,8 +1035,7 @@ fail: free_gc: stop_gc_thread(sbi); free_root_inode: - dput(sb->s_root); - sb->s_root = NULL; + iput(root); free_node_inode: iput(sbi->node_inode); free_nm: @@ -1069,6 +1067,7 @@ static struct file_system_type f2fs_fs_type = { .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; +MODULE_ALIAS_FS("f2fs"); static int __init init_inodecache(void) { diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index b0fb8a27f3d..dc261b54531 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -176,7 +176,7 @@ static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, int f2fs_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, struct page *ipage) { - return security_inode_init_security(inode, dir, qstr, + return security_new_inode_init_security(inode, dir, qstr, &f2fs_initxattrs, ipage); } #endif diff --git a/fs/namei.c b/fs/namei.c index 16bda6cd602..e15ff9d0c08 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -355,7 +355,7 @@ int get_write_access(struct inode * inode) int deny_write_access(struct file * file) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file_inode(file); spin_lock(&inode->i_lock); if (atomic_read(&inode->i_writecount) > 0) { diff --git a/fs/posix_acl.c b/fs/posix_acl.c index b1cf6bf4b41..365a0712da6 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -386,3 +386,39 @@ posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode) return 0; } + +int +posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p) +{ + struct posix_acl *clone = posix_acl_clone(*acl, gfp); + int err = -ENOMEM; + if (clone) { + err = posix_acl_create_masq(clone, mode_p); + if (err < 0) { + posix_acl_release(clone); + clone = NULL; + } + } + posix_acl_release(*acl); + *acl = clone; + return err; +} +EXPORT_SYMBOL(posix_acl_create); + +int +posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, mode_t mode) +{ + struct posix_acl *clone = posix_acl_clone(*acl, gfp); + int err = -ENOMEM; + if (clone) { + err = posix_acl_chmod_masq(clone, mode); + if (err) { + posix_acl_release(clone); + clone = NULL; + } + } + posix_acl_release(*acl); + *acl = clone; + return err; +} +EXPORT_SYMBOL(posix_acl_chmod); |