aboutsummaryrefslogtreecommitdiffstats
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
parent6307d43c25ee624ae51cd5b56c85f9fa88af3b6a (diff)
downloadkernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.zip
kernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.tar.gz
kernel_samsung_smdk4412-d4322cd694ca73be92c2b6f8d96226ba4734bd6a.tar.bz2
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>
-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
-rw-r--r--include/linux/fs.h22
-rw-r--r--include/linux/posix_acl.h2
-rw-r--r--include/linux/security.h23
-rw-r--r--include/linux/xattr.h6
-rw-r--r--security/security.c37
15 files changed, 204 insertions, 50 deletions
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index ca393ae..c01b4d4 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 4963313..2a5bd7e 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 d73c37f..bd24132 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 ad47500..4581644 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 24a363b..775f200 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 06eacf3..74e150c 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 aac3d3d..3194ed3 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 b0fb8a2..dc261b5 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 16bda6c..e15ff9d 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 b1cf6bf..365a071 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);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 212ea7b..f74b004 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1726,6 +1726,19 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
}
/**
+ * set_nlink - directly set an inode's link count
+ * @inode: inode
+ * @nlink: new nlink (should be non-zero)
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink.
+ */
+static inline void set_nlink(struct inode *inode, unsigned int nlink)
+{
+ inode->i_nlink = nlink;
+}
+
+/**
* inc_nlink - directly increment an inode's link count
* @inode: inode
*
@@ -1824,6 +1837,8 @@ struct file_system_type {
struct lock_class_key i_alloc_sem_key;
};
+#define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
+
extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
void *data, int (*fill_super)(struct super_block *, void *, int));
extern struct dentry *mount_bdev(struct file_system_type *fs_type,
@@ -2203,6 +2218,11 @@ static inline bool execute_ok(struct inode *inode)
return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);
}
+static inline struct inode *file_inode(struct file *f)
+{
+ return f->f_path.dentry->d_inode;
+}
+
extern int get_write_access(struct inode *);
extern int deny_write_access(struct file *);
static inline void put_write_access(struct inode * inode)
@@ -2212,7 +2232,7 @@ static inline void put_write_access(struct inode * inode)
static inline void allow_write_access(struct file *file)
{
if (file)
- atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
+ atomic_inc(&file_inode(file)->i_writecount);
}
#ifdef CONFIG_IMA
static inline void i_readcount_dec(struct inode *inode)
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 54211c1..0ae0e4a 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -80,6 +80,8 @@ extern struct posix_acl *posix_acl_from_mode(mode_t, gfp_t);
extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
extern int posix_acl_create_masq(struct posix_acl *, mode_t *);
extern int posix_acl_chmod_masq(struct posix_acl *, mode_t);
+extern int posix_acl_create(struct posix_acl **, gfp_t, mode_t *);
+extern int posix_acl_chmod(struct posix_acl **, gfp_t, mode_t);
extern struct posix_acl *get_posix_acl(struct inode *, int);
extern int set_posix_acl(struct inode *, int, struct posix_acl *);
diff --git a/include/linux/security.h b/include/linux/security.h
index 8388914..79b8b7d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -36,6 +36,7 @@
#include <linux/key.h>
#include <linux/xfrm.h>
#include <linux/slab.h>
+#include <linux/xattr.h>
#include <net/flow.h>
/* Maximum number of letters for an LSM name string */
@@ -147,6 +148,10 @@ extern int mmap_min_addr_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
+/* security_inode_init_security callback function to write xattrs */
+typedef int (*initxattrs) (struct inode *inode,
+ const struct xattr *xattr_array, void *fs_data);
+
#ifdef CONFIG_SECURITY
struct security_mnt_opts {
@@ -1713,8 +1718,11 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
int security_inode_alloc(struct inode *inode);
void security_inode_free(struct inode *inode);
int security_inode_init_security(struct inode *inode, struct inode *dir,
- const struct qstr *qstr, char **name,
- void **value, size_t *len);
+ const struct qstr *qstr, char **name,
+ void **value, size_t *len);
+int security_new_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr,
+ initxattrs initxattrs, void *fs_data);
int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry);
@@ -2068,7 +2076,16 @@ static inline int security_inode_init_security(struct inode *inode,
void **value,
size_t *len)
{
- return -EOPNOTSUPP;
+ return 0;
+}
+
+static inline int security_new_inode_init_security(struct inode *inode,
+ struct inode *dir,
+ const struct qstr *qstr,
+ initxattrs initxattrs,
+ void *fs_data)
+{
+ return 0;
}
static inline int security_inode_create(struct inode *dir,
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index aed54c5..7a37866 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -67,6 +67,12 @@ struct xattr_handler {
size_t size, int flags, int handler_flags);
};
+struct xattr {
+ char *name;
+ void *value;
+ size_t value_len;
+};
+
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
diff --git a/security/security.c b/security/security.c
index 6db15aa..837d3d3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -18,6 +18,8 @@
#include <linux/security.h>
#include <linux/ima.h>
+#define MAX_LSM_XATTR 1
+
/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
@@ -359,8 +361,8 @@ void security_inode_free(struct inode *inode)
}
int security_inode_init_security(struct inode *inode, struct inode *dir,
- const struct qstr *qstr, char **name,
- void **value, size_t *len)
+ const struct qstr *qstr, char **name,
+ void **value, size_t *len)
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
@@ -369,6 +371,37 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
}
EXPORT_SYMBOL(security_inode_init_security);
+int security_new_inode_init_security(struct inode *inode, struct inode *dir,
+ const struct qstr *qstr,
+ const initxattrs initxattrs, void *fs_data)
+{
+ struct xattr new_xattrs[MAX_LSM_XATTR + 1];
+ struct xattr *lsm_xattr;
+ int ret;
+
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
+ memset(new_xattrs, 0, sizeof new_xattrs);
+ if (!initxattrs)
+ return security_ops->inode_init_security(inode, dir, qstr,
+ NULL, NULL, NULL);
+ lsm_xattr = new_xattrs;
+ ret = security_ops->inode_init_security(inode, dir, qstr,
+ &lsm_xattr->name,
+ &lsm_xattr->value,
+ &lsm_xattr->value_len);
+ if (ret)
+ goto out;
+ ret = initxattrs(inode, new_xattrs, fs_data);
+out:
+ kfree(lsm_xattr->name);
+ kfree(lsm_xattr->value);
+
+ return (ret == -EOPNOTSUPP) ? 0 : ret;
+}
+EXPORT_SYMBOL(security_new_inode_init_security);
+
#ifdef CONFIG_SECURITY_PATH
int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
unsigned int dev)