LCOV - code coverage report
Current view: top level - fs/cachefiles - bind.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 96 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 3 0.0 %
Branches: 0 198 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Bind and unbind a cache from the filesystem backing it
       3                 :            :  *
       4                 :            :  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
       5                 :            :  * Written by David Howells (dhowells@redhat.com)
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/module.h>
       9                 :            : #include <linux/init.h>
      10                 :            : #include <linux/sched.h>
      11                 :            : #include <linux/completion.h>
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/fs.h>
      14                 :            : #include <linux/file.h>
      15                 :            : #include <linux/namei.h>
      16                 :            : #include <linux/mount.h>
      17                 :            : #include <linux/statfs.h>
      18                 :            : #include <linux/ctype.h>
      19                 :            : #include <linux/xattr.h>
      20                 :            : #include "internal.h"
      21                 :            : 
      22                 :            : static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
      23                 :            : 
      24                 :            : /*
      25                 :            :  * bind a directory as a cache
      26                 :            :  */
      27                 :          0 : int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
      28                 :            : {
      29                 :            :         _enter("{%u,%u,%u,%u,%u,%u},%s",
      30                 :            :                cache->frun_percent,
      31                 :            :                cache->fcull_percent,
      32                 :            :                cache->fstop_percent,
      33                 :            :                cache->brun_percent,
      34                 :            :                cache->bcull_percent,
      35                 :            :                cache->bstop_percent,
      36                 :            :                args);
      37                 :            : 
      38                 :            :         /* start by checking things over */
      39   [ #  #  #  #  :          0 :         ASSERT(cache->fstop_percent >= 0 &&
             #  #  #  # ]
      40                 :            :                cache->fstop_percent < cache->fcull_percent &&
      41                 :            :                cache->fcull_percent < cache->frun_percent &&
      42                 :            :                cache->frun_percent  < 100);
      43                 :            : 
      44   [ #  #  #  #  :          0 :         ASSERT(cache->bstop_percent >= 0 &&
             #  #  #  # ]
      45                 :            :                cache->bstop_percent < cache->bcull_percent &&
      46                 :            :                cache->bcull_percent < cache->brun_percent &&
      47                 :            :                cache->brun_percent  < 100);
      48                 :            : 
      49         [ #  # ]:          0 :         if (*args) {
      50                 :          0 :                 pr_err("'bind' command doesn't take an argument\n");
      51                 :          0 :                 return -EINVAL;
      52                 :            :         }
      53                 :            : 
      54         [ #  # ]:          0 :         if (!cache->rootdirname) {
      55                 :          0 :                 pr_err("No cache directory specified\n");
      56                 :          0 :                 return -EINVAL;
      57                 :            :         }
      58                 :            : 
      59                 :            :         /* don't permit already bound caches to be re-bound */
      60         [ #  # ]:          0 :         if (test_bit(CACHEFILES_READY, &cache->flags)) {
      61                 :          0 :                 pr_err("Cache already bound\n");
      62                 :          0 :                 return -EBUSY;
      63                 :            :         }
      64                 :            : 
      65                 :            :         /* make sure we have copies of the tag and dirname strings */
      66         [ #  # ]:          0 :         if (!cache->tag) {
      67                 :            :                 /* the tag string is released by the fops->release()
      68                 :            :                  * function, so we don't release it on error here */
      69                 :          0 :                 cache->tag = kstrdup("CacheFiles", GFP_KERNEL);
      70         [ #  # ]:          0 :                 if (!cache->tag)
      71                 :            :                         return -ENOMEM;
      72                 :            :         }
      73                 :            : 
      74                 :            :         /* add the cache */
      75                 :          0 :         return cachefiles_daemon_add_cache(cache);
      76                 :            : }
      77                 :            : 
      78                 :            : /*
      79                 :            :  * add a cache
      80                 :            :  */
      81                 :          0 : static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
      82                 :            : {
      83                 :            :         struct cachefiles_object *fsdef;
      84                 :            :         struct path path;
      85                 :            :         struct kstatfs stats;
      86                 :            :         struct dentry *graveyard, *cachedir, *root;
      87                 :            :         const struct cred *saved_cred;
      88                 :            :         int ret;
      89                 :            : 
      90                 :            :         _enter("");
      91                 :            : 
      92                 :            :         /* we want to work under the module's security ID */
      93                 :          0 :         ret = cachefiles_get_security_ID(cache);
      94         [ #  # ]:          0 :         if (ret < 0)
      95                 :            :                 return ret;
      96                 :            : 
      97                 :            :         cachefiles_begin_secure(cache, &saved_cred);
      98                 :            : 
      99                 :            :         /* allocate the root index object */
     100                 :            :         ret = -ENOMEM;
     101                 :            : 
     102                 :          0 :         fsdef = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL);
     103         [ #  # ]:          0 :         if (!fsdef)
     104                 :            :                 goto error_root_object;
     105                 :            : 
     106         [ #  # ]:          0 :         ASSERTCMP(fsdef->backer, ==, NULL);
     107                 :            : 
     108                 :            :         atomic_set(&fsdef->usage, 1);
     109                 :          0 :         fsdef->type = FSCACHE_COOKIE_TYPE_INDEX;
     110                 :            : 
     111                 :            :         _debug("- fsdef %p", fsdef);
     112                 :            : 
     113                 :            :         /* look up the directory at the root of the cache */
     114                 :          0 :         ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
     115         [ #  # ]:          0 :         if (ret < 0)
     116                 :            :                 goto error_open_root;
     117                 :            : 
     118                 :          0 :         cache->mnt = path.mnt;
     119                 :          0 :         root = path.dentry;
     120                 :            : 
     121                 :            :         /* check parameters */
     122                 :            :         ret = -EOPNOTSUPP;
     123   [ #  #  #  # ]:          0 :         if (d_is_negative(root) ||
     124         [ #  # ]:          0 :             !d_backing_inode(root)->i_op->lookup ||
     125         [ #  # ]:          0 :             !d_backing_inode(root)->i_op->mkdir ||
     126         [ #  # ]:          0 :             !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
     127         [ #  # ]:          0 :             !root->d_sb->s_op->statfs ||
     128                 :          0 :             !root->d_sb->s_op->sync_fs)
     129                 :            :                 goto error_unsupported;
     130                 :            : 
     131                 :            :         ret = -EROFS;
     132         [ #  # ]:          0 :         if (sb_rdonly(root->d_sb))
     133                 :            :                 goto error_unsupported;
     134                 :            : 
     135                 :            :         /* determine the security of the on-disk cache as this governs
     136                 :            :          * security ID of files we create */
     137                 :          0 :         ret = cachefiles_determine_cache_security(cache, root, &saved_cred);
     138         [ #  # ]:          0 :         if (ret < 0)
     139                 :            :                 goto error_unsupported;
     140                 :            : 
     141                 :            :         /* get the cache size and blocksize */
     142                 :          0 :         ret = vfs_statfs(&path, &stats);
     143         [ #  # ]:          0 :         if (ret < 0)
     144                 :            :                 goto error_unsupported;
     145                 :            : 
     146                 :            :         ret = -ERANGE;
     147         [ #  # ]:          0 :         if (stats.f_bsize <= 0)
     148                 :            :                 goto error_unsupported;
     149                 :            : 
     150                 :            :         ret = -EOPNOTSUPP;
     151         [ #  # ]:          0 :         if (stats.f_bsize > PAGE_SIZE)
     152                 :            :                 goto error_unsupported;
     153                 :            : 
     154                 :          0 :         cache->bsize = stats.f_bsize;
     155                 :          0 :         cache->bshift = 0;
     156         [ #  # ]:          0 :         if (stats.f_bsize < PAGE_SIZE)
     157   [ #  #  #  #  :          0 :                 cache->bshift = PAGE_SHIFT - ilog2(stats.f_bsize);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     158                 :            : 
     159                 :            :         _debug("blksize %u (shift %u)",
     160                 :            :                cache->bsize, cache->bshift);
     161                 :            : 
     162                 :            :         _debug("size %llu, avail %llu",
     163                 :            :                (unsigned long long) stats.f_blocks,
     164                 :            :                (unsigned long long) stats.f_bavail);
     165                 :            : 
     166                 :            :         /* set up caching limits */
     167                 :          0 :         do_div(stats.f_files, 100);
     168                 :          0 :         cache->fstop = stats.f_files * cache->fstop_percent;
     169                 :          0 :         cache->fcull = stats.f_files * cache->fcull_percent;
     170                 :          0 :         cache->frun  = stats.f_files * cache->frun_percent;
     171                 :            : 
     172                 :            :         _debug("limits {%llu,%llu,%llu} files",
     173                 :            :                (unsigned long long) cache->frun,
     174                 :            :                (unsigned long long) cache->fcull,
     175                 :            :                (unsigned long long) cache->fstop);
     176                 :            : 
     177                 :          0 :         stats.f_blocks >>= cache->bshift;
     178                 :          0 :         do_div(stats.f_blocks, 100);
     179                 :          0 :         cache->bstop = stats.f_blocks * cache->bstop_percent;
     180                 :          0 :         cache->bcull = stats.f_blocks * cache->bcull_percent;
     181                 :          0 :         cache->brun  = stats.f_blocks * cache->brun_percent;
     182                 :            : 
     183                 :            :         _debug("limits {%llu,%llu,%llu} blocks",
     184                 :            :                (unsigned long long) cache->brun,
     185                 :            :                (unsigned long long) cache->bcull,
     186                 :            :                (unsigned long long) cache->bstop);
     187                 :            : 
     188                 :            :         /* get the cache directory and check its type */
     189                 :          0 :         cachedir = cachefiles_get_directory(cache, root, "cache");
     190         [ #  # ]:          0 :         if (IS_ERR(cachedir)) {
     191                 :            :                 ret = PTR_ERR(cachedir);
     192                 :          0 :                 goto error_unsupported;
     193                 :            :         }
     194                 :            : 
     195                 :          0 :         fsdef->dentry = cachedir;
     196                 :          0 :         fsdef->fscache.cookie = NULL;
     197                 :            : 
     198                 :          0 :         ret = cachefiles_check_object_type(fsdef);
     199         [ #  # ]:          0 :         if (ret < 0)
     200                 :            :                 goto error_unsupported;
     201                 :            : 
     202                 :            :         /* get the graveyard directory */
     203                 :          0 :         graveyard = cachefiles_get_directory(cache, root, "graveyard");
     204         [ #  # ]:          0 :         if (IS_ERR(graveyard)) {
     205                 :            :                 ret = PTR_ERR(graveyard);
     206                 :          0 :                 goto error_unsupported;
     207                 :            :         }
     208                 :            : 
     209                 :          0 :         cache->graveyard = graveyard;
     210                 :            : 
     211                 :            :         /* publish the cache */
     212                 :          0 :         fscache_init_cache(&cache->cache,
     213                 :            :                            &cachefiles_cache_ops,
     214                 :            :                            "%s",
     215                 :          0 :                            fsdef->dentry->d_sb->s_id);
     216                 :            : 
     217                 :          0 :         fscache_object_init(&fsdef->fscache, &fscache_fsdef_index,
     218                 :            :                             &cache->cache);
     219                 :            : 
     220                 :          0 :         ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag);
     221         [ #  # ]:          0 :         if (ret < 0)
     222                 :            :                 goto error_add_cache;
     223                 :            : 
     224                 :            :         /* done */
     225                 :          0 :         set_bit(CACHEFILES_READY, &cache->flags);
     226                 :          0 :         dput(root);
     227                 :            : 
     228                 :          0 :         pr_info("File cache on %s registered\n", cache->cache.identifier);
     229                 :            : 
     230                 :            :         /* check how much space the cache has */
     231                 :          0 :         cachefiles_has_space(cache, 0, 0);
     232                 :          0 :         cachefiles_end_secure(cache, saved_cred);
     233                 :          0 :         return 0;
     234                 :            : 
     235                 :            : error_add_cache:
     236                 :          0 :         dput(cache->graveyard);
     237                 :          0 :         cache->graveyard = NULL;
     238                 :            : error_unsupported:
     239                 :          0 :         mntput(cache->mnt);
     240                 :          0 :         cache->mnt = NULL;
     241                 :          0 :         dput(fsdef->dentry);
     242                 :          0 :         fsdef->dentry = NULL;
     243                 :          0 :         dput(root);
     244                 :            : error_open_root:
     245                 :          0 :         kmem_cache_free(cachefiles_object_jar, fsdef);
     246                 :            : error_root_object:
     247                 :          0 :         cachefiles_end_secure(cache, saved_cred);
     248                 :          0 :         pr_err("Failed to register: %d\n", ret);
     249                 :          0 :         return ret;
     250                 :            : }
     251                 :            : 
     252                 :            : /*
     253                 :            :  * unbind a cache on fd release
     254                 :            :  */
     255                 :          0 : void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
     256                 :            : {
     257                 :            :         _enter("");
     258                 :            : 
     259         [ #  # ]:          0 :         if (test_bit(CACHEFILES_READY, &cache->flags)) {
     260                 :          0 :                 pr_info("File cache on %s unregistering\n",
     261                 :            :                         cache->cache.identifier);
     262                 :            : 
     263                 :          0 :                 fscache_withdraw_cache(&cache->cache);
     264                 :            :         }
     265                 :            : 
     266                 :          0 :         dput(cache->graveyard);
     267                 :          0 :         mntput(cache->mnt);
     268                 :            : 
     269                 :          0 :         kfree(cache->rootdirname);
     270                 :          0 :         kfree(cache->secctx);
     271                 :          0 :         kfree(cache->tag);
     272                 :            : 
     273                 :            :         _leave("");
     274                 :          0 : }

Generated by: LCOV version 1.14