From: Vyacheslav Dubeyko <[email protected]>
Subject: [RFC][STEP 1][PATCH v2 15/17] nilfs2: integrate xattrs support 
functionality into driver

This patch integrates xattrs support functionality into
file system driver.

Signed-off-by: Vyacheslav Dubeyko <[email protected]>
CC: Ryusuke Konishi <[email protected]>
---
 fs/nilfs2/Kconfig     |   38 ++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/Makefile    |    6 +++++-
 fs/nilfs2/bmap.c      |    1 +
 fs/nilfs2/file.c      |    7 +++++++
 fs/nilfs2/inode.c     |   22 ++++++++--------------
 fs/nilfs2/namei.c     |   42 ++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/nilfs.h     |   24 ++++--------------------
 fs/nilfs2/segment.c   |   22 ++++++++++++++++++++++
 fs/nilfs2/super.c     |   20 +++++++++++++++++---
 fs/nilfs2/the_nilfs.c |   19 +++++++++++++++++++
 10 files changed, 163 insertions(+), 38 deletions(-)

diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
index 80da8eb..dcd420e 100644
--- a/fs/nilfs2/Kconfig
+++ b/fs/nilfs2/Kconfig
@@ -22,3 +22,41 @@ config NILFS2_FS
 
          To compile this file system support as a module, choose M here: the
          module will be called nilfs2.  If unsure, say N.
+
+config NILFS2_FS_DEBUG
+       bool "NILFS2 debugging"
+       depends on NILFS2_FS
+       help
+         This option enables additional pre-condition and post-condition
+         checking in functions. It can enable debug output too. The main
+         goal of this option is providing environment for debugging code
+         of NILFS2 driver and excluding debug checking and output from
+         end-users' kernel build.
+
+         If you are going to debug NILFS2 driver then choose Y here.
+         If unsure, say N.
+
+config NILFS2_FS_POSIX_ACL
+       bool "NILFS2 POSIX Access Control Lists"
+       depends on NILFS2_FS
+       select FS_POSIX_ACL
+       help
+         POSIX Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the POSIX ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N
+
+config NILFS2_FS_SECURITY
+       bool "NILFS2 Security Labels"
+       depends on NILFS2_FS
+       help
+         Security labels support alternative access control models
+         implemented by security modules like SELinux.  This option
+         enables an extended attribute handler for file security
+         labels in the NILFS2 filesystem.
+
+         If you are not using a security module that requires using
+         extended attributes for file security labels, say N.
diff --git a/fs/nilfs2/Makefile b/fs/nilfs2/Makefile
index 85c9873..8e56dbd 100644
--- a/fs/nilfs2/Makefile
+++ b/fs/nilfs2/Makefile
@@ -2,4 +2,8 @@ obj-$(CONFIG_NILFS2_FS) += nilfs2.o
 nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \
        btnode.o bmap.o btree.o direct.o dat.o recovery.o \
        the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \
-       ifile.o alloc.o gcinode.o ioctl.o
+       ifile.o alloc.o gcinode.o ioctl.o \
+       xafile.o xattr.o xattr_user.o xattr_trusted.o
+
+nilfs2-$(CONFIG_NILFS2_FS_POSIX_ACL)   += acl.o
+nilfs2-$(CONFIG_NILFS2_FS_SECURITY)    += xattr_security.o
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index aadbd0b..7ab515f 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -499,6 +499,7 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct 
nilfs_inode *raw_inode)
                break;
        case NILFS_CPFILE_INO:
        case NILFS_SUFILE_INO:
+       case NILFS_XATTR_INO:
                bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
                bmap->b_last_allocated_key = 0;
                bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 08fdb77..7592e37 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -26,6 +26,8 @@
 #include <linux/writeback.h>
 #include "nilfs.h"
 #include "segment.h"
+#include "xattr.h"
+#include "acl.h"
 
 int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
@@ -169,6 +171,11 @@ const struct file_operations nilfs_file_operations = {
 const struct inode_operations nilfs_file_inode_operations = {
        .setattr        = nilfs_setattr,
        .permission     = nilfs_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = nilfs_listxattr,
+       .removexattr    = generic_removexattr,
+       .get_acl        = nilfs_get_acl,
        .fiemap         = nilfs_fiemap,
 };
 
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 7e350c5..690072b 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -33,6 +33,8 @@
 #include "mdt.h"
 #include "cpfile.h"
 #include "ifile.h"
+#include "xattr.h"
+#include "acl.h"
 
 /**
  * struct nilfs_iget_args - arguments used during comparison between inodes
@@ -386,8 +388,6 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t 
mode)
        ii->i_flags = nilfs_mask_flags(
                mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
 
-       /* ii->i_file_acl = 0; */
-       /* ii->i_dir_acl = 0; */
        ii->i_dir_start_lookup = 0;
        nilfs_set_inode_flags(inode);
        spin_lock(&nilfs->ns_next_gen_lock);
@@ -395,15 +395,10 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t 
mode)
        spin_unlock(&nilfs->ns_next_gen_lock);
        insert_inode_hash(inode);
 
