[XFS] Remove vn_from_inode()
[safe/jmp/linux-2.6] / fs / ecryptfs / main.c
index 4750d82..448dfd5 100644 (file)
@@ -130,26 +130,12 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                        ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
 
                lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-               /* Corresponding dput() and mntput() are done when the
-                * persistent file is fput() when the eCryptfs inode
-                * is destroyed. */
-               dget(lower_dentry);
-               mntget(lower_mnt);
-               inode_info->lower_file = dentry_open(lower_dentry,
-                                                    lower_mnt,
-                                                    (O_RDWR | O_LARGEFILE));
-               if (IS_ERR(inode_info->lower_file)) {
-                       dget(lower_dentry);
-                       mntget(lower_mnt);
-                       inode_info->lower_file = dentry_open(lower_dentry,
-                                                            lower_mnt,
-                                                            (O_RDONLY
-                                                             | O_LARGEFILE));
-               }
-               if (IS_ERR(inode_info->lower_file)) {
+               rc = ecryptfs_privileged_open(&inode_info->lower_file,
+                                                    lower_dentry, lower_mnt);
+               if (rc || IS_ERR(inode_info->lower_file)) {
                        printk(KERN_ERR "Error opening lower persistent file "
-                              "for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
-                              lower_dentry, lower_mnt);
+                              "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
+                              "rc = [%d]\n", lower_dentry, lower_mnt, rc);
                        rc = PTR_ERR(inode_info->lower_file);
                        inode_info->lower_file = NULL;
                }
@@ -163,14 +149,14 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
  * @lower_dentry: Existing dentry in the lower filesystem
  * @dentry: ecryptfs' dentry
  * @sb: ecryptfs's super_block
- * @flag: If set to true, then d_add is called, else d_instantiate is called
+ * @flags: flags to govern behavior of interpose procedure
  *
  * Interposes upper and lower dentries.
  *
  * Returns zero on success; non-zero otherwise
  */
 int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
-                      struct super_block *sb, int flag)
+                      struct super_block *sb, u32 flags)
 {
        struct inode *lower_inode;
        struct inode *inode;
@@ -207,7 +193,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
                init_special_inode(inode, lower_inode->i_mode,
                                   lower_inode->i_rdev);
        dentry->d_op = &ecryptfs_dops;
-       if (flag)
+       if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
                d_add(dentry, inode);
        else
                d_instantiate(dentry, inode);
@@ -215,28 +201,19 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
        /* This size will be overwritten for real files w/ headers and
         * other metadata */
        fsstack_copy_inode_size(inode, lower_inode);
-       rc = ecryptfs_init_persistent_file(dentry);
-       if (rc) {
-               printk(KERN_ERR "%s: Error attempting to initialize the "
-                      "persistent file for the dentry with name [%s]; "
-                      "rc = [%d]\n", __FUNCTION__, dentry->d_name.name, rc);
-               goto out;
-       }
 out:
        return rc;
 }
 
-enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
-       ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
-       ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
+enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
+       ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
+       ecryptfs_opt_ecryptfs_key_bytes,
        ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
        ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
 
 static match_table_t tokens = {
        {ecryptfs_opt_sig, "sig=%s"},
        {ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"},
-       {ecryptfs_opt_debug, "debug=%u"},
-       {ecryptfs_opt_ecryptfs_debug, "ecryptfs_debug=%u"},
        {ecryptfs_opt_cipher, "cipher=%s"},
        {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
        {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
@@ -264,10 +241,11 @@ static int ecryptfs_init_global_auth_toks(
                               "session keyring for sig specified in mount "
                               "option: [%s]\n", global_auth_tok->sig);
                        global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
-                       rc = 0;
+                       goto out;
                } else
                        global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
        }
+out:
        return rc;
 }
 
@@ -313,11 +291,9 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
        substring_t args[MAX_OPT_ARGS];
        int token;
        char *sig_src;
-       char *debug_src;
        char *cipher_name_dst;
        char *cipher_name_src;
        char *cipher_key_bytes_src;
-       int cipher_name_len;
 
        if (!options) {
                rc = -EINVAL;
@@ -341,16 +317,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
                        }
                        sig_set = 1;
                        break;
-               case ecryptfs_opt_debug:
-               case ecryptfs_opt_ecryptfs_debug:
-                       debug_src = args[0].from;
-                       ecryptfs_verbosity =
-                               (int)simple_strtol(debug_src, &debug_src,
-                                                  0);
-                       ecryptfs_printk(KERN_DEBUG,
-                                       "Verbosity set to [%d]" "\n",
-                                       ecryptfs_verbosity);
-                       break;
                case ecryptfs_opt_cipher:
                case ecryptfs_opt_ecryptfs_cipher:
                        cipher_name_src = args[0].from;
@@ -408,24 +374,23 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
                goto out;
        }
        if (!cipher_name_set) {
-               cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
-               if (unlikely(cipher_name_len
-                            >= ECRYPTFS_MAX_CIPHER_NAME_SIZE)) {
-                       rc = -EINVAL;
-                       BUG();
-                       goto out;
-               }
-               memcpy(mount_crypt_stat->global_default_cipher_name,
-                      ECRYPTFS_DEFAULT_CIPHER, cipher_name_len);
-               mount_crypt_stat->global_default_cipher_name[cipher_name_len]
-                   = '\0';
+               int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
+
+               BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+
+               strcpy(mount_crypt_stat->global_default_cipher_name,
+                      ECRYPTFS_DEFAULT_CIPHER);
        }
        if (!cipher_key_bytes_set) {
                mount_crypt_stat->global_default_cipher_key_size = 0;
        }
