LCOV - code coverage report
Current view: top level - fs/lockd - mon.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 162 0.0 %
Date: 2014-02-18 Functions: 0 23 0.0 %
Branches: 0 84 0.0 %

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

Generated by: LCOV version 1.9