1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 1994-2002 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * RPC service routines.
  31  */
  32 
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <string.h>
  36 #include <errno.h>
  37 #include <rpc/rpc.h>
  38 #include <rpc/pmap_clnt.h> /* for pmap_unset */
  39 #include <string.h> /* strcmp */
  40 #include <signal.h>
  41 #include <unistd.h> /* setsid */
  42 #include <sys/types.h>
  43 #include <sys/stat.h>
  44 #include <time.h>
  45 #include <memory.h>
  46 #include <stropts.h>
  47 #include <netconfig.h>
  48 #include <sys/resource.h> /* rlimit */
  49 #include <thread.h>
  50 #include <synch.h>
  51 #include <mdbug/mdbug.h>
  52 #include <common/cachefsd.h>
  53 #include <sys/fs/cachefs_fs.h>
  54 #include <sys/fs/cachefs_dlog.h>
  55 #include <sys/fs/cachefs_ioctl.h>
  56 #include "cfsd.h"
  57 #include "cfsd_kmod.h"
  58 #include "cfsd_maptbl.h"
  59 #include "cfsd_logfile.h"
  60 #include "cfsd_fscache.h"
  61 #include "cfsd_cache.h"
  62 #include "cfsd_all.h"
  63 #include "cfsd_subr.h"
  64 
  65 /* declared in cfsd_main.c */
  66 extern cfsd_all_object_t *all_object_p;
  67 
  68 /*
  69  *                      cachefsd_null_1_svc
  70  *
  71  * Description:
  72  *      Routine to process NULLPROC command, see /usr/include/rpc/clnt.h.
  73  * Arguments:
  74  *      inp     should be NULL
  75  *      outp    should be NULL
  76  *      reqp    svc_req info
  77  * Returns:
  78  *      Always returns 1, e.g. returns success result.
  79  * Preconditions:
  80  *      precond(reqp)
  81  */
  82 bool_t
  83 cachefsd_null_1_svc(void *inp, void *outp, struct svc_req *reqp)
  84 {
  85         dbug_enter("cachefsd_null_1_svc");
  86         dbug_precond(reqp);
  87 
  88         dbug_assert(inp == NULL);
  89         dbug_assert(outp == NULL);
  90 
  91         dbug_leave("cachefsd_null_1_svc");
  92         return (1);
  93 }
  94 
  95 /*
  96  *                      cachefsd_caches_1_svc
  97  *
  98  * Description:
  99  *      Returns list of caches on the system.
 100  * Arguments:
 101  *      inp     should be NULL
 102  *      outp    should point to return object
 103  *      reqp    svc_req info
 104  * Returns:
 105  *      Returns 1 for success 0 if an error occurs.
 106  * Preconditions:
 107  *      precond(reqp)
 108  */
 109 bool_t
 110 cachefsd_caches_1_svc(void *inp,
 111         cachefsd_caches_return *outp,
 112         struct svc_req *reqp)
 113 {
 114         size_t cnt;
 115         size_t index;
 116         cfsd_cache_object_t *cache_object_p;
 117         cachefsd_caches_id *headp, *idp;
 118 
 119         dbug_enter("cachefsd_caches_1_svc");
 120         dbug_precond(reqp);
 121 
 122         dbug_assert(inp == NULL);
 123         dbug_assert(outp);
 124 
 125         if (inp || (outp == NULL)) {
 126                 dbug_leave("cachefsd_caches_1_svc");
 127                 return (0);
 128         }
 129         all_lock(all_object_p);
 130         headp = NULL;
 131 
 132         /* if there are any caches */
 133         cnt = all_object_p->i_cachecount;
 134         if (cnt) {
 135                 /* allocate space for each cache information */
 136                 headp = idp = cfsd_calloc(sizeof (cachefsd_caches_id) * cnt);
 137 
 138                 /* for each cache */
 139                 for (index = 0; index < cnt; index++, idp++) {
 140                         /* get the cache */
 141                         cache_object_p = all_cachelist_at(all_object_p, index);
 142                         dbug_assert(cache_object_p);
 143 
 144                         /* get the cache id and name */
 145                         idp->cci_cacheid = cache_object_p->i_cacheid;
 146                         idp->cci_name = subr_strdup(cache_object_p->i_cachedir);
 147                 }
 148         }
 149 
 150         /* fill in the return object */
 151         outp->ccr_modify = all_object_p->i_modify;
 152         outp->ccr_ids.ccr_ids_len = cnt;
 153         outp->ccr_ids.ccr_ids_val = headp;
 154 
 155         all_unlock(all_object_p);
 156 
 157         dbug_leave("cachefsd_caches_1_svc");
 158         return (1);
 159 }
 160 
 161 /*
 162  *                      cachefsd_cache_status_1_svc
 163  *
 164  * Description:
 165  *      Returns status about a particular cache.
 166  * Arguments:
 167  *      inp     should be ptr to cache id
 168  *      outp    should be ptr to place to put cache status
 169  *      reqp    svc_req info
 170  * Returns:
 171  *      Returns 1 for success 0 if an error occurs.
 172  * Preconditions:
 173  *      precond(reqp)
 174  */
 175 bool_t
 176 cachefsd_cache_status_1_svc(int *inp, struct cachefsd_cache_status *outp,
 177     struct svc_req *reqp)
 178 {
 179         cfsd_fscache_object_t *fscache_object_p = NULL;
 180         size_t cnt, index;
 181         cfsd_cache_object_t *cache_object_p;
 182         cfsd_kmod_object_t *kmod_object_p;
 183         cachefsio_getstats_t gs;
 184         int xx;
 185 
 186         dbug_enter("cachefsd_cache_status_1_svc");
 187         dbug_precond(reqp);
 188 
 189         dbug_assert(inp);
 190         dbug_assert(outp);
 191 
 192         if ((inp == NULL) || (outp == NULL)) {
 193                 dbug_leave("cachefsd_cache_status_1_svc");
 194                 return (0);
 195         }
 196         memset(outp, 0, sizeof (*outp));
 197 
 198         /* find the requested cache */
 199         all_lock(all_object_p);
 200         cnt = all_object_p->i_cachecount;
 201         for (index = 0; index < cnt; index++) {
 202                 /* get the cache */
 203                 cache_object_p = all_cachelist_at(all_object_p, index);
 204                 dbug_assert(cache_object_p);
 205 
 206                 /* if a match */
 207                 if (cache_object_p->i_cacheid == *inp) {
 208                         cache_lock(cache_object_p);
 209                         cache_object_p->i_refcnt++;
 210                         cache_unlock(cache_object_p);
 211                         break;
 212                 }
 213         }
 214         all_unlock(all_object_p);
 215 
 216         /* if no match */
 217         if (index >= cnt) {
 218                 dbug_leave("cachefsd_cache_status_1_svc");
 219                 return (1);
 220         }
 221         /* find a mounted file system in the cache */
 222         cache_lock(cache_object_p);
 223         cnt = cache_object_p->i_fscachecount;
 224         for (index = 0; index < cnt; index++) {
 225                 /* get the fscache */
 226                 fscache_object_p = cache_fscachelist_at(cache_object_p, index);
 227                 dbug_assert(fscache_object_p);
 228 
 229                 /* mounted */
 230                 if (fscache_object_p->i_mounted) {
 231                         fscache_lock(fscache_object_p);
 232                         fscache_object_p->i_refcnt++;
 233                         fscache_unlock(fscache_object_p);
 234                         break;
 235                 }
 236                 fscache_object_p = NULL;
 237         }
 238         cache_unlock(cache_object_p);
 239 
 240         outp->ccs_size = 0;
 241         outp->ccs_lrusize = 0;
 242         outp->ccs_packsize = 0;
 243         outp->ccs_freesize = 0;
 244         outp->ccs_lrutime = 0;
 245 
 246         kmod_object_p = cfsd_kmod_create();
 247         if (fscache_object_p) {
 248                 xx = kmod_setup(kmod_object_p, fscache_object_p->i_mntpt);
 249                 if (xx != 0) {
 250                         dbug_print(("err",
 251                             "setup of kmod interface failed %d", xx));
 252                 } else if ((xx = kmod_getstats(kmod_object_p, &gs)) != 0) {
 253                         dbug_print(("err", "getstat failed %d", xx));
 254                 } else {
 255                         outp->ccs_size = gs.gs_total;
 256                         outp->ccs_lrusize = gs.gs_gc + gs.gs_active;
 257                         outp->ccs_packsize = gs.gs_packed;
 258                         outp->ccs_freesize = gs.gs_free;
 259                         outp->ccs_lrutime = gs.gs_gctime;
 260 
 261                         fscache_lock(fscache_object_p);
 262                         fscache_object_p->i_refcnt--;
 263                         fscache_unlock(fscache_object_p);
 264                 }
 265         }
 266         cfsd_kmod_destroy(kmod_object_p);
 267 
 268         outp->ccs_id = cache_object_p->i_cacheid;
 269         outp->ccs_name = subr_strdup(cache_object_p->i_cachedir);
 270         outp->ccs_modify = cache_object_p->i_modify;
 271         cache_lock(cache_object_p);
 272         cache_object_p->i_refcnt--;
 273         cache_unlock(cache_object_p);
 274 
 275         dbug_leave("cachefsd_cache_status_1_svc");
 276         return (1);
 277 }
 278 
 279 /*
 280  *                      cachefsd_mounts_1_svc
 281  *
 282  * Description:
 283  *      Returns the list of file systems that are in the cache.
 284  * Arguments:
 285  *      inp     should be ptr to cache id
 286  *      outp    should be ptr to place to put mounts
 287  *      reqp    svc_req info
 288  * Returns:
 289  *      Returns 1 for success 0 if an internal error occurs.
 290  * Preconditions:
 291  *      precond(reqp)
 292  */
 293 bool_t
 294 cachefsd_mounts_1_svc(int *inp, struct cachefsd_mount_returns *outp,
 295     struct svc_req *reqp)
 296 {
 297         size_t cnt, index;
 298         cfsd_cache_object_t *cache_object_p;
 299         cfsd_fscache_object_t *fscache_object_p;
 300         struct cachefsd_mount *headp, *idp;
 301 
 302         dbug_enter("cachefsd_mounts_1_svc");
 303         dbug_precond(reqp);
 304 
 305         dbug_assert(inp);
 306         dbug_assert(outp);
 307         if ((inp == NULL) || (outp == NULL)) {
 308                 dbug_leave("cachefsd_mounts_1_svc");
 309                 return (0);
 310         }
 311         memset(outp, 0, sizeof (*outp));
 312 
 313         /* find the requested cache */
 314         all_lock(all_object_p);
 315         cnt = all_object_p->i_cachecount;
 316         for (index = 0; index < cnt; index++) {
 317                 /* get the cache */
 318                 cache_object_p = all_cachelist_at(all_object_p, index);
 319                 dbug_assert(cache_object_p);
 320 
 321                 /* if a match */
 322                 if (cache_object_p->i_cacheid == *inp) {
 323                         cache_lock(cache_object_p);
 324                         cache_object_p->i_refcnt++;
 325                         cache_unlock(cache_object_p);
 326                         break;
 327                 }
 328         }
 329         all_unlock(all_object_p);
 330 
 331         /* if no match was found */
 332         if (index >= cnt) {
 333                 outp->cmr_error = ENOENT;
 334                 dbug_leave("cachefsd_mounts_1_svc");
 335                 return (1);
 336         }
 337 
 338         cache_lock(cache_object_p);
 339         headp = NULL;
 340 
 341         /* if there are any fscaches */
 342         cnt = cache_object_p->i_fscachecount;
 343         if (cnt) {
 344                 /* allocate space for each fscache information */
 345                 headp = idp = cfsd_calloc(sizeof (cachefsd_mount) * cnt);
 346                 /* for each fscache */
 347                 for (index = 0; index < cnt; index++, idp++) {
 348                         /* get the fscache */
 349                         fscache_object_p =
 350                             cache_fscachelist_at(cache_object_p, index);
 351                         dbug_assert(fscache_object_p);
 352 
 353                         /* get the fscache id and name */
 354                         idp->cm_fsid = fscache_object_p->i_fscacheid;
 355                         idp->cm_name = subr_strdup(fscache_object_p->i_name);
 356                 }
 357         }
 358 
 359         /* fill in the return object */
 360         outp->cmr_modify = cache_object_p->i_modify;
 361         outp->cmr_error = 0;
 362         outp->cmr_names.cmr_names_len = cnt;
 363         outp->cmr_names.cmr_names_val = headp;
 364 
 365         cache_object_p->i_refcnt--;
 366         cache_unlock(cache_object_p);
 367 
 368         dbug_leave("cachefsd_mounts_1_svc");
 369         return (1);
 370 }
 371 
 372 /*
 373  *                      cachefsd_mount_stat_1_svc
 374  *
 375  * Description:
 376  *      Returns status information about a single file system
 377  *      in the cache.
 378  * Arguments:
 379  *      inp     should be which file system to get info for
 380  *      outp    should be place to put mount info
 381  *      reqp    svc_req info
 382  * Returns:
 383  *      Returns 1 for success 0 if an error occurs.
 384  * Preconditions:
 385  *      precond(reqp)
 386  */
 387 bool_t
 388 cachefsd_mount_stat_1_svc(struct cachefsd_mount_stat_args *inp,
 389     struct cachefsd_mount_stat *outp, struct svc_req *reqp)
 390 {
 391         size_t cnt, index;
 392         cfsd_cache_object_t *cache_object_p;
 393         cfsd_fscache_object_t *fscache_object_p;
 394         char namebuf[MAXPATHLEN];
 395         struct stat sinfo;
 396 
 397         dbug_enter("cachefsd_mount_stat_1_svc");
 398         dbug_precond(reqp);
 399 
 400         dbug_assert(inp);
 401         dbug_assert(outp);
 402         if ((inp == NULL) || (outp == NULL)) {
 403                 dbug_leave("cachefsd_mount_stat_1_svc");
 404                 return (0);
 405         }
 406         memset(outp, 0, sizeof (*outp));
 407 
 408         /* find the requested cache */
 409         all_lock(all_object_p);
 410         cnt = all_object_p->i_cachecount;
 411         for (index = 0; index < cnt; index++) {
 412                 /* get the cache */
 413                 cache_object_p = all_cachelist_at(all_object_p, index);
 414                 dbug_assert(cache_object_p);
 415 
 416                 /* if a match */
 417                 if (cache_object_p->i_cacheid == inp->cma_cacheid) {
 418                         cache_lock(cache_object_p);
 419                         cache_object_p->i_refcnt++;
 420                         cache_unlock(cache_object_p);
 421                         break;
 422                 }
 423         }
 424         all_unlock(all_object_p);
 425 
 426         /* if no match was found */
 427         if (index >= cnt) {
 428                 dbug_leave("cachefsd_mount_stat_1_svc");
 429                 return (1);
 430         }
 431 
 432         /* find the requested fscache */
 433         cache_lock(cache_object_p);
 434         cnt = cache_object_p->i_fscachecount;
 435         for (index = 0; index < cnt; index++) {
 436                 /* get the fscache */
 437                 fscache_object_p = cache_fscachelist_at(cache_object_p, index);
 438                 dbug_assert(fscache_object_p);
 439 
 440                 /* if a match */
 441                 if (fscache_object_p->i_fscacheid == inp->cma_fsid) {
 442                         fscache_lock(fscache_object_p);
 443                         fscache_object_p->i_refcnt++;
 444                         fscache_unlock(fscache_object_p);
 445                         break;
 446                 }
 447         }
 448         cache_unlock(cache_object_p);
 449 
 450         /* if no match was found */
 451         if (index >= cnt) {
 452                 cache_lock(cache_object_p);
 453                 cache_object_p->i_refcnt--;
 454                 cache_unlock(cache_object_p);
 455                 dbug_leave("cachefsd_mount_stat_1_svc");
 456                 return (1);
 457         }
 458 
 459         fscache_lock(fscache_object_p);
 460 
 461         /* see if there are changes to roll to the server */
 462         if ((fscache_object_p->i_connected == 0) &&
 463             (fscache_object_p->i_changes == 0)) {
 464                 snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
 465                     cache_object_p->i_cachedir, fscache_object_p->i_name,
 466                     CACHEFS_DLOG_FILE);
 467                 if (stat(namebuf, &sinfo) == 0) {
 468                         fscache_changes(fscache_object_p, 1);
 469                 }
 470         }
 471 
 472         /* fill in the return object */
 473         outp->cms_cacheid = cache_object_p->i_cacheid;
 474         outp->cms_fsid = fscache_object_p->i_fscacheid;
 475         outp->cms_name = subr_strdup(fscache_object_p->i_name);
 476         outp->cms_backfs = subr_strdup(fscache_object_p->i_backfs);
 477         outp->cms_mountpt = subr_strdup(fscache_object_p->i_mntpt);
 478         outp->cms_backfstype = subr_strdup(fscache_object_p->i_backfstype);
 479         outp->cms_writemode = NULL;
 480         outp->cms_options = subr_strdup(fscache_object_p->i_cfsopt);
 481         outp->cms_mounted = fscache_object_p->i_mounted;
 482         outp->cms_connected = fscache_object_p->i_connected;
 483         outp->cms_reconcile = fscache_object_p->i_reconcile;
 484         outp->cms_changes = fscache_object_p->i_changes;
 485         outp->cms_time_state = fscache_object_p->i_time_state;
 486         outp->cms_mnttime = fscache_object_p->i_time_mnt;
 487         outp->cms_modify = fscache_object_p->i_modify;
 488 
 489         fscache_object_p->i_refcnt--;
 490         fscache_unlock(fscache_object_p);
 491 
 492         cache_lock(cache_object_p);
 493         cache_object_p->i_refcnt--;
 494         cache_unlock(cache_object_p);
 495 
 496         dbug_leave("cachefsd_mount_stat_1_svc");
 497         return (1);
 498 }
 499 
 500 /*
 501  *                      cachefsd_fs_mounted_1_svc
 502  *
 503  * Description:
 504  *      Sent by the mount command to indicate a new file system
 505  *      has been mounted
 506  * Arguments:
 507  *      inp     ptr to mount information
 508  *      outp    should be null
 509  *      reqp    svc_req info
 510  * Returns:
 511  *      Returns 1 for success 0 if an internal error occurs.
 512  * Preconditions:
 513  *      precond(inp)
 514  */
 515 bool_t
 516 cachefsd_fs_mounted_1_svc(struct cachefsd_fs_mounted *inp, void *outp,
 517     struct svc_req *reqp)
 518 {
 519         int error = 0;
 520 
 521         dbug_enter("cachefsd_fs_mounted_1_svc");
 522         dbug_precond(reqp);
 523 
 524         dbug_assert(inp);
 525         dbug_assert(outp == NULL);
 526         if ((inp == NULL) || outp) {
 527                 dbug_leave("cachefsd_fs_mounted_1_svc");
 528                 return (0);
 529         }
 530 
 531         if (inp->mt_cachedir == NULL) {
 532                 dbug_print(("error", "cachedir is null"));
 533                 error = 1;
 534         }
 535         if (inp->mt_cacheid == NULL) {
 536                 dbug_print(("error", "cacheid is null"));
 537                 error = 1;
 538         }
 539 
 540         if (error == 0) {
 541                 dbug_print(("info", "Mounted in %s file system %s",
 542                     inp->mt_cachedir, inp->mt_cacheid));
 543                 subr_add_mount(all_object_p, inp->mt_cachedir, inp->mt_cacheid);
 544         }
 545 
 546         dbug_leave("cachefsd_fs_mounted_1_svc");
 547         return (1);
 548 }
 549 
 550 /*
 551  *                      cachefsd_fs_unmounted_1_svc
 552  *
 553  * Description:
 554  * Arguments:
 555  *      inp
 556  *      outp
 557  *      reqp
 558  * Returns:
 559  *      Returns 1 for success 0 if an internal error occurs.
 560  * Preconditions:
 561  *      precond(inp)
 562  *      precond(outp == NULL)
 563  *      precond(reqp)
 564  */
 565 bool_t
 566 cachefsd_fs_unmounted_1_svc(struct cachefsd_fs_unmounted *inp, int *outp,
 567     struct svc_req *reqp)
 568 {
 569         size_t cnt1, cnt2, index1, index2;
 570         cfsd_cache_object_t *cache_object_p;
 571         cfsd_fscache_object_t *fscache_object_p = NULL;
 572         int found = 0;
 573         int flag = 0;
 574 
 575         dbug_enter("cachefsd_fs_unmounted_1_svc");
 576 
 577         dbug_precond(inp);
 578         dbug_precond(outp);
 579         dbug_precond(reqp);
 580 
 581         if ((inp == NULL) || (outp == NULL)) {
 582                 dbug_leave("cachefsd_fs_unmounted_1_svc");
 583                 return (0);
 584         }
 585         memset(outp, 0, sizeof (*outp));
 586 
 587         if (inp->mntpt == NULL) {
 588                 dbug_print(("error", "mntpt is null"));
 589                 *outp = EIO;
 590                 dbug_leave("cachefsd_fs_unmounted_1_svc");
 591                 return (1);
 592         }
 593 
 594         /* for each cache */
 595         all_lock(all_object_p);
 596         cnt1 = all_object_p->i_cachecount;
 597         for (index1 = 0; index1 < cnt1; index1++) {
 598                 /* get the cache */
 599                 cache_object_p = all_cachelist_at(all_object_p, index1);
 600                 dbug_assert(cache_object_p);
 601 
 602                 /* for each file system in this cache */
 603                 cache_lock(cache_object_p);
 604                 cnt2 = cache_object_p->i_fscachecount;
 605                 for (index2 = 0; index2 < cnt2; index2++) {
 606                         /* get the fscache */
 607                         fscache_object_p =
 608                             cache_fscachelist_at(cache_object_p, index2);
 609                         dbug_assert(fscache_object_p);
 610 
 611                         /* skip if not mounted */
 612                         if (fscache_object_p->i_mounted == 0)
 613                                 continue;
 614 
 615                         /* if a match */
 616                         if (strcmp(fscache_object_p->i_mntpt,
 617                                 inp->mntpt) == 0) {
 618                                 fscache_lock(fscache_object_p);
 619                                 fscache_object_p->i_refcnt++;
 620                                 flag = inp->flag;
 621                                 fscache_unlock(fscache_object_p);
 622                                 found = 1;
 623                                 break;
 624                         }
 625                 }
 626                 cache_unlock(cache_object_p);
 627                 if (found)
 628                         break;
 629                 fscache_object_p = NULL;
 630         }
 631         all_unlock(all_object_p);
 632 
 633         /* if no match */
 634         if (fscache_object_p == NULL) {
 635                 *outp = EIO;
 636         } else {
 637                 *outp = fscache_unmount(fscache_object_p, flag);
 638 
 639                 fscache_lock(fscache_object_p);
 640                 fscache_object_p->i_refcnt--;
 641                 fscache_unlock(fscache_object_p);
 642         }
 643         dbug_leave("cachefsd_fs_unmounted_1_svc");
 644         return (1);
 645 }
 646 
 647 /*
 648  *                      cachefsd_disconnection_1_svc
 649  *
 650  * Description:
 651  * Arguments:
 652  *      inp
 653  *      outp
 654  *      reqp
 655  * Returns:
 656  *      Returns 1 for success 0 if an internal error occurs.
 657  * Preconditions:
 658  *      precond(inp)
 659  *      precond(outp)
 660  *      precond(reqp)
 661  */
 662 bool_t
 663 cachefsd_disconnection_1_svc(struct cachefsd_disconnection_args *inp, int *outp,
 664     struct svc_req *reqp)
 665 {
 666         size_t cnt1, cnt2, index1, index2;
 667         cfsd_cache_object_t *cache_object_p;
 668         cfsd_fscache_object_t *fscache_object_p = NULL;
 669         int found = 0;
 670 
 671         dbug_enter("cachefsd_disconnection_1_svc");
 672 
 673         dbug_precond(inp);
 674         dbug_precond(outp);
 675         dbug_precond(reqp);
 676 
 677         if ((inp == NULL) || (outp == NULL)) {
 678                 dbug_leave("cachefsd_disconnection_1_svc");
 679                 return (0);
 680         }
 681         memset(outp, 0, sizeof (*outp));
 682 
 683         /* for each cache */
 684         all_lock(all_object_p);
 685         cnt1 = all_object_p->i_cachecount;
 686         for (index1 = 0; index1 < cnt1; index1++) {
 687                 /* get the cache */
 688                 cache_object_p = all_cachelist_at(all_object_p, index1);
 689                 dbug_assert(cache_object_p);
 690 
 691                 /* for each file system in this cache */
 692                 cache_lock(cache_object_p);
 693                 cnt2 = cache_object_p->i_fscachecount;
 694                 for (index2 = 0; index2 < cnt2; index2++) {
 695                         /* get the fscache */
 696                         fscache_object_p =
 697                             cache_fscachelist_at(cache_object_p, index2);
 698                         dbug_assert(fscache_object_p);
 699 
 700                         /* if a match */
 701                         if (strcmp(fscache_object_p->i_mntpt, inp->cda_mntpt)
 702                             == 0) {
 703                                 fscache_lock(fscache_object_p);
 704                                 fscache_object_p->i_refcnt++;
 705                                 fscache_unlock(fscache_object_p);
 706                                 found = 1;
 707                                 break;
 708                         }
 709                 }
 710                 cache_unlock(cache_object_p);
 711                 if (found)
 712                         break;
 713                 fscache_object_p = NULL;
 714         }
 715         all_unlock(all_object_p);
 716 
 717         /* if no match */
 718         if (fscache_object_p == NULL) {
 719                 *outp = 3;
 720         } else {
 721                 *outp = fscache_simdisconnect(fscache_object_p,
 722                     inp->cda_disconnect);
 723 
 724                 fscache_lock(fscache_object_p);
 725                 fscache_object_p->i_refcnt--;
 726                 fscache_unlock(fscache_object_p);
 727         }
 728         dbug_leave("cachefsd_disconnection_1_svc");
 729         return (1);
 730 }
 731 
 732 /*
 733  *                      cachefsdprog_1_freeresult
 734  *
 735  * Description:
 736  * Arguments:
 737  *      transp
 738  *      xdr_result
 739  *      resultp
 740  * Returns:
 741  *      Returns ...
 742  * Preconditions:
 743  *      precond(transp)
 744  */
 745 int
 746 cachefsdprog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
 747         caddr_t resultp)
 748 {
 749         dbug_enter("cachefsdprog_1_freeresult");
 750 
 751         dbug_precond(transp);
 752 
 753         (void) xdr_free(xdr_result, resultp);
 754         dbug_leave("cachefsdprog_1_freeresult");
 755         return (1);
 756 }