-       err = nilfs_init_acl(inode, dir);
-       if (unlikely(err))
-               goto failed_acl; /* never occur. When supporting
-                                   nilfs_init_acl(), proper cancellation of
-                                   above jobs should be considered */
+       ii->i_xattr = NILFS_INVALID_XANODE;
 
        return inode;
 
- failed_acl:
  failed_bmap:
        clear_nlink(inode);
        iput(inode);  /* raw_inode will be deleted through
@@ -460,14 +455,12 @@ int nilfs_read_inode_common(struct inode *inode,
 
        inode->i_blocks = le64_to_cpu(raw_inode->i_blocks);
        ii->i_flags = le32_to_cpu(raw_inode->i_flags);
-#if 0
-       ii->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-       ii->i_dir_acl = S_ISREG(inode->i_mode) ?
-               0 : le32_to_cpu(raw_inode->i_dir_acl);
-#endif
+
        ii->i_dir_start_lookup = 0;
        inode->i_generation = le32_to_cpu(raw_inode->i_generation);
 
+       ii->i_xattr = le64_to_cpu(raw_inode->i_xattr);
+
        if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
            S_ISLNK(inode->i_mode)) {
                err = nilfs_bmap_read(ii->i_bmap, raw_inode);
@@ -655,7 +648,8 @@ void nilfs_write_inode_common(struct inode *inode,
                raw_inode->i_pad = 0;
                memset((void *)raw_inode + sizeof(*raw_inode), 0,
                       nilfs->ns_inode_size - sizeof(*raw_inode));
-       }
+       } else
+               raw_inode->i_xattr = cpu_to_le64(ii->i_xattr);
 
        if (has_bmap)
                nilfs_bmap_write(ii->i_bmap, raw_inode);
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 9de78f0..dc40a99 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -41,6 +41,8 @@
 #include <linux/pagemap.h>
 #include "nilfs.h"
 #include "export.h"
+#include "xattr.h"
+#include "acl.h"
 
 #define NILFS_FID_SIZE_NON_CONNECTABLE \
        (offsetof(struct nilfs_fid, parent_gen) / 4)
@@ -97,12 +99,17 @@ static int nilfs_create(struct inode *dir, struct dentry 
*dentry, umode_t mode,
        inode = nilfs_new_inode(dir, mode);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
+               err = nilfs_init_inode_security(inode, dir, &dentry->d_name);
+               if (unlikely(err))
+                       goto out;
                inode->i_op = &nilfs_file_inode_operations;
                inode->i_fop = &nilfs_file_operations;
                inode->i_mapping->a_ops = &nilfs_aops;
                nilfs_mark_inode_dirty(inode);
                err = nilfs_add_nondir(dentry, inode);
        }
+
+out:
        if (!err)
                err = nilfs_transaction_commit(dir->i_sb);
        else
@@ -127,10 +134,15 @@ nilfs_mknod(struct inode *dir, struct dentry *dentry, 
umode_t mode, dev_t rdev)
        inode = nilfs_new_inode(dir, mode);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
+               err = nilfs_init_inode_security(inode, dir, &dentry->d_name);
+               if (unlikely(err))
+                       goto out;
                init_special_inode(inode, inode->i_mode, rdev);
                nilfs_mark_inode_dirty(inode);
                err = nilfs_add_nondir(dentry, inode);
        }
+
+out:
        if (!err)
                err = nilfs_transaction_commit(dir->i_sb);
        else
@@ -160,6 +172,10 @@ static int nilfs_symlink(struct inode *dir, struct dentry 
*dentry,
        if (IS_ERR(inode))
                goto out;
 
+       err = nilfs_init_inode_security(inode, dir, &dentry->d_name);
+       if (unlikely(err))
+               goto out;
+
        /* slow symlink */
        inode->i_op = &nilfs_symlink_inode_operations;
        inode->i_mapping->a_ops = &nilfs_aops;
@@ -227,6 +243,10 @@ static int nilfs_mkdir(struct inode *dir, struct dentry 
*dentry, umode_t mode)
        if (IS_ERR(inode))
                goto out_dir;
 
+       err = nilfs_init_inode_security(inode, dir, &dentry->d_name);
+       if (unlikely(err))
+               goto out_dir;
+
        inode->i_op = &nilfs_dir_inode_operations;
        inode->i_fop = &nilfs_dir_operations;
        inode->i_mapping->a_ops = &nilfs_aops;
