aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorarter97 <qkrwngud825@gmail.com>2014-01-07 14:29:31 +0900
committerrogersb11 <brettrogers11@gmail.com>2016-02-13 21:04:16 -0500
commitd4322cd694ca73be92c2b6f8d96226ba4734bd6a (patch)
tree80f46e6ddded2943b30961b2f7457f890d264f70 /fs
parent6307d43c25ee624ae51cd5b56c85f9fa88af3b6a (diff)
downloadkernel_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.c35
-rw-r--r--fs/f2fs/acl.h3
-rw-r--r--fs/f2fs/data.c4
-rw-r--r--fs/f2fs/f2fs.h7
-rw-r--r--fs/f2fs/file.c29
-rw-r--r--fs/f2fs/namei.c33
-rw-r--r--fs/f2fs/super.c13
-rw-r--r--fs/f2fs/xattr.c2
-rw-r--r--fs/namei.c2
-rw-r--r--fs/posix_acl.c36
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);