-       rc = ecryptfs_add_new_key_tfm(
-               NULL, mount_crypt_stat->global_default_cipher_name,
-               mount_crypt_stat->global_default_cipher_key_size);
+       mutex_lock(&key_tfm_list_mutex);
+       if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
+                                NULL))
+               rc = ecryptfs_add_new_key_tfm(
+                       NULL, mount_crypt_stat->global_default_cipher_name,
+                       mount_crypt_stat->global_default_cipher_key_size);
+       mutex_unlock(&key_tfm_list_mutex);
        if (rc) {
                printk(KERN_ERR "Error attempting to initialize cipher with "
                       "name = [%s] and key size = [%td]; rc = [%d]\n",
@@ -439,7 +404,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
                printk(KERN_WARNING "One or more global auth toks could not "
                       "properly register; rc = [%d]\n", rc);
        }
-       rc = 0;
 out:
        return rc;
 }
@@ -522,8 +486,8 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
                ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n");
                goto out;
        }
-       lower_root = nd.dentry;
-       lower_mnt = nd.mnt;
+       lower_root = nd.path.dentry;
+       lower_mnt = nd.path.mnt;
        ecryptfs_set_superblock_lower(sb, lower_root->d_sb);
        sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
        sb->s_blocksize = lower_root->d_sb->s_blocksize;
@@ -535,7 +499,7 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
        rc = 0;
        goto out;
 out_free:
-       path_release(&nd);
+       path_put(&nd.path);
 out:
        return rc;
 }
