Am-Utils Cross Reference
am-utils/amd/nfs_subr.c

source navigation ]
diff markup ]
identifier search ]
freetext search ]
file search ]
 
Version: 6.0.1 ] [ 6.0.2 ] [ 6.0.3 ] [ 6.0.4 ] [ 6.0.5 ] [ 6.0.6 ] [ 6.0.7 ] [ 6.0.8 ] [ 6.0.9 ] [ 6.0.10 ] [ 6.1 ] [ 6.1.1 ]

  1 /*
  2  * Copyright (c) 1997-2005 Erez Zadok
  3  * Copyright (c) 1990 Jan-Simon Pendry
  4  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  5  * Copyright (c) 1990 The Regents of the University of California.
  6  * All rights reserved.
  7  *
  8  * This code is derived from software contributed to Berkeley by
  9  * Jan-Simon Pendry at Imperial College, London.
 10  *
 11  * Redistribution and use in source and binary forms, with or without
 12  * modification, are permitted provided that the following conditions
 13  * are met:
 14  * 1. Redistributions of source code must retain the above copyright
 15  *    notice, this list of conditions and the following disclaimer.
 16  * 2. Redistributions in binary form must reproduce the above copyright
 17  *    notice, this list of conditions and the following disclaimer in the
 18  *    documentation and/or other materials provided with the distribution.
 19  * 3. All advertising materials mentioning features or use of this software
 20  *    must display the following acknowledgment:
 21  *      This product includes software developed by the University of
 22  *      California, Berkeley and its contributors.
 23  * 4. Neither the name of the University nor the names of its contributors
 24  *    may be used to endorse or promote products derived from this software
 25  *    without specific prior written permission.
 26  *
 27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 37  * SUCH DAMAGE.
 38  *
 39  *
 40  * File: am-utils/amd/nfs_subr.c
 41  *
 42  */
 43 
 44 #ifdef HAVE_CONFIG_H
 45 # include <config.h>
 46 #endif /* HAVE_CONFIG_H */
 47 #include <am_defs.h>
 48 #include <amd.h>
 49 
 50 /*
 51  * Convert from UN*X to NFS error code.
 52  * Some systems like linux define their own (see
 53  * conf/mount/mount_linux.h).
 54  */
 55 #ifndef nfs_error
 56 # define nfs_error(e) ((nfsstat)(e))
 57 #endif /* nfs_error */
 58 
 59 /*
 60  * File Handle structure
 61  *
 62  * This is interpreted by indexing the exported array
 63  * by fhh_id (for old-style filehandles), or by retrieving
 64  * the node name from fhh_path (for new-style filehandles).
 65  *
 66  * The whole structure is mapped onto a standard fhandle_t
 67  * when transmitted.
 68  */
 69 struct am_fh {
 70   u_int fhh_gen;                                /* generation number */
 71   union {
 72     struct {
 73       int fhh_type;                             /* old or new am_fh */
 74       int fhh_pid;                              /* process id */
 75       int fhh_id;                               /* map id */
 76     } s;
 77     char fhh_path[NFS_FHSIZE-sizeof(u_int)];    /* path to am_node */
 78   } u;
 79 };
 80 
 81 
 82 /* forward declarations */
 83 /* converting am-filehandles to mount-points */
 84 static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
 85 static am_node *fh_to_mp(am_nfs_fh *fhp);
 86 static void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail);
 87 
 88 
 89 static char *
 90 do_readlink(am_node *mp, int *error_return)
 91 {
 92   char *ln;
 93 
 94   /*
 95    * If there is a readlink method then use it,
 96    * otherwise if a link exists use that,
 97    * otherwise use the mount point.
 98    */
 99   if (mp->am_mnt->mf_ops->readlink) {
100     int retry = 0;
101     mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry);
102     if (mp == 0) {
103       *error_return = retry;
104       return 0;
105     }
106     /* reschedule_timeout_mp(); */
107   }
108 
109   if (mp->am_link) {
110     ln = mp->am_link;
111   } else {
112     ln = mp->am_mnt->mf_mount;
113   }
114 
115   return ln;
116 }
117 
118 
119 voidp
120 nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
121 {
122   static char res;
123 
124   return (voidp) &res;
125 }
126 
127 
128 nfsattrstat *
129 nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
130 {
131   static nfsattrstat res;
132   am_node *mp;
133   int retry;
134   time_t now = clocktime();
135 
136   if (amuDebug(D_TRACE))
137     plog(XLOG_DEBUG, "getattr:");
138 
139   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
140   if (mp == 0) {
141     if (amuDebug(D_TRACE))
142       plog(XLOG_DEBUG, "\tretry=%d", retry);
143 
144     if (retry < 0) {
145       amd_stats.d_drops++;
146       return 0;
147     }
148     res.ns_status = nfs_error(retry);
149     return &res;
150   }
151 
152   res = mp->am_attr;
153   if (amuDebug(D_TRACE))
154     plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld",
155          mp->am_path,
156          (int) res.ns_u.ns_attr_u.na_size,
157          (long) res.ns_u.ns_attr_u.na_mtime.nt_seconds);
158 
159   /* Delay unmount of what was looked up */
160   if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
161     mp->am_timeo_w += gopt.am_timeo_w;
162   mp->am_ttl = now + mp->am_timeo_w;
163 
164   mp->am_stats.s_getattr++;
165   return &res;
166 }
167 
168 
169 nfsattrstat *
170 nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
171 {
172   static nfsattrstat res;
173 
174   if (!fh_to_mp(&argp->sag_fhandle))
175     res.ns_status = nfs_error(ESTALE);
176   else
177     res.ns_status = nfs_error(EROFS);
178 
179   return &res;
180 }
181 
182 
183 voidp
184 nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
185 {
186   static char res;
187 
188   return (voidp) &res;
189 }
190 
191 
192 nfsdiropres *
193 nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
194 {
195   static nfsdiropres res;
196   am_node *mp;
197   int retry;
198   uid_t uid;
199   gid_t gid;
200 
201   if (amuDebug(D_TRACE))
202     plog(XLOG_DEBUG, "lookup:");
203 
204   /* finally, find the effective uid/gid from RPC request */
205   if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0)
206     plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials");
207   sprintf(opt_uid, "%d", (int) uid);
208   sprintf(opt_gid, "%d", (int) gid);
209 
210   mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
211   if (mp == 0) {
212     if (retry < 0) {
213       amd_stats.d_drops++;
214       return 0;
215     }
216     res.dr_status = nfs_error(retry);
217   } else {
218     int error;
219     am_node *ap;
220     if (amuDebug(D_TRACE))
221       plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name);
222     ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE);
223     if (ap && error < 0)
224       ap = mp->am_mnt->mf_ops->mount_child(ap, &error);
225     if (ap == 0) {
226       if (error < 0) {
227         amd_stats.d_drops++;
228         return 0;
229       }
230       res.dr_status = nfs_error(error);
231     } else {
232       /*
233        * XXX: EXPERIMENTAL! Delay unmount of what was looked up.  This
234        * should reduce the chance for race condition between unmounting an
235        * entry synchronously, and re-mounting it asynchronously.
236        */
237       if (ap->am_ttl < mp->am_ttl)
238         ap->am_ttl = mp->am_ttl;
239       mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle);
240       res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr;
241       res.dr_status = NFS_OK;
242     }
243     mp->am_stats.s_lookup++;
244     /* reschedule_timeout_mp(); */
245   }
246 
247   return &res;
248 }
249 
250 
251 void
252 nfs_quick_reply(am_node *mp, int error)
253 {
254   SVCXPRT *transp = mp->am_transp;
255   nfsdiropres res;
256   xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
257 
258   /*
259    * If there's a transp structure then we can reply to the client's
260    * nfs lookup request.
261    */
262   if (transp) {
263     if (error == 0) {
264       /*
265        * Construct a valid reply to a lookup request.  Same
266        * code as in nfsproc_lookup_2_svc() above.
267        */
268       mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
269       res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
270       res.dr_status = NFS_OK;
271     } else
272       /*
273        * Return the error that was passed to us.
274        */
275       res.dr_status = nfs_error(error);
276 
277     /*
278      * Send off our reply
279      */
280     if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res))
281       svcerr_systemerr(transp);
282 
283     /*
284      * Free up transp.  It's only used for one reply.
285      */
286     XFREE(mp->am_transp);
287     dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
288   }
289 }
290 
291 
292 nfsreadlinkres *
293 nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
294 {
295   static nfsreadlinkres res;
296   am_node *mp;
297   int retry;
298 
299   if (amuDebug(D_TRACE))
300     plog(XLOG_DEBUG, "readlink:");
301 
302   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
303   if (mp == 0) {
304   readlink_retry:
305     if (retry < 0) {
306       amd_stats.d_drops++;
307       return 0;
308     }
309     res.rlr_status = nfs_error(retry);
310   } else {
311     char *ln = do_readlink(mp, &retry);
312     if (ln == 0)
313       goto readlink_retry;
314     res.rlr_status = NFS_OK;
315     if (amuDebug(D_TRACE) && ln)
316       plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
317     res.rlr_u.rlr_data_u = ln;
318     mp->am_stats.s_readlink++;
319   }
320 
321   return &res;
322 }
323 
324 
325 nfsreadres *
326 nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
327 {
328   static nfsreadres res;
329 
330   memset((char *) &res, 0, sizeof(res));
331   res.rr_status = nfs_error(EACCES);
332 
333   return &res;
334 }
335 
336 
337 voidp
338 nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
339 {
340   static char res;
341 
342   return (voidp) &res;
343 }
344 
345 
346 nfsattrstat *
347 nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
348 {
349   static nfsattrstat res;
350 
351   if (!fh_to_mp(&argp->wra_fhandle))
352     res.ns_status = nfs_error(ESTALE);
353   else
354     res.ns_status = nfs_error(EROFS);
355 
356   return &res;
357 }
358 
359 
360 nfsdiropres *
361 nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
362 {
363   static nfsdiropres res;
364 
365   if (!fh_to_mp(&argp->ca_where.da_fhandle))
366     res.dr_status = nfs_error(ESTALE);
367   else
368     res.dr_status = nfs_error(EROFS);
369 
370   return &res;
371 }
372 
373 
374 static nfsstat *
375 unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
376 {
377   static nfsstat res;
378   int retry;
379 
380   am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE);
381   if (mp == 0) {
382     if (retry < 0) {
383       amd_stats.d_drops++;
384       return 0;
385     }
386     res = nfs_error(retry);
387     goto out;
388   }
389 
390   if (mp->am_fattr.na_type != NFDIR) {
391     res = nfs_error(ENOTDIR);
392     goto out;
393   }
394 
395   if (amuDebug(D_TRACE))
396     plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name);
397 
398   mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
399   if (mp == 0) {
400     /*
401      * Ignore retries...
402      */
403     if (retry < 0)
404       retry = 0;
405     /*
406      * Usual NFS workaround...
407      */
408     else if (retry == ENOENT)
409       retry = 0;
410     res = nfs_error(retry);
411   } else {
412     forcibly_timeout_mp(mp);
413     res = NFS_OK;
414   }
415 
416 out:
417   return &res;
418 }
419 
420 
421 nfsstat *
422 nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
423 {
424   return unlink_or_rmdir(argp, rqstp, TRUE);
425 }
426 
427 
428 nfsstat *
429 nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
430 {
431   static nfsstat res;
432 
433   if (!fh_to_mp(&argp->rna_from.da_fhandle) || !fh_to_mp(&argp->rna_to.da_fhandle))
434     res = nfs_error(ESTALE);
435   /*
436    * If the kernel is doing clever things with referenced files
437    * then let it pretend...
438    */
439   else if (NSTREQ(argp->rna_to.da_name, ".nfs", 4))
440     res = NFS_OK;
441   /*
442    * otherwise a failure
443    */
444   else
445     res = nfs_error(EROFS);
446 
447   return &res;
448 }
449 
450 
451 nfsstat *
452 nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
453 {
454   static nfsstat res;
455 
456   if (!fh_to_mp(&argp->la_fhandle) || !fh_to_mp(&argp->la_to.da_fhandle))
457     res = nfs_error(ESTALE);
458   else
459     res = nfs_error(EROFS);
460 
461   return &res;
462 }
463 
464 
465 nfsstat *
466 nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
467 {
468   static nfsstat res;
469 
470   if (!fh_to_mp(&argp->sla_from.da_fhandle))
471     res = nfs_error(ESTALE);
472   else
473     res = nfs_error(EROFS);
474 
475   return &res;
476 }
477 
478 
479 nfsdiropres *
480 nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
481 {
482   static nfsdiropres res;
483 
484   if (!fh_to_mp(&argp->ca_where.da_fhandle))
485     res.dr_status = nfs_error(ESTALE);
486   else
487     res.dr_status = nfs_error(EROFS);
488 
489   return &res;
490 }
491 
492 
493 nfsstat *
494 nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
495 {
496   return unlink_or_rmdir(argp, rqstp, FALSE);
497 }
498 
499 
500 nfsreaddirres *
501 nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
502 {
503   static nfsreaddirres res;
504   static nfsentry e_res[MAX_READDIR_ENTRIES];
505   am_node *mp;
506   int retry;
507 
508   if (amuDebug(D_TRACE))
509     plog(XLOG_DEBUG, "readdir:");
510 
511   mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
512   if (mp == 0) {
513     if (retry < 0) {
514       amd_stats.d_drops++;
515       return 0;
516     }
517     res.rdr_status = nfs_error(retry);
518   } else {
519     if (amuDebug(D_TRACE))
520       plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
521     res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
522                            (mp, argp->rda_cookie,
523                             &res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
524     mp->am_stats.s_readdir++;
525   }
526 
527   return &res;
528 }
529 
530 
531 nfsstatfsres *
532 nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
533 {
534   static nfsstatfsres res;
535   am_node *mp;
536   int retry;
537   mntent_t mnt;
538 
539   if (amuDebug(D_TRACE))
540     plog(XLOG_DEBUG, "statfs:");
541 
542   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
543   if (mp == 0) {
544     if (retry < 0) {
545       amd_stats.d_drops++;
546       return 0;
547     }
548     res.sfr_status = nfs_error(retry);
549   } else {
550     nfsstatfsokres *fp;
551     if (amuDebug(D_TRACE))
552       plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
553 
554     /*
555      * just return faked up file system information
556      */
557     fp = &res.sfr_u.sfr_reply_u;
558 
559     fp->sfrok_tsize = 1024;
560     fp->sfrok_bsize = 1024;
561 
562     /* check if map is browsable and show_statfs_entries=yes  */
563     if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
564         mp->am_mnt && mp->am_mnt->mf_mopts) {
565       mnt.mnt_opts = mp->am_mnt->mf_mopts;
566       if (amu_hasmntopt(&mnt, "browsable")) {
567         count_map_entries(mp,
568                           &fp->sfrok_blocks,
569                           &fp->sfrok_bfree,
570                           &fp->sfrok_bavail);
571       }
572     } else {
573       fp->sfrok_blocks = 0; /* set to 1 if you don't want empty automounts */
574       fp->sfrok_bfree = 0;
575       fp->sfrok_bavail = 0;
576     }
577 
578     res.sfr_status = NFS_OK;
579     mp->am_stats.s_statfs++;
580   }
581 
582   return &res;
583 }
584 
585 
586 /*
587  * count how many total entries there are in a map, and how many
588  * of them are in use.
589  */
590 static void
591 count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail)
592 {
593   u_int blocks, bfree, bavail, i;
594   mntfs *mf;
595   mnt_map *mmp;
596   kv *k;
597 
598   blocks = bfree = bavail = 0;
599   if (!mp)
600     goto out;
601   mf = mp->am_mnt;
602   if (!mf)
603     goto out;
604   mmp = (mnt_map *) mf->mf_private;
605   if (!mmp)
606     goto out;
607 
608   /* iterate over keys */
609   for (i = 0; i < NKVHASH; i++) {
610     for (k = mmp->kvhash[i]; k ; k = k->next) {
611       if (!k->key)
612         continue;
613       blocks++;
614       /*
615        * XXX: Need to count how many are actively in use and recompute
616        * bfree and bavail based on it.
617        */
618     }
619   }
620 
621 out:
622   *out_blocks = blocks;
623   *out_bfree = bfree;
624   *out_bavail = bavail;
625 }
626 
627 
628 /*
629  * Convert from file handle to automount node.
630  */
631 static am_node *
632 fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
633 {
634   struct am_fh *fp = (struct am_fh *) fhp;
635   am_node *ap = 0;
636 
637   if (fp->u.s.fhh_type != 0) {
638     /* New filehandle type */
639     int len = sizeof(*fhp) - sizeof(fp->fhh_gen);
640     char *path = xmalloc(len+1);
641     /*
642      * Because fhp is treated as a filehandle we use memcpy
643      * instead of xstrlcpy.
644      */
645     memcpy(path, (char *) fp->u.fhh_path, len);
646     path[len] = '\0';
647     /* dlog("fh_to_mp3: new filehandle: %s", path); */
648 
649     ap = path_to_exported_ap(path);
650     XFREE(path);
651   } else {
652     /* dlog("fh_to_mp3: old filehandle: %d", fp->fhh_id); */
653     /*
654      * Check process id matches
655      * If it doesn't then it is probably
656      * from an old kernel-cached filehandle
657      * which is now out of date.
658      */
659     if (fp->u.s.fhh_pid != am_mypid)
660       goto drop;
661 
662     /*
663      * Get hold of the supposed mount node
664      */
665     ap = get_exported_ap(fp->u.s.fhh_id);
666   }
667 
668   /*
669    * Check the generation number in the node
670    * matches the one from the kernel.  If not
671    * then the old node has been timed out and
672    * a new one allocated.
673    */
674   if (ap != NULL && ap->am_gen != fp->fhh_gen)
675     ap = 0;
676 
677   /*
678    * If it doesn't exists then drop the request
679    */
680   if (!ap)
681     goto drop;
682 
683 #if 0
684   /*
685    * If the node is hung then locate a new node
686    * for it.  This implements the replicated filesystem
687    * retries.
688    */
689   if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
690     int error;
691     am_node *orig_ap = ap;
692 
693     dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server",
694          orig_ap->am_path, orig_ap->am_mnt->mf_info);
695 
696     /*
697      * Update modify time of parent node.
698      * With any luck the kernel will re-stat
699      * the child node and get new information.
700      */
701     orig_ap->am_fattr.na_mtime.nt_seconds = clocktime();
702 
703     /*
704      * Call the parent's lookup routine for an object
705      * with the same name.  This may return -1 in error
706      * if a mount is in progress.  In any case, if no
707      * mount node is returned the error code is propagated
708      * to the caller.
709      */
710     if (vop == VLOOK_CREATE) {
711       ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop);
712       if (ap && error < 0)
713         ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error);
714     } else {
715       ap = 0;
716       error = ESTALE;
717     }
718     if (ap == 0) {
719       if (error < 0 && amd_state == Finishing)
720         error = ENOENT;
721       *rp = error;
722       return 0;
723     }
724 
725     /*
726      * Update last access to original node.  This
727      * avoids timing it out and so sending ESTALE
728      * back to the kernel.
729      * XXX - Not sure we need this anymore (jsp, 90/10/6).
730      */
731     new_ttl(orig_ap);
732 
733   }
734 #endif
735 
736   /*
737    * Disallow references to objects being unmounted, unless
738    * they are automount points.
739    */
740   if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
741       !(ap->am_flags & AMF_ROOT)) {
742     if (amd_state == Finishing)
743       *rp = ENOENT;
744     else
745       *rp = -1;
746     return 0;
747   }
748   new_ttl(ap);
749 
750 drop:
751   if (!ap || !ap->am_mnt) {
752     /*
753      * If we are shutting down then it is likely
754      * that this node has disappeared because of
755      * a fast timeout.  To avoid things thrashing
756      * just pretend it doesn't exist at all.  If
757      * ESTALE is returned, some NFS clients just
758      * keep retrying (stupid or what - if it's
759      * stale now, what's it going to be in 5 minutes?)
760      */
761     if (amd_state == Finishing)
762       *rp = ENOENT;
763     else
764       *rp = ESTALE;
765     amd_stats.d_stale++;
766   }
767 
768   return ap;
769 }
770 
771 
772 static am_node *
773 fh_to_mp(am_nfs_fh *fhp)
774 {
775   int dummy;
776 
777   return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
778 }
779 
780 
781 /*
782  * Convert from automount node to file handle.
783  */
784 void
785 mp_to_fh(am_node *mp, am_nfs_fh *fhp)
786 {
787   u_int pathlen;
788   struct am_fh *fp = (struct am_fh *) fhp;
789 
790   memset((char *) fhp, 0, sizeof(am_nfs_fh));
791 
792   /* Store the generation number */
793   fp->fhh_gen = mp->am_gen;
794 
795   pathlen = strlen(mp->am_path);
796   if (pathlen <= sizeof(*fhp) - sizeof(fp->fhh_gen)) {
797     /* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */
798 
799     /*
800      * Because fhp is treated as a filehandle we use memcpy instead of
801      * xstrlcpy.
802      */
803     memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */
804   } else {
805     /*
806      * Take the process id
807      */
808     fp->u.s.fhh_pid = am_mypid;
809 
810     /*
811      * ... the map number
812      */
813     fp->u.s.fhh_id = mp->am_mapno;
814 
815     /*
816      * ... and the generation number (previously stored)
817      * to make a "unique" triple that will never
818      * be reallocated except across reboots (which doesn't matter)
819      * or if we are unlucky enough to be given the same
820      * pid as a previous amd (very unlikely).
821      */
822     /* dlog("mp_to_fh: old filehandle: %d", fp->fhh_id); */
823   }
824 }
825 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
This page is hosted at the Filesystems and Storage Lab at Stony Brook.