LCOV - code coverage report
Current view: top level - fs/lockd - mon.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 182 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 15 0.0 %
Branches: 0 66 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * linux/fs/lockd/mon.c
       4                 :            :  *
       5                 :            :  * The kernel statd client.
       6                 :            :  *
       7                 :            :  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
       8                 :            :  */
       9                 :            : 
      10                 :            : #include <linux/types.h>
      11                 :            : #include <linux/kernel.h>
      12                 :            : #include <linux/ktime.h>
      13                 :            : #include <linux/slab.h>
      14                 :            : 
      15                 :            : #include <linux/sunrpc/clnt.h>
      16                 :            : #include <linux/sunrpc/addr.h>
      17                 :            : #include <linux/sunrpc/xprtsock.h>
      18                 :            : #include <linux/sunrpc/svc.h>
      19                 :            : #include <linux/lockd/lockd.h>
      20                 :            : 
      21                 :            : #include <asm/unaligned.h>
      22                 :            : 
      23                 :            : #include "netns.h"
      24                 :            : 
      25                 :            : #define NLMDBG_FACILITY         NLMDBG_MONITOR
      26                 :            : #define NSM_PROGRAM             100024
      27                 :            : #define NSM_VERSION             1
      28                 :            : 
      29                 :            : enum {
      30                 :            :         NSMPROC_NULL,
      31                 :            :         NSMPROC_STAT,
      32                 :            :         NSMPROC_MON,
      33                 :            :         NSMPROC_UNMON,
      34                 :            :         NSMPROC_UNMON_ALL,
      35                 :            :         NSMPROC_SIMU_CRASH,
      36                 :            :         NSMPROC_NOTIFY,
      37                 :            : };
      38                 :            : 
      39                 :            : struct nsm_args {
      40                 :            :         struct nsm_private      *priv;
      41                 :            :         u32                     prog;           /* RPC callback info */
      42                 :            :         u32                     vers;
      43                 :            :         u32                     proc;
      44                 :            : 
      45                 :            :         char                    *mon_name;
      46                 :            :         const char              *nodename;
      47                 :            : };
      48                 :            : 
      49                 :            : struct nsm_res {
      50                 :            :         u32                     status;
      51                 :            :         u32                     state;
      52                 :            : };
      53                 :            : 
      54                 :            : static const struct rpc_program nsm_program;
      55                 :            : static                          DEFINE_SPINLOCK(nsm_lock);
      56                 :            : 
      57                 :            : /*
      58                 :            :  * Local NSM state
      59                 :            :  */
      60                 :            : u32     __read_mostly           nsm_local_state;
      61                 :            : bool    __read_mostly           nsm_use_hostnames;
      62                 :            : 
      63                 :          0 : static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
      64                 :            : {
      65                 :          0 :         return (struct sockaddr *)&nsm->sm_addr;
      66                 :            : }
      67                 :            : 
      68                 :          0 : static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
      69                 :            : {
      70                 :          0 :         struct sockaddr_in sin = {
      71                 :            :                 .sin_family             = AF_INET,
      72                 :            :                 .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
      73                 :            :         };
      74                 :          0 :         struct rpc_create_args args = {
      75                 :            :                 .net                    = net,
      76                 :            :                 .protocol               = XPRT_TRANSPORT_TCP,
      77                 :            :                 .address                = (struct sockaddr *)&sin,
      78                 :            :                 .addrsize               = sizeof(sin),
      79                 :            :                 .servername             = "rpc.statd",
      80                 :            :                 .nodename               = nodename,
      81                 :            :                 .program                = &nsm_program,
      82                 :            :                 .version                = NSM_VERSION,
      83                 :            :                 .authflavor             = RPC_AUTH_NULL,
      84                 :            :                 .flags                  = RPC_CLNT_CREATE_NOPING,
      85                 :          0 :                 .cred                   = current_cred(),
      86                 :            :         };
      87                 :            : 
      88                 :          0 :         return rpc_create(&args);
      89                 :            : }
      90                 :            : 
      91                 :          0 : static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
      92                 :            :                          const struct nlm_host *host)
      93                 :            : {
      94                 :          0 :         int             status;
      95                 :          0 :         struct rpc_clnt *clnt;
      96                 :          0 :         struct nsm_args args = {
      97                 :          0 :                 .priv           = &nsm->sm_priv,
      98                 :            :                 .prog           = NLM_PROGRAM,
      99                 :            :                 .vers           = 3,
     100                 :            :                 .proc           = NLMPROC_NSM_NOTIFY,
     101                 :          0 :                 .mon_name       = nsm->sm_mon_name,
     102                 :          0 :                 .nodename       = host->nodename,
     103                 :            :         };
     104                 :          0 :         struct rpc_message msg = {
     105                 :            :                 .rpc_argp       = &args,
     106                 :            :                 .rpc_resp       = res,
     107                 :            :         };
     108                 :            : 
     109                 :          0 :         memset(res, 0, sizeof(*res));
     110                 :            : 
     111                 :          0 :         clnt = nsm_create(host->net, host->nodename);
     112         [ #  # ]:          0 :         if (IS_ERR(clnt)) {
     113                 :          0 :                 dprintk("lockd: failed to create NSM upcall transport, "
     114                 :            :                         "status=%ld, net=%x\n", PTR_ERR(clnt),
     115                 :            :                         host->net->ns.inum);
     116                 :          0 :                 return PTR_ERR(clnt);
     117                 :            :         }
     118                 :            : 
     119                 :          0 :         msg.rpc_proc = &clnt->cl_procinfo[proc];
     120                 :          0 :         status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
     121         [ #  # ]:          0 :         if (status == -ECONNREFUSED) {
     122                 :          0 :                 dprintk("lockd:    NSM upcall RPC failed, status=%d, forcing rebind\n",
     123                 :            :                                 status);
     124                 :          0 :                 rpc_force_rebind(clnt);
     125                 :          0 :                 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
     126                 :            :         }
     127                 :          0 :         if (status < 0)
     128                 :            :                 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
     129                 :            :                                 status);
     130                 :            :         else
     131                 :            :                 status = 0;
     132                 :            : 
     133                 :          0 :         rpc_shutdown_client(clnt);
     134                 :          0 :         return status;
     135                 :            : }
     136                 :            : 
     137                 :            : /**
     138                 :            :  * nsm_monitor - Notify a peer in case we reboot
     139                 :            :  * @host: pointer to nlm_host of peer to notify
     140                 :            :  *
     141                 :            :  * If this peer is not already monitored, this function sends an
     142                 :            :  * upcall to the local rpc.statd to record the name/address of
     143                 :            :  * the peer to notify in case we reboot.
     144                 :            :  *
     145                 :            :  * Returns zero if the peer is monitored by the local rpc.statd;
     146                 :            :  * otherwise a negative errno value is returned.
     147                 :            :  */
     148                 :          0 : int nsm_monitor(const struct nlm_host *host)
     149                 :            : {
     150                 :          0 :         struct nsm_handle *nsm = host->h_nsmhandle;
     151                 :          0 :         struct nsm_res  res;
     152                 :          0 :         int             status;
     153                 :            : 
     154                 :          0 :         dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
     155                 :            : 
     156         [ #  # ]:          0 :         if (nsm->sm_monitored)
     157                 :            :                 return 0;
     158                 :            : 
     159                 :            :         /*
     160                 :            :          * Choose whether to record the caller_name or IP address of
     161                 :            :          * this peer in the local rpc.statd's database.
     162                 :            :          */
     163         [ #  # ]:          0 :         nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
     164                 :            : 
     165                 :          0 :         status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host);
     166         [ #  # ]:          0 :         if (unlikely(res.status != 0))
     167                 :          0 :                 status = -EIO;
     168         [ #  # ]:          0 :         if (unlikely(status < 0)) {
     169         [ #  # ]:          0 :                 pr_notice_ratelimited("lockd: cannot monitor %s\n", nsm->sm_name);
     170                 :          0 :                 return status;
     171                 :            :         }
     172                 :            : 
     173                 :          0 :         nsm->sm_monitored = 1;
     174         [ #  # ]:          0 :         if (unlikely(nsm_local_state != res.state)) {
     175                 :          0 :                 nsm_local_state = res.state;
     176                 :            :                 dprintk("lockd: NSM state changed to %d\n", nsm_local_state);
     177                 :            :         }
     178                 :            :         return 0;
     179                 :            : }
     180                 :            : 
     181                 :            : /**
     182                 :            :  * nsm_unmonitor - Unregister peer notification
     183                 :            :  * @host: pointer to nlm_host of peer to stop monitoring
     184                 :            :  *
     185                 :            :  * If this peer is monitored, this function sends an upcall to
     186                 :            :  * tell the local rpc.statd not to send this peer a notification
     187                 :            :  * when we reboot.
     188                 :            :  */
     189                 :          0 : void nsm_unmonitor(const struct nlm_host *host)
     190                 :            : {
     191                 :          0 :         struct nsm_handle *nsm = host->h_nsmhandle;
     192                 :          0 :         struct nsm_res  res;
     193                 :          0 :         int status;
     194                 :            : 
     195         [ #  # ]:          0 :         if (refcount_read(&nsm->sm_count) == 1
     196         [ #  # ]:          0 :          && nsm->sm_monitored && !nsm->sm_sticky) {
     197                 :          0 :                 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
     198                 :            : 
     199                 :          0 :                 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host);
     200         [ #  # ]:          0 :                 if (res.status != 0)
     201                 :            :                         status = -EIO;
     202         [ #  # ]:          0 :                 if (status < 0)
     203                 :          0 :                         printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
     204                 :            :                                         nsm->sm_name);
     205                 :            :                 else
     206                 :          0 :                         nsm->sm_monitored = 0;
     207                 :            :         }
     208                 :          0 : }
     209                 :            : 
     210                 :          0 : static struct nsm_handle *nsm_lookup_hostname(const struct list_head *nsm_handles,
     211                 :            :                                         const char *hostname, const size_t len)
     212                 :            : {
     213                 :          0 :         struct nsm_handle *nsm;
     214                 :            : 
     215         [ #  # ]:          0 :         list_for_each_entry(nsm, nsm_handles, sm_link)
     216         [ #  # ]:          0 :                 if (strlen(nsm->sm_name) == len &&
     217         [ #  # ]:          0 :                     memcmp(nsm->sm_name, hostname, len) == 0)
     218                 :          0 :                         return nsm;
     219                 :            :         return NULL;
     220                 :            : }
     221                 :            : 
     222                 :          0 : static struct nsm_handle *nsm_lookup_addr(const struct list_head *nsm_handles,
     223                 :            :                                         const struct sockaddr *sap)
     224                 :            : {
     225                 :          0 :         struct nsm_handle *nsm;
     226                 :            : 
     227         [ #  # ]:          0 :         list_for_each_entry(nsm, nsm_handles, sm_link)
     228         [ #  # ]:          0 :                 if (rpc_cmp_addr(nsm_addr(nsm), sap))
     229                 :            :                         return nsm;
     230                 :            :         return NULL;
     231                 :            : }
     232                 :            : 
     233                 :          0 : static struct nsm_handle *nsm_lookup_priv(const struct list_head *nsm_handles,
     234                 :            :                                         const struct nsm_private *priv)
     235                 :            : {
     236                 :          0 :         struct nsm_handle *nsm;
     237                 :            : 
     238         [ #  # ]:          0 :         list_for_each_entry(nsm, nsm_handles, sm_link)
     239         [ #  # ]:          0 :                 if (memcmp(nsm->sm_priv.data, priv->data,
     240                 :            :                                         sizeof(priv->data)) == 0)
     241                 :            :                         return nsm;
     242                 :            :         return NULL;
     243                 :            : }
     244                 :            : 
     245                 :            : /*
     246                 :            :  * Construct a unique cookie to match this nsm_handle to this monitored
     247                 :            :  * host.  It is passed to the local rpc.statd via NSMPROC_MON, and
     248                 :            :  * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
     249                 :            :  * requests.
     250                 :            :  *
     251                 :            :  * The NSM protocol requires that these cookies be unique while the
     252                 :            :  * system is running.  We prefer a stronger requirement of making them
     253                 :            :  * unique across reboots.  If user space bugs cause a stale cookie to
     254                 :            :  * be sent to the kernel, it could cause the wrong host to lose its
     255                 :            :  * lock state if cookies were not unique across reboots.
     256                 :            :  *
     257                 :            :  * The cookies are exposed only to local user space via loopback.  They
     258                 :            :  * do not appear on the physical network.  If we want greater security
     259                 :            :  * for some reason, nsm_init_private() could perform a one-way hash to
     260                 :            :  * obscure the contents of the cookie.
     261                 :            :  */
     262                 :          0 : static void nsm_init_private(struct nsm_handle *nsm)
     263                 :            : {
     264                 :          0 :         u64 *p = (u64 *)&nsm->sm_priv.data;
     265                 :          0 :         s64 ns;
     266                 :            : 
     267                 :          0 :         ns = ktime_get_ns();
     268                 :          0 :         put_unaligned(ns, p);
     269                 :          0 :         put_unaligned((unsigned long)nsm, p + 1);
     270                 :            : }
     271                 :            : 
     272                 :          0 : static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
     273                 :            :                                             const size_t salen,
     274                 :            :                                             const char *hostname,
     275                 :            :                                             const size_t hostname_len)
     276                 :            : {
     277                 :          0 :         struct nsm_handle *new;
     278                 :            : 
     279                 :          0 :         new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL);
     280         [ #  # ]:          0 :         if (unlikely(new == NULL))
     281                 :            :                 return NULL;
     282                 :            : 
     283                 :          0 :         refcount_set(&new->sm_count, 1);
     284                 :          0 :         new->sm_name = (char *)(new + 1);
     285                 :          0 :         memcpy(nsm_addr(new), sap, salen);
     286                 :          0 :         new->sm_addrlen = salen;
     287                 :          0 :         nsm_init_private(new);
     288                 :            : 
     289         [ #  # ]:          0 :         if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
     290                 :            :                                         sizeof(new->sm_addrbuf)) == 0)
     291                 :          0 :                 (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
     292                 :            :                                 "unsupported address family");
     293                 :          0 :         memcpy(new->sm_name, hostname, hostname_len);
     294                 :          0 :         new->sm_name[hostname_len] = '\0';
     295                 :            : 
     296                 :          0 :         return new;
     297                 :            : }
     298                 :            : 
     299                 :            : /**
     300                 :            :  * nsm_get_handle - Find or create a cached nsm_handle
     301                 :            :  * @net: network namespace
     302                 :            :  * @sap: pointer to socket address of handle to find
     303                 :            :  * @salen: length of socket address
     304                 :            :  * @hostname: pointer to C string containing hostname to find
     305                 :            :  * @hostname_len: length of C string
     306                 :            :  *
     307                 :            :  * Behavior is modulated by the global nsm_use_hostnames variable.
     308                 :            :  *
     309                 :            :  * Returns a cached nsm_handle after bumping its ref count, or
     310                 :            :  * returns a fresh nsm_handle if a handle that matches @sap and/or
     311                 :            :  * @hostname cannot be found in the handle cache.  Returns NULL if
     312                 :            :  * an error occurs.
     313                 :            :  */
     314                 :          0 : struct nsm_handle *nsm_get_handle(const struct net *net,
     315                 :            :                                   const struct sockaddr *sap,
     316                 :            :                                   const size_t salen, const char *hostname,
     317                 :            :                                   const size_t hostname_len)
     318                 :            : {
     319                 :          0 :         struct nsm_handle *cached, *new = NULL;
     320                 :          0 :         struct lockd_net *ln = net_generic(net, lockd_net_id);
     321                 :            : 
     322   [ #  #  #  # ]:          0 :         if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
     323         [ #  # ]:          0 :                 if (printk_ratelimit()) {
     324                 :          0 :                         printk(KERN_WARNING "Invalid hostname \"%.*s\" "
     325                 :            :                                             "in NFS lock request\n",
     326                 :            :                                 (int)hostname_len, hostname);
     327                 :            :                 }
     328                 :          0 :                 return NULL;
     329                 :            :         }
     330                 :            : 
     331                 :          0 : retry:
     332                 :          0 :         spin_lock(&nsm_lock);
     333                 :            : 
     334   [ #  #  #  # ]:          0 :         if (nsm_use_hostnames && hostname != NULL)
     335                 :          0 :                 cached = nsm_lookup_hostname(&ln->nsm_handles,
     336                 :            :                                         hostname, hostname_len);
     337                 :            :         else
     338                 :          0 :                 cached = nsm_lookup_addr(&ln->nsm_handles, sap);
     339                 :            : 
     340         [ #  # ]:          0 :         if (cached != NULL) {
     341                 :          0 :                 refcount_inc(&cached->sm_count);
     342                 :          0 :                 spin_unlock(&nsm_lock);
     343                 :          0 :                 kfree(new);
     344                 :          0 :                 dprintk("lockd: found nsm_handle for %s (%s), "
     345                 :            :                                 "cnt %d\n", cached->sm_name,
     346                 :            :                                 cached->sm_addrbuf,
     347                 :            :                                 refcount_read(&cached->sm_count));
     348                 :          0 :                 return cached;
     349                 :            :         }
     350                 :            : 
     351         [ #  # ]:          0 :         if (new != NULL) {
     352                 :          0 :                 list_add(&new->sm_link, &ln->nsm_handles);
     353                 :          0 :                 spin_unlock(&nsm_lock);
     354                 :          0 :                 dprintk("lockd: created nsm_handle for %s (%s)\n",
     355                 :            :                                 new->sm_name, new->sm_addrbuf);
     356                 :          0 :                 return new;
     357                 :            :         }
     358                 :            : 
     359                 :          0 :         spin_unlock(&nsm_lock);
     360                 :            : 
     361                 :          0 :         new = nsm_create_handle(sap, salen, hostname, hostname_len);
     362         [ #  # ]:          0 :         if (unlikely(new == NULL))
     363                 :            :                 return NULL;
     364                 :          0 :         goto retry;
     365                 :            : }
     366                 :            : 
     367                 :            : /**
     368                 :            :  * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
     369                 :            :  * @net:  network namespace
     370                 :            :  * @info: pointer to NLMPROC_SM_NOTIFY arguments
     371                 :            :  *
     372                 :            :  * Returns a matching nsm_handle if found in the nsm cache. The returned
     373                 :            :  * nsm_handle's reference count is bumped. Otherwise returns NULL if some
     374                 :            :  * error occurred.
     375                 :            :  */
     376                 :          0 : struct nsm_handle *nsm_reboot_lookup(const struct net *net,
     377                 :            :                                 const struct nlm_reboot *info)
     378                 :            : {
     379                 :          0 :         struct nsm_handle *cached;
     380                 :          0 :         struct lockd_net *ln = net_generic(net, lockd_net_id);
     381                 :            : 
     382                 :          0 :         spin_lock(&nsm_lock);
     383                 :            : 
     384                 :          0 :         cached = nsm_lookup_priv(&ln->nsm_handles, &info->priv);
     385         [ #  # ]:          0 :         if (unlikely(cached == NULL)) {
     386                 :          0 :                 spin_unlock(&nsm_lock);
     387                 :          0 :                 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
     388                 :            :                                 info->len, info->mon);
     389                 :          0 :                 return cached;
     390                 :            :         }
     391                 :            : 
     392                 :          0 :         refcount_inc(&cached->sm_count);
     393                 :          0 :         spin_unlock(&nsm_lock);
     394                 :            : 
     395                 :          0 :         dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
     396                 :            :                         cached->sm_name, cached->sm_addrbuf,
     397                 :            :                         refcount_read(&cached->sm_count));
     398                 :          0 :         return cached;
     399                 :            : }
     400                 :            : 
     401                 :            : /**
     402                 :            :  * nsm_release - Release an NSM handle
     403                 :            :  * @nsm: pointer to handle to be released
     404                 :            :  *
     405                 :            :  */
     406                 :          0 : void nsm_release(struct nsm_handle *nsm)
     407                 :            : {
     408         [ #  # ]:          0 :         if (refcount_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
     409                 :          0 :                 list_del(&nsm->sm_link);
     410                 :          0 :                 spin_unlock(&nsm_lock);
     411                 :          0 :                 dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
     412                 :            :                                 nsm->sm_name, nsm->sm_addrbuf);
     413                 :          0 :                 kfree(nsm);
     414                 :            :         }
     415                 :          0 : }
     416                 :            : 
     417                 :            : /*
     418                 :            :  * XDR functions for NSM.
     419                 :            :  *
     420                 :            :  * See http://www.opengroup.org/ for details on the Network
     421                 :            :  * Status Monitor wire protocol.
     422                 :            :  */
     423                 :            : 
     424                 :          0 : static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
     425                 :            : {
     426                 :          0 :         const u32 len = strlen(string);
     427                 :          0 :         __be32 *p;
     428                 :            : 
     429                 :          0 :         p = xdr_reserve_space(xdr, 4 + len);
     430                 :          0 :         xdr_encode_opaque(p, string, len);
     431                 :          0 : }
     432                 :            : 
     433                 :            : /*
     434                 :            :  * "mon_name" specifies the host to be monitored.
     435                 :            :  */
     436                 :          0 : static void encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
     437                 :            : {
     438                 :          0 :         encode_nsm_string(xdr, argp->mon_name);
     439                 :            : }
     440                 :            : 
     441                 :            : /*
     442                 :            :  * The "my_id" argument specifies the hostname and RPC procedure
     443                 :            :  * to be called when the status manager receives notification
     444                 :            :  * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
     445                 :            :  * has changed.
     446                 :            :  */
     447                 :          0 : static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
     448                 :            : {
     449                 :          0 :         __be32 *p;
     450                 :            : 
     451                 :          0 :         encode_nsm_string(xdr, argp->nodename);
     452                 :          0 :         p = xdr_reserve_space(xdr, 4 + 4 + 4);
     453                 :          0 :         *p++ = cpu_to_be32(argp->prog);
     454                 :          0 :         *p++ = cpu_to_be32(argp->vers);
     455                 :          0 :         *p = cpu_to_be32(argp->proc);
     456                 :          0 : }
     457                 :            : 
     458                 :            : /*
     459                 :            :  * The "mon_id" argument specifies the non-private arguments
     460                 :            :  * of an NSMPROC_MON or NSMPROC_UNMON call.
     461                 :            :  */
     462                 :          0 : static void encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
     463                 :            : {
     464                 :          0 :         encode_mon_name(xdr, argp);
     465                 :          0 :         encode_my_id(xdr, argp);
     466                 :            : }
     467                 :            : 
     468                 :            : /*
     469                 :            :  * The "priv" argument may contain private information required
     470                 :            :  * by the NSMPROC_MON call. This information will be supplied in the
     471                 :            :  * NLMPROC_SM_NOTIFY call.
     472                 :            :  */
     473                 :            : static void encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
     474                 :            : {
     475                 :            :         __be32 *p;
     476                 :            : 
     477                 :            :         p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
     478                 :            :         xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE);
     479                 :            : }
     480                 :            : 
     481                 :          0 : static void nsm_xdr_enc_mon(struct rpc_rqst *req, struct xdr_stream *xdr,
     482                 :            :                             const void *argp)
     483                 :            : {
     484                 :          0 :         encode_mon_id(xdr, argp);
     485                 :          0 :         encode_priv(xdr, argp);
     486                 :          0 : }
     487                 :            : 
     488                 :          0 : static void nsm_xdr_enc_unmon(struct rpc_rqst *req, struct xdr_stream *xdr,
     489                 :            :                               const void *argp)
     490                 :            : {
     491                 :          0 :         encode_mon_id(xdr, argp);
     492                 :          0 : }
     493                 :            : 
     494                 :          0 : static int nsm_xdr_dec_stat_res(struct rpc_rqst *rqstp,
     495                 :            :                                 struct xdr_stream *xdr,
     496                 :            :                                 void *data)
     497                 :            : {
     498                 :          0 :         struct nsm_res *resp = data;
     499                 :          0 :         __be32 *p;
     500                 :            : 
     501                 :          0 :         p = xdr_inline_decode(xdr, 4 + 4);
     502         [ #  # ]:          0 :         if (unlikely(p == NULL))
     503                 :            :                 return -EIO;
     504                 :          0 :         resp->status = be32_to_cpup(p++);
     505                 :          0 :         resp->state = be32_to_cpup(p);
     506                 :            : 
     507                 :          0 :         dprintk("lockd: %s status %d state %d\n",
     508                 :            :                 __func__, resp->status, resp->state);
     509                 :          0 :         return 0;
     510                 :            : }
     511                 :            : 
     512                 :          0 : static int nsm_xdr_dec_stat(struct rpc_rqst *rqstp,
     513                 :            :                             struct xdr_stream *xdr,
     514                 :            :                             void *data)
     515                 :            : {
     516                 :          0 :         struct nsm_res *resp = data;
     517                 :          0 :         __be32 *p;
     518                 :            : 
     519                 :          0 :         p = xdr_inline_decode(xdr, 4);
     520         [ #  # ]:          0 :         if (unlikely(p == NULL))
     521                 :            :                 return -EIO;
     522                 :          0 :         resp->state = be32_to_cpup(p);
     523                 :            : 
     524                 :          0 :         dprintk("lockd: %s state %d\n", __func__, resp->state);
     525                 :          0 :         return 0;
     526                 :            : }
     527                 :            : 
     528                 :            : #define SM_my_name_sz   (1+XDR_QUADLEN(SM_MAXSTRLEN))
     529                 :            : #define SM_my_id_sz     (SM_my_name_sz+3)
     530                 :            : #define SM_mon_name_sz  (1+XDR_QUADLEN(SM_MAXSTRLEN))
     531                 :            : #define SM_mon_id_sz    (SM_mon_name_sz+SM_my_id_sz)
     532                 :            : #define SM_priv_sz      (XDR_QUADLEN(SM_PRIV_SIZE))
     533                 :            : #define SM_mon_sz       (SM_mon_id_sz+SM_priv_sz)
     534                 :            : #define SM_monres_sz    2
     535                 :            : #define SM_unmonres_sz  1
     536                 :            : 
     537                 :            : static const struct rpc_procinfo nsm_procedures[] = {
     538                 :            : [NSMPROC_MON] = {
     539                 :            :                 .p_proc         = NSMPROC_MON,
     540                 :            :                 .p_encode       = nsm_xdr_enc_mon,
     541                 :            :                 .p_decode       = nsm_xdr_dec_stat_res,
     542                 :            :                 .p_arglen       = SM_mon_sz,
     543                 :            :                 .p_replen       = SM_monres_sz,
     544                 :            :                 .p_statidx      = NSMPROC_MON,
     545                 :            :                 .p_name         = "MONITOR",
     546                 :            :         },
     547                 :            : [NSMPROC_UNMON] = {
     548                 :            :                 .p_proc         = NSMPROC_UNMON,
     549                 :            :                 .p_encode       = nsm_xdr_enc_unmon,
     550                 :            :                 .p_decode       = nsm_xdr_dec_stat,
     551                 :            :                 .p_arglen       = SM_mon_id_sz,
     552                 :            :                 .p_replen       = SM_unmonres_sz,
     553                 :            :                 .p_statidx      = NSMPROC_UNMON,
     554                 :            :                 .p_name         = "UNMONITOR",
     555                 :            :         },
     556                 :            : };
     557                 :            : 
     558                 :            : static unsigned int nsm_version1_counts[ARRAY_SIZE(nsm_procedures)];
     559                 :            : static const struct rpc_version nsm_version1 = {
     560                 :            :         .number         = 1,
     561                 :            :         .nrprocs        = ARRAY_SIZE(nsm_procedures),
     562                 :            :         .procs          = nsm_procedures,
     563                 :            :         .counts         = nsm_version1_counts,
     564                 :            : };
     565                 :            : 
     566                 :            : static const struct rpc_version *nsm_version[] = {
     567                 :            :         [1] = &nsm_version1,
     568                 :            : };
     569                 :            : 
     570                 :            : static struct rpc_stat          nsm_stats;
     571                 :            : 
     572                 :            : static const struct rpc_program nsm_program = {
     573                 :            :         .name           = "statd",
     574                 :            :         .number         = NSM_PROGRAM,
     575                 :            :         .nrvers         = ARRAY_SIZE(nsm_version),
     576                 :            :         .version        = nsm_version,
     577                 :            :         .stats          = &nsm_stats
     578                 :            : };

Generated by: LCOV version 1.14