root/fs/nfs/cache_lib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfs_cache_upcall
  2. nfs_cache_defer_req_put
  3. nfs_dns_cache_revisit
  4. nfs_dns_cache_defer
  5. nfs_cache_defer_req_alloc
  6. nfs_cache_wait_for_upcall
  7. nfs_cache_register_sb
  8. nfs_cache_register_net
  9. nfs_cache_unregister_sb
  10. nfs_cache_unregister_net

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * linux/fs/nfs/cache_lib.c
   4  *
   5  * Helper routines for the NFS client caches
   6  *
   7  * Copyright (c) 2009 Trond Myklebust <Trond.Myklebust@netapp.com>
   8  */
   9 #include <linux/kmod.h>
  10 #include <linux/module.h>
  11 #include <linux/moduleparam.h>
  12 #include <linux/mount.h>
  13 #include <linux/namei.h>
  14 #include <linux/slab.h>
  15 #include <linux/sunrpc/cache.h>
  16 #include <linux/sunrpc/rpc_pipe_fs.h>
  17 #include <net/net_namespace.h>
  18 
  19 #include "cache_lib.h"
  20 
  21 #define NFS_CACHE_UPCALL_PATHLEN 256
  22 #define NFS_CACHE_UPCALL_TIMEOUT 15
  23 
  24 static char nfs_cache_getent_prog[NFS_CACHE_UPCALL_PATHLEN] =
  25                                 "/sbin/nfs_cache_getent";
  26 static unsigned long nfs_cache_getent_timeout = NFS_CACHE_UPCALL_TIMEOUT;
  27 
  28 module_param_string(cache_getent, nfs_cache_getent_prog,
  29                 sizeof(nfs_cache_getent_prog), 0600);
  30 MODULE_PARM_DESC(cache_getent, "Path to the client cache upcall program");
  31 module_param_named(cache_getent_timeout, nfs_cache_getent_timeout, ulong, 0600);
  32 MODULE_PARM_DESC(cache_getent_timeout, "Timeout (in seconds) after which "
  33                 "the cache upcall is assumed to have failed");
  34 
  35 int nfs_cache_upcall(struct cache_detail *cd, char *entry_name)
  36 {
  37         static char *envp[] = { "HOME=/",
  38                 "TERM=linux",
  39                 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
  40                 NULL
  41         };
  42         char *argv[] = {
  43                 nfs_cache_getent_prog,
  44                 cd->name,
  45                 entry_name,
  46                 NULL
  47         };
  48         int ret = -EACCES;
  49 
  50         if (nfs_cache_getent_prog[0] == '\0')
  51                 goto out;
  52         ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
  53         /*
  54          * Disable the upcall mechanism if we're getting an ENOENT or
  55          * EACCES error. The admin can re-enable it on the fly by using
  56          * sysfs to set the 'cache_getent' parameter once the problem
  57          * has been fixed.
  58          */
  59         if (ret == -ENOENT || ret == -EACCES)
  60                 nfs_cache_getent_prog[0] = '\0';
  61 out:
  62         return ret > 0 ? 0 : ret;
  63 }
  64 
  65 /*
  66  * Deferred request handling
  67  */
  68 void nfs_cache_defer_req_put(struct nfs_cache_defer_req *dreq)
  69 {
  70         if (refcount_dec_and_test(&dreq->count))
  71                 kfree(dreq);
  72 }
  73 
  74 static void nfs_dns_cache_revisit(struct cache_deferred_req *d, int toomany)
  75 {
  76         struct nfs_cache_defer_req *dreq;
  77 
  78         dreq = container_of(d, struct nfs_cache_defer_req, deferred_req);
  79 
  80         complete(&dreq->completion);
  81         nfs_cache_defer_req_put(dreq);
  82 }
  83 
  84 static struct cache_deferred_req *nfs_dns_cache_defer(struct cache_req *req)
  85 {
  86         struct nfs_cache_defer_req *dreq;
  87 
  88         dreq = container_of(req, struct nfs_cache_defer_req, req);
  89         dreq->deferred_req.revisit = nfs_dns_cache_revisit;
  90         refcount_inc(&dreq->count);
  91 
  92         return &dreq->deferred_req;
  93 }
  94 
  95 struct nfs_cache_defer_req *nfs_cache_defer_req_alloc(void)
  96 {
  97         struct nfs_cache_defer_req *dreq;
  98 
  99         dreq = kzalloc(sizeof(*dreq), GFP_KERNEL);
 100         if (dreq) {
 101                 init_completion(&dreq->completion);
 102                 refcount_set(&dreq->count, 1);
 103                 dreq->req.defer = nfs_dns_cache_defer;
 104         }
 105         return dreq;
 106 }
 107 
 108 int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq)
 109 {
 110         if (wait_for_completion_timeout(&dreq->completion,
 111                         nfs_cache_getent_timeout * HZ) == 0)
 112                 return -ETIMEDOUT;
 113         return 0;
 114 }
 115 
 116 int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd)
 117 {
 118         int ret;
 119         struct dentry *dir;
 120 
 121         dir = rpc_d_lookup_sb(sb, "cache");
 122         ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd);
 123         dput(dir);
 124         return ret;
 125 }
 126 
 127 int nfs_cache_register_net(struct net *net, struct cache_detail *cd)
 128 {
 129         struct super_block *pipefs_sb;
 130         int ret = 0;
 131 
 132         sunrpc_init_cache_detail(cd);
 133         pipefs_sb = rpc_get_sb_net(net);
 134         if (pipefs_sb) {
 135                 ret = nfs_cache_register_sb(pipefs_sb, cd);
 136                 rpc_put_sb_net(net);
 137                 if (ret)
 138                         sunrpc_destroy_cache_detail(cd);
 139         }
 140         return ret;
 141 }
 142 
 143 void nfs_cache_unregister_sb(struct super_block *sb, struct cache_detail *cd)
 144 {
 145         sunrpc_cache_unregister_pipefs(cd);
 146 }
 147 
 148 void nfs_cache_unregister_net(struct net *net, struct cache_detail *cd)
 149 {
 150         struct super_block *pipefs_sb;
 151 
 152         pipefs_sb = rpc_get_sb_net(net);
 153         if (pipefs_sb) {
 154                 nfs_cache_unregister_sb(pipefs_sb, cd);
 155                 rpc_put_sb_net(net);
 156         }
 157         sunrpc_destroy_cache_detail(cd);
 158 }

/* [<][>][^][v][top][bottom][index][help] */