@@ -285,6 +305,13 @@ static int nilfs_do_unlink(struct inode *dir, struct 
dentry *dentry)
                              inode->i_ino, inode->i_nlink);
                set_nlink(inode, 1);
        }
+
+       if (inode->i_nlink == 1) {
+               err = nilfs_xattr_delete_inode(inode);
+               if (err)
+                       goto out;
+       }
+
        err = nilfs_delete_entry(de, page);
        if (err)
                goto out;
@@ -553,12 +580,22 @@ const struct inode_operations nilfs_dir_inode_operations 
= {
        .rename         = nilfs_rename,
        .setattr        = nilfs_setattr,
        .permission     = nilfs_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = nilfs_listxattr,
+       .removexattr    = generic_removexattr,
+       .get_acl        = nilfs_get_acl,
        .fiemap         = nilfs_fiemap,
 };
 
 const struct inode_operations nilfs_special_inode_operations = {
        .setattr        = nilfs_setattr,
        .permission     = nilfs_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = nilfs_listxattr,
+       .removexattr    = generic_removexattr,
+       .get_acl        = nilfs_get_acl,
 };
 
 const struct inode_operations nilfs_symlink_inode_operations = {
@@ -566,6 +603,11 @@ const struct inode_operations 
nilfs_symlink_inode_operations = {
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
        .permission     = nilfs_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = nilfs_listxattr,
+       .removexattr    = generic_removexattr,
+       .get_acl        = nilfs_get_acl,
 };
 
 const struct export_operations nilfs_export_ops = {
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 3cdacda..c82ba24 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -196,26 +196,6 @@ static inline int nilfs_doing_construction(void)
        return nilfs_test_transaction_flag(NILFS_TI_WRITER);
 }
 
-/*
- * function prototype
- */
-#ifdef CONFIG_NILFS_POSIX_ACL
-#error "NILFS: not yet supported POSIX ACL"
-extern int nilfs_acl_chmod(struct inode *);
-extern int nilfs_init_acl(struct inode *, struct inode *);
-#else
-static inline int nilfs_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
-
-static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
-{
-       inode->i_mode &= ~current_umask();
-       return 0;
-}
-#endif
-
 #define NILFS_ATIME_DISABLE
 
 /* Flags that should be inherited by new inodes from their parent. */
@@ -235,6 +215,10 @@ static inline __u32 nilfs_mask_flags(umode_t mode, __u32 
flags)
                return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
 }
 
+/*
+ * Function prototypes
+ */
+
 /* dir.c */
 extern int nilfs_add_link(struct dentry *, struct inode *);
 extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 9f6b486..f808934 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -70,6 +70,7 @@ enum {
        NILFS_ST_IFILE,
        NILFS_ST_CPFILE,
        NILFS_ST_SUFILE,
+       NILFS_ST_XAFILE,
        NILFS_ST_DAT,
        NILFS_ST_SR,            /* Super root */
        NILFS_ST_DSYNC,         /* Data sync blocks */
@@ -757,6 +758,10 @@ static int nilfs_test_metadata_dirty(struct the_nilfs 
*nilfs,
                ret++;
        if (nilfs_mdt_fetch_dirty(nilfs->ns_sufile))
                ret++;
+       if (nilfs_has_xafile(nilfs)) {
+               if (nilfs_mdt_fetch_dirty(nilfs->ns_xafile))
+                       ret++;
+       }
        if ((ret || nilfs_doing_gc()) && nilfs_mdt_fetch_dirty(nilfs->ns_dat))
                ret++;
        return ret;
@@ -793,6 +798,8 @@ static void nilfs_segctor_clear_metadata_dirty(struct 
nilfs_sc_info *sci)
        nilfs_mdt_clear_dirty(sci->sc_root->ifile);
        nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
        nilfs_mdt_clear_dirty(nilfs->ns_sufile);
+       if (nilfs_has_xafile(nilfs))
+               nilfs_mdt_clear_dirty(nilfs->ns_xafile);
        nilfs_mdt_clear_dirty(nilfs->ns_dat);
 }
 
@@ -909,6 +916,13 @@ static void nilfs_segctor_fill_in_super_root(struct 
nilfs_sc_info *sci,
                                 NILFS_SR_CPFILE_OFFSET(isz), 1);
        nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr +
                                 NILFS_SR_SUFILE_OFFSET(isz), 1);
+       if (nilfs_has_xafile(nilfs)) {
+               nilfs_write_inode_common(nilfs->ns_xafile, (void *)raw_sr +
+                                        NILFS_SR_XAFILE_OFFSET(isz), 1);
+       } else {
+               memset((void *)raw_sr + NILFS_SR_XAFILE_OFFSET(isz), 0,
+                       sizeof(struct nilfs_inode));
+       }
        memset((void *)raw_sr + srsz, 0, nilfs->ns_blocksize - srsz);
 }
 