@@ -614,7 +578,7 @@ static struct file_system_type ecryptfs_fs_type = {
  * Initializes the ecryptfs_inode_info_cache when it is created
  */
 static void
-inode_info_init_once(struct kmem_cache *cachep, void *vptr)
+inode_info_init_once(void *vptr)
 {
        struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr;
 
@@ -625,7 +589,7 @@ static struct ecryptfs_cache_info {
        struct kmem_cache **cache;
        const char *name;
        size_t size;
-       void (*ctor)(struct kmem_cache *cache, void *obj);
+       void (*ctor)(void *obj);
 } ecryptfs_cache_infos[] = {
        {
                .cache = &ecryptfs_auth_tok_list_item_cache,
@@ -654,11 +618,6 @@ static struct ecryptfs_cache_info {
                .size = sizeof(struct ecryptfs_sb_info),
        },
        {
-               .cache = &ecryptfs_header_cache_0,
-               .name = "ecryptfs_headers_0",
-               .size = PAGE_CACHE_SIZE,
-       },
-       {
                .cache = &ecryptfs_header_cache_1,
                .name = "ecryptfs_headers_1",
                .size = PAGE_CACHE_SIZE,
@@ -693,6 +652,11 @@ static struct ecryptfs_cache_info {
                .name = "ecryptfs_key_tfm_cache",
                .size = sizeof(struct ecryptfs_key_tfm),
        },
+       {
+               .cache = &ecryptfs_open_req_cache,
+               .name = "ecryptfs_open_req_cache",
+               .size = sizeof(struct ecryptfs_open_req),
+       },
 };
 
 static void ecryptfs_free_kmem_caches(void)
@@ -734,59 +698,18 @@ static int ecryptfs_init_kmem_caches(void)
        return 0;
 }
 
-static struct kset *ecryptfs_kset;
+static struct kobject *ecryptfs_kobj;
 
-static ssize_t version_show(struct kset *kset, char *buff)
+static ssize_t version_show(struct kobject *kobj,
+                           struct kobj_attribute *attr, char *buff)
 {
        return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK);
 }
 
-static struct subsys_attribute version_attr = __ATTR_RO(version);
-
-static struct ecryptfs_version_str_map_elem {
-       u32 flag;
-       char *str;
-} ecryptfs_version_str_map[] = {
-       {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"},
-       {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
-       {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
-       {ECRYPTFS_VERSIONING_POLICY, "policy"},
-       {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"},
-       {ECRYPTFS_VERSIONING_MULTKEY, "multiple keys per file"}
-};
-
-static ssize_t version_str_show(struct kset *kset, char *buff)
-{
-       int i;
-       int remaining = PAGE_SIZE;
-       int total_written = 0;
-
-       buff[0] = '\0';
-       for (i = 0; i < ARRAY_SIZE(ecryptfs_version_str_map); i++) {
-               int entry_size;
-
-               if (!(ECRYPTFS_VERSIONING_MASK
-                     & ecryptfs_version_str_map[i].flag))
-                       continue;
-               entry_size = strlen(ecryptfs_version_str_map[i].str);
-               if ((entry_size + 2) > remaining)
-                       goto out;
-               memcpy(buff, ecryptfs_version_str_map[i].str, entry_size);
-               buff[entry_size++] = '\n';
-               buff[entry_size] = '\0';
-               buff += entry_size;
-               total_written += entry_size;
-               remaining -= entry_size;
-       }
-out:
-       return total_written;
-}
-
-static struct subsys_attribute version_attr_str = __ATTR_RO(version_str);
+static struct kobj_attribute version_attr = __ATTR_RO(version);
 
 static struct attribute *attributes[] = {
        &version_attr.attr,
-       &version_attr_str.attr,
        NULL,
 };
 
@@ -798,17 +721,17 @@ static int do_sysfs_registration(void)
 {
        int rc;
 
-       ecryptfs_kset = kset_create_and_add("ecryptfs", NULL, &fs_subsys.kobj);
-       if (!ecryptfs_kset) {
+       ecryptfs_kobj = kobject_create_and_add("ecryptfs", fs_kobj);
+       if (!ecryptfs_kobj) {
                printk(KERN_ERR "Unable to create ecryptfs kset\n");
                rc = -ENOMEM;
                goto out;
        }
-       rc = sysfs_create_group(&ecryptfs_kset->kobj, &attr_group);
+       rc = sysfs_create_group(ecryptfs_kobj, &attr_group);
        if (rc) {
                printk(KERN_ERR
                       "Unable to create ecryptfs version attributes\n");
-               kset_unregister(ecryptfs_kset);
+               kobject_put(ecryptfs_kobj);
        }
 out:
        return rc;
@@ -816,8 +739,8 @@ out:
 
 static void do_sysfs_unregistration(void)
 {
-       sysfs_remove_group(&ecryptfs_kset->kobj, &attr_group);
-       kset_unregister(ecryptfs_kset);
+       sysfs_remove_group(ecryptfs_kobj, &attr_group);
+       kobject_put(ecryptfs_kobj);
 }
 
 static int __init ecryptfs_init(void)
@@ -850,11 +773,17 @@ static int __init ecryptfs_init(void)
                printk(KERN_ERR "sysfs registration failed\n");
                goto out_unregister_filesystem;
        }
+       rc = ecryptfs_init_kthread();
+       if (rc) {
+               printk(KERN_ERR "%s: kthread initialization failed; "
+                      "rc = [%d]\n", __func__, rc);
+               goto out_do_sysfs_unregistration;
+       }
        rc = ecryptfs_init_messaging(ecryptfs_transport);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+               printk(KERN_ERR "Failure occured while attempting to "
                                "initialize the eCryptfs netlink socket\n");
-               goto out_do_sysfs_unregistration;
+               goto out_destroy_kthread;
        }
        rc = ecryptfs_init_crypto();
        if (rc) {
@@ -862,9 +791,15 @@ static int __init ecryptfs_init(void)
                       "rc = [%d]\n", rc);
                goto out_release_messaging;
        }
+       if (ecryptfs_verbosity > 0)
+               printk(KERN_CRIT "eCryptfs verbosity set to %d. Secret values "
+                       "will be written to the syslog!\n", ecryptfs_verbosity);
+
        goto out;
 out_release_messaging:
        ecryptfs_release_messaging(ecryptfs_transport);
+out_destroy_kthread:
+       ecryptfs_destroy_kthread();
 out_do_sysfs_unregistration:
        do_sysfs_unregistration();
 out_unregister_filesystem:
@@ -884,6 +819,7 @@ static void __exit ecryptfs_exit(void)
                printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
                       "rc = [%d]\n", rc);
        ecryptfs_release_messaging(ecryptfs_transport);
+       ecryptfs_destroy_kthread();
        do_sysfs_unregistration();
        unregister_filesystem(&ecryptfs_fs_type);
        ecryptfs_free_kmem_caches();