@@ -1157,6 +1171,14 @@ static int nilfs_segctor_collect_blocks(struct 
nilfs_sc_info *sci, int mode)
                if (unlikely(err))
                        break;
                sci->sc_stage.scnt++;  /* Fall through */
+       case NILFS_ST_XAFILE:
+               if (nilfs_has_xafile(nilfs)) {
+                       err = nilfs_segctor_scan_file(sci, nilfs->ns_xafile,
+                                                       &nilfs_sc_file_ops);
+                       if (unlikely(err))
+                               break;
+               }
+               sci->sc_stage.scnt++;  /* Fall through */
        case NILFS_ST_DAT:
  dat_stage:
                err = nilfs_segctor_scan_file(sci, nilfs->ns_dat,
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 7ac2a12..75b1362 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -61,6 +61,8 @@
 #include "dat.h"
 #include "segment.h"
 #include "segbuf.h"
+#include "xattr.h"
+#include "acl.h"
 
 MODULE_AUTHOR("NTT Corp.");
 MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem "
@@ -486,6 +488,8 @@ static void nilfs_put_super(struct super_block *sb)
                up_write(&nilfs->ns_sem);
        }
 
+       if (nilfs_has_xafile(nilfs))
+               iput(nilfs->ns_xafile);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_dat);
@@ -1071,6 +1075,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int 
silent)
        sb->s_time_gran = 1;
        sb->s_max_links = NILFS_LINK_MAX;
 
+       sb->s_xattr = nilfs_xattr_handlers;
+       if (nilfs_has_xafile(nilfs))
+               set_posix_acl_flag(sb);
+       else
+               sb->s_flags &= ~MS_POSIXACL;
+
        bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
        sb->s_bdi = bdi ? : &default_backing_dev_info;
 
@@ -1113,6 +1123,8 @@ nilfs_fill_super(struct super_block *sb, void *data, int 
silent)
        nilfs_put_root(fsroot);
 
  failed_unload:
+       if (nilfs_has_xafile(nilfs))
+               iput(nilfs->ns_xafile);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_dat);
@@ -1136,7 +1148,11 @@ static int nilfs_remount(struct super_block *sb, int 
*flags, char *data)
                err = -EINVAL;
                goto restore_opts;
        }
-       sb->s_flags = (sb->s_flags & ~MS_POSIXACL);
+
+       if (nilfs_has_xafile(nilfs))
+               set_posix_acl_flag(sb);
+       else
+               sb->s_flags &= ~MS_POSIXACL;
 
        err = -EINVAL;
 
@@ -1379,9 +1395,7 @@ static void nilfs_inode_init_once(void *obj)
        struct nilfs_inode_info *ii = obj;
 
        INIT_LIST_HEAD(&ii->i_dirty);
-#ifdef CONFIG_NILFS_XATTR
        init_rwsem(&ii->xattr_sem);
-#endif
        address_space_init_once(&ii->i_btnode_cache);
        ii->i_bmap = &ii->i_bmap_data;
        inode_init_once(&ii->vfs_inode);
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 94c451c..a5fa271 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -33,6 +33,7 @@
 #include "cpfile.h"
 #include "sufile.h"
 #include "dat.h"
+#include "xafile.h"
 #include "segbuf.h"
 
 
@@ -142,6 +143,14 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
        if (err)
                goto failed_cpfile;
 
+       if (nilfs_has_xafile(nilfs)) {
+               rawi = (void *)bh_sr->b_data +
+                               NILFS_SR_XAFILE_OFFSET(inode_size);
+               err = nilfs_xafile_read(sb, rawi, &nilfs->ns_xafile);
+               if (err)
+                       goto failed_xafile;
+       }
+
        raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
        nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime);
 
@@ -149,6 +158,10 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
        brelse(bh_sr);
        return err;
 
+ failed_xafile:
+       if (nilfs_has_xafile(nilfs))
+               iput(nilfs->ns_xafile);
+
  failed_cpfile:
        iput(nilfs->ns_cpfile);
 
@@ -343,6 +356,8 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block 
*sb)
        goto failed;
 
  failed_unload:
+       if (nilfs_has_xafile(nilfs))
+               iput(nilfs->ns_xafile);
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_dat);
@@ -584,6 +599,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block 
*sb, char *data)
        if (err)
                goto failed_sbh;
 
+       if (le64_to_cpu(sbp->s_feature_compat_ro) &
+           NILFS_FEATURE_COMPAT_RO_XAFILE)
+               set_nilfs_has_xafile(nilfs);
+
        blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
        if (blocksize < NILFS_MIN_BLOCK_SIZE ||
            blocksize > NILFS_MAX_BLOCK_SIZE) {
-- 
1.7.9.5



--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to