nfs_subr.c revision 42629
138494Sobrien/* 238494Sobrien * Copyright (c) 1997-1998 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 1938494Sobrien * 3. All advertising materials mentioning features or use of this software 2042629Sobrien * must display the following acknowledgment: 2138494Sobrien * This product includes software developed by the University of 2238494Sobrien * California, Berkeley and its contributors. 2338494Sobrien * 4. Neither the name of the University nor the names of its contributors 2438494Sobrien * may be used to endorse or promote products derived from this software 2538494Sobrien * without specific prior written permission. 2638494Sobrien * 2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738494Sobrien * SUCH DAMAGE. 3838494Sobrien * 3938494Sobrien * %W% (Berkeley) %G% 4038494Sobrien * 4142629Sobrien * $Id: nfs_subr.c,v 1.1.1.1 1998/11/05 02:04:48 ezk Exp $ 4238494Sobrien * 4338494Sobrien */ 4438494Sobrien 4538494Sobrien#ifdef HAVE_CONFIG_H 4638494Sobrien# include <config.h> 4738494Sobrien#endif /* HAVE_CONFIG_H */ 4838494Sobrien#include <am_defs.h> 4938494Sobrien#include <amd.h> 5038494Sobrien 5138494Sobrien/* 5238494Sobrien * Convert from UN*X to NFS error code. 5338494Sobrien * Some systems like linux define their own (see 5438494Sobrien * conf/mount/mount_linux.h). 5538494Sobrien */ 5638494Sobrien#ifndef nfs_error 5738494Sobrien# define nfs_error(e) ((nfsstat)(e)) 5838494Sobrien#endif /* nfs_error */ 5938494Sobrien 6038494Sobrien/* forward declarations */ 6138494Sobrienstatic void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail); 6238494Sobrien 6338494Sobrien 6438494Sobrienstatic char * 6538494Sobriendo_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp) 6638494Sobrien{ 6738494Sobrien char *ln; 6838494Sobrien 6938494Sobrien /* 7038494Sobrien * If there is a readlink method, then use 7138494Sobrien * that, otherwise if a link exists use 7238494Sobrien * that, otherwise use the mount point. 7338494Sobrien */ 7438494Sobrien if (mp->am_mnt->mf_ops->readlink) { 7538494Sobrien int retry = 0; 7638494Sobrien mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry); 7738494Sobrien if (mp == 0) { 7838494Sobrien *error_return = retry; 7938494Sobrien return 0; 8038494Sobrien } 8138494Sobrien /* reschedule_timeout_mp(); */ 8238494Sobrien } 8338494Sobrien 8438494Sobrien if (mp->am_link) { 8538494Sobrien ln = mp->am_link; 8638494Sobrien } else { 8738494Sobrien ln = mp->am_mnt->mf_mount; 8838494Sobrien } 8938494Sobrien if (attrpp) 9038494Sobrien *attrpp = &mp->am_attr; 9138494Sobrien 9238494Sobrien return ln; 9338494Sobrien} 9438494Sobrien 9538494Sobrien 9638494Sobrienvoidp 9738494Sobriennfsproc_null_2_svc(voidp argp, struct svc_req *rqstp) 9838494Sobrien{ 9938494Sobrien static char res; 10038494Sobrien 10138494Sobrien return (voidp) &res; 10238494Sobrien} 10338494Sobrien 10438494Sobrien 10538494Sobriennfsattrstat * 10638494Sobriennfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) 10738494Sobrien{ 10838494Sobrien static nfsattrstat res; 10938494Sobrien am_node *mp; 11038494Sobrien int retry; 11138494Sobrien 11238494Sobrien#ifdef DEBUG 11338494Sobrien amuDebug(D_TRACE) 11438494Sobrien plog(XLOG_DEBUG, "getattr:"); 11538494Sobrien#endif /* DEBUG */ 11638494Sobrien 11738494Sobrien mp = fh_to_mp2(argp, &retry); 11838494Sobrien if (mp == 0) { 11938494Sobrien 12038494Sobrien#ifdef DEBUG 12138494Sobrien amuDebug(D_TRACE) 12238494Sobrien plog(XLOG_DEBUG, "\tretry=%d", retry); 12338494Sobrien#endif /* DEBUG */ 12438494Sobrien 12538494Sobrien if (retry < 0) 12638494Sobrien return 0; 12738494Sobrien res.ns_status = nfs_error(retry); 12838494Sobrien } else { 12938494Sobrien nfsattrstat *attrp = &mp->am_attr; 13038494Sobrien 13138494Sobrien#ifdef DEBUG 13238494Sobrien amuDebug(D_TRACE) 13338494Sobrien plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, 13438494Sobrien attrp->ns_u.ns_attr_u.na_size); 13538494Sobrien#endif /* DEBUG */ 13638494Sobrien 13738494Sobrien mp->am_stats.s_getattr++; 13838494Sobrien return attrp; 13938494Sobrien } 14038494Sobrien 14138494Sobrien#ifndef MNT2_NFS_OPT_SYMTTL 14238494Sobrien /* 14338494Sobrien * This code is needed to defeat Solaris 2.4's (and newer) symlink values 14442629Sobrien * cache. It forces the last-modified time of the symlink to be current. 14538494Sobrien * It is not needed if the O/S has an nfs flag to turn off the 14638494Sobrien * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. 14738494Sobrien */ 14838494Sobrien if (++res.ns_u.ns_attr_u.na_mtime.nt_useconds == 0) 14938494Sobrien ++res.ns_u.ns_attr_u.na_mtime.nt_seconds; 15038494Sobrien#endif /* not MNT2_NFS_OPT_SYMTTL */ 15138494Sobrien 15238494Sobrien return &res; 15338494Sobrien} 15438494Sobrien 15538494Sobrien 15638494Sobriennfsattrstat * 15738494Sobriennfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp) 15838494Sobrien{ 15938494Sobrien static nfsattrstat res; 16038494Sobrien 16138494Sobrien if (!fh_to_mp(&argp->sag_fhandle)) 16238494Sobrien res.ns_status = nfs_error(ESTALE); 16338494Sobrien else 16438494Sobrien res.ns_status = nfs_error(EROFS); 16538494Sobrien 16638494Sobrien return &res; 16738494Sobrien} 16838494Sobrien 16938494Sobrien 17038494Sobrienvoidp 17138494Sobriennfsproc_root_2_svc(voidp argp, struct svc_req *rqstp) 17238494Sobrien{ 17338494Sobrien static char res; 17438494Sobrien 17538494Sobrien return (voidp) &res; 17638494Sobrien} 17738494Sobrien 17838494Sobrien 17938494Sobriennfsdiropres * 18038494Sobriennfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) 18138494Sobrien{ 18238494Sobrien static nfsdiropres res; 18338494Sobrien am_node *mp; 18438494Sobrien int retry; 18538494Sobrien 18638494Sobrien#ifdef DEBUG 18738494Sobrien amuDebug(D_TRACE) 18838494Sobrien plog(XLOG_DEBUG, "lookup:"); 18938494Sobrien#endif /* DEBUG */ 19038494Sobrien 19138494Sobrien mp = fh_to_mp2(&argp->da_fhandle, &retry); 19238494Sobrien if (mp == 0) { 19338494Sobrien if (retry < 0) 19438494Sobrien return 0; 19538494Sobrien res.dr_status = nfs_error(retry); 19638494Sobrien } else { 19738494Sobrien int error; 19838494Sobrien am_node *ap; 19938494Sobrien#ifdef DEBUG 20038494Sobrien amuDebug(D_TRACE) 20138494Sobrien plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->da_name); 20238494Sobrien#endif /* DEBUG */ 20338494Sobrien ap = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &error, VLOOK_CREATE); 20438494Sobrien if (ap == 0) { 20538494Sobrien if (error < 0) { 20638494Sobrien#ifdef DEBUG 20738494Sobrien dlog("Not sending RPC reply"); 20838494Sobrien#endif /* DEBUG */ 20938494Sobrien amd_stats.d_drops++; 21038494Sobrien return 0; 21138494Sobrien } 21238494Sobrien res.dr_status = nfs_error(error); 21338494Sobrien } else { 21442629Sobrien /* 21542629Sobrien * XXX: EXPERIMENTAL! Delay unmount of what was looked up. This 21642629Sobrien * should reduce the chance for race condition between unmounting an 21742629Sobrien * entry synchronously, and re-mounting it asynchronously. 21842629Sobrien */ 21942629Sobrien if (ap->am_ttl < mp->am_ttl) 22042629Sobrien ap->am_ttl = mp->am_ttl; 22138494Sobrien mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle); 22238494Sobrien res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr; 22338494Sobrien res.dr_status = NFS_OK; 22438494Sobrien } 22538494Sobrien mp->am_stats.s_lookup++; 22638494Sobrien /* reschedule_timeout_mp(); */ 22738494Sobrien } 22838494Sobrien 22938494Sobrien return &res; 23038494Sobrien} 23138494Sobrien 23238494Sobrien 23338494Sobrienvoid 23438494Sobrienquick_reply(am_node *mp, int error) 23538494Sobrien{ 23638494Sobrien SVCXPRT *transp = mp->am_transp; 23738494Sobrien nfsdiropres res; 23838494Sobrien xdrproc_t xdr_result = (xdrproc_t) xdr_diropres; 23938494Sobrien 24038494Sobrien /* 24138494Sobrien * If there's a transp structure then we can reply to the client's 24238494Sobrien * nfs lookup request. 24338494Sobrien */ 24438494Sobrien if (transp) { 24538494Sobrien if (error == 0) { 24638494Sobrien /* 24738494Sobrien * Construct a valid reply to a lookup request. Same 24838494Sobrien * code as in nfsproc_lookup_2_svc() above. 24938494Sobrien */ 25038494Sobrien mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle); 25138494Sobrien res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr; 25238494Sobrien res.dr_status = NFS_OK; 25338494Sobrien } else 25438494Sobrien /* 25538494Sobrien * Return the error that was passed to us. 25638494Sobrien */ 25738494Sobrien res.dr_status = nfs_error(error); 25838494Sobrien 25938494Sobrien /* 26038494Sobrien * Send off our reply 26138494Sobrien */ 26238494Sobrien if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res)) 26338494Sobrien svcerr_systemerr(transp); 26438494Sobrien 26538494Sobrien /* 26638494Sobrien * Free up transp. It's only used for one reply. 26738494Sobrien */ 26838494Sobrien XFREE(transp); 26938494Sobrien mp->am_transp = NULL; 27038494Sobrien#ifdef DEBUG 27138494Sobrien dlog("Quick reply sent for %s", mp->am_mnt->mf_mount); 27238494Sobrien#endif /* DEBUG */ 27338494Sobrien } 27438494Sobrien} 27538494Sobrien 27638494Sobrien 27738494Sobriennfsreadlinkres * 27838494Sobriennfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) 27938494Sobrien{ 28038494Sobrien static nfsreadlinkres res; 28138494Sobrien am_node *mp; 28238494Sobrien int retry; 28338494Sobrien 28438494Sobrien#ifdef DEBUG 28538494Sobrien amuDebug(D_TRACE) 28638494Sobrien plog(XLOG_DEBUG, "readlink:"); 28738494Sobrien#endif /* DEBUG */ 28838494Sobrien 28938494Sobrien mp = fh_to_mp2(argp, &retry); 29038494Sobrien if (mp == 0) { 29138494Sobrien readlink_retry: 29238494Sobrien if (retry < 0) 29338494Sobrien return 0; 29438494Sobrien res.rlr_status = nfs_error(retry); 29538494Sobrien } else { 29638494Sobrien char *ln = do_readlink(mp, &retry, (nfsattrstat **) 0); 29738494Sobrien if (ln == 0) 29838494Sobrien goto readlink_retry; 29938494Sobrien res.rlr_status = NFS_OK; 30038494Sobrien#ifdef DEBUG 30138494Sobrien amuDebug(D_TRACE) 30238494Sobrien if (ln) 30338494Sobrien plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln); 30438494Sobrien#endif /* DEBUG */ 30538494Sobrien res.rlr_u.rlr_data_u = ln; 30638494Sobrien mp->am_stats.s_readlink++; 30738494Sobrien } 30838494Sobrien 30938494Sobrien return &res; 31038494Sobrien} 31138494Sobrien 31238494Sobrien 31338494Sobriennfsreadres * 31438494Sobriennfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp) 31538494Sobrien{ 31638494Sobrien static nfsreadres res; 31738494Sobrien 31838494Sobrien memset((char *) &res, 0, sizeof(res)); 31938494Sobrien res.rr_status = nfs_error(EACCES); 32038494Sobrien 32138494Sobrien return &res; 32238494Sobrien} 32338494Sobrien 32438494Sobrien 32538494Sobrienvoidp 32638494Sobriennfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp) 32738494Sobrien{ 32838494Sobrien static char res; 32938494Sobrien 33038494Sobrien return (voidp) &res; 33138494Sobrien} 33238494Sobrien 33338494Sobrien 33438494Sobriennfsattrstat * 33538494Sobriennfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp) 33638494Sobrien{ 33738494Sobrien static nfsattrstat res; 33838494Sobrien 33938494Sobrien if (!fh_to_mp(&argp->wra_fhandle)) 34038494Sobrien res.ns_status = nfs_error(ESTALE); 34138494Sobrien else 34238494Sobrien res.ns_status = nfs_error(EROFS); 34338494Sobrien 34438494Sobrien return &res; 34538494Sobrien} 34638494Sobrien 34738494Sobrien 34838494Sobriennfsdiropres * 34938494Sobriennfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp) 35038494Sobrien{ 35138494Sobrien static nfsdiropres res; 35238494Sobrien 35338494Sobrien if (!fh_to_mp(&argp->ca_where.da_fhandle)) 35438494Sobrien res.dr_status = nfs_error(ESTALE); 35538494Sobrien else 35638494Sobrien res.dr_status = nfs_error(EROFS); 35738494Sobrien 35838494Sobrien return &res; 35938494Sobrien} 36038494Sobrien 36138494Sobrien 36238494Sobrienstatic nfsstat * 36338494Sobrienunlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp) 36438494Sobrien{ 36538494Sobrien static nfsstat res; 36638494Sobrien int retry; 36738494Sobrien 36838494Sobrien am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE); 36938494Sobrien if (mp == 0) { 37038494Sobrien if (retry < 0) 37138494Sobrien return 0; 37238494Sobrien res = nfs_error(retry); 37338494Sobrien goto out; 37438494Sobrien } 37538494Sobrien 37638494Sobrien if (mp->am_fattr.na_type != NFDIR) { 37738494Sobrien res = nfs_error(ENOTDIR); 37838494Sobrien goto out; 37938494Sobrien } 38038494Sobrien 38138494Sobrien#ifdef DEBUG 38238494Sobrien amuDebug(D_TRACE) 38338494Sobrien plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name); 38438494Sobrien#endif /* DEBUG */ 38538494Sobrien 38638494Sobrien mp = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &retry, VLOOK_DELETE); 38738494Sobrien if (mp == 0) { 38838494Sobrien /* 38938494Sobrien * Ignore retries... 39038494Sobrien */ 39138494Sobrien if (retry < 0) 39238494Sobrien retry = 0; 39338494Sobrien /* 39438494Sobrien * Usual NFS workaround... 39538494Sobrien */ 39638494Sobrien else if (retry == ENOENT) 39738494Sobrien retry = 0; 39838494Sobrien res = nfs_error(retry); 39938494Sobrien } else { 40038494Sobrien forcibly_timeout_mp(mp); 40138494Sobrien res = NFS_OK; 40238494Sobrien } 40338494Sobrien 40438494Sobrienout: 40538494Sobrien return &res; 40638494Sobrien} 40738494Sobrien 40838494Sobrien 40938494Sobriennfsstat * 41038494Sobriennfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) 41138494Sobrien{ 41238494Sobrien return unlink_or_rmdir(argp, rqstp, TRUE); 41338494Sobrien} 41438494Sobrien 41538494Sobrien 41638494Sobriennfsstat * 41738494Sobriennfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp) 41838494Sobrien{ 41938494Sobrien static nfsstat res; 42038494Sobrien 42138494Sobrien if (!fh_to_mp(&argp->rna_from.da_fhandle) || !fh_to_mp(&argp->rna_to.da_fhandle)) 42238494Sobrien res = nfs_error(ESTALE); 42338494Sobrien /* 42438494Sobrien * If the kernel is doing clever things with referenced files 42538494Sobrien * then let it pretend... 42638494Sobrien */ 42738494Sobrien else if (NSTREQ(argp->rna_to.da_name, ".nfs", 4)) 42838494Sobrien res = NFS_OK; 42938494Sobrien /* 43038494Sobrien * otherwise a failure 43138494Sobrien */ 43238494Sobrien else 43338494Sobrien res = nfs_error(EROFS); 43438494Sobrien 43538494Sobrien return &res; 43638494Sobrien} 43738494Sobrien 43838494Sobrien 43938494Sobriennfsstat * 44038494Sobriennfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp) 44138494Sobrien{ 44238494Sobrien static nfsstat res; 44338494Sobrien 44438494Sobrien if (!fh_to_mp(&argp->la_fhandle) || !fh_to_mp(&argp->la_to.da_fhandle)) 44538494Sobrien res = nfs_error(ESTALE); 44638494Sobrien else 44738494Sobrien res = nfs_error(EROFS); 44838494Sobrien 44938494Sobrien return &res; 45038494Sobrien} 45138494Sobrien 45238494Sobrien 45338494Sobriennfsstat * 45438494Sobriennfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp) 45538494Sobrien{ 45638494Sobrien static nfsstat res; 45738494Sobrien 45838494Sobrien if (!fh_to_mp(&argp->sla_from.da_fhandle)) 45938494Sobrien res = nfs_error(ESTALE); 46038494Sobrien else 46138494Sobrien res = nfs_error(EROFS); 46238494Sobrien 46338494Sobrien return &res; 46438494Sobrien} 46538494Sobrien 46638494Sobrien 46738494Sobriennfsdiropres * 46838494Sobriennfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp) 46938494Sobrien{ 47038494Sobrien static nfsdiropres res; 47138494Sobrien 47238494Sobrien if (!fh_to_mp(&argp->ca_where.da_fhandle)) 47338494Sobrien res.dr_status = nfs_error(ESTALE); 47438494Sobrien else 47538494Sobrien res.dr_status = nfs_error(EROFS); 47638494Sobrien 47738494Sobrien return &res; 47838494Sobrien} 47938494Sobrien 48038494Sobrien 48138494Sobriennfsstat * 48238494Sobriennfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) 48338494Sobrien{ 48438494Sobrien return unlink_or_rmdir(argp, rqstp, FALSE); 48538494Sobrien} 48638494Sobrien 48738494Sobrien 48838494Sobriennfsreaddirres * 48938494Sobriennfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) 49038494Sobrien{ 49138494Sobrien static nfsreaddirres res; 49238494Sobrien static nfsentry e_res[MAX_READDIR_ENTRIES]; 49338494Sobrien am_node *mp; 49438494Sobrien int retry; 49538494Sobrien 49638494Sobrien#ifdef DEBUG 49738494Sobrien amuDebug(D_TRACE) 49838494Sobrien plog(XLOG_DEBUG, "readdir:"); 49938494Sobrien#endif /* DEBUG */ 50038494Sobrien 50138494Sobrien mp = fh_to_mp2(&argp->rda_fhandle, &retry); 50238494Sobrien if (mp == 0) { 50338494Sobrien if (retry < 0) 50438494Sobrien return 0; 50538494Sobrien res.rdr_status = nfs_error(retry); 50638494Sobrien } else { 50738494Sobrien#ifdef DEBUG 50838494Sobrien amuDebug(D_TRACE) 50938494Sobrien plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path); 51038494Sobrien#endif /* DEBUG */ 51138494Sobrien res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir) 51238494Sobrien (mp, argp->rda_cookie, 51338494Sobrien &res.rdr_u.rdr_reply_u, e_res, argp->rda_count)); 51438494Sobrien mp->am_stats.s_readdir++; 51538494Sobrien } 51638494Sobrien 51738494Sobrien return &res; 51838494Sobrien} 51938494Sobrien 52038494Sobrien 52138494Sobriennfsstatfsres * 52238494Sobriennfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) 52338494Sobrien{ 52438494Sobrien static nfsstatfsres res; 52538494Sobrien am_node *mp; 52638494Sobrien int retry; 52738494Sobrien mntent_t mnt; 52838494Sobrien 52938494Sobrien#ifdef DEBUG 53038494Sobrien amuDebug(D_TRACE) 53138494Sobrien plog(XLOG_DEBUG, "statfs:"); 53238494Sobrien#endif /* DEBUG */ 53338494Sobrien 53438494Sobrien mp = fh_to_mp2(argp, &retry); 53538494Sobrien if (mp == 0) { 53638494Sobrien if (retry < 0) 53738494Sobrien return 0; 53838494Sobrien res.sfr_status = nfs_error(retry); 53938494Sobrien } else { 54038494Sobrien nfsstatfsokres *fp; 54138494Sobrien#ifdef DEBUG 54238494Sobrien amuDebug(D_TRACE) 54338494Sobrien plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path); 54438494Sobrien#endif /* DEBUG */ 54538494Sobrien 54638494Sobrien /* 54738494Sobrien * just return faked up file system information 54838494Sobrien */ 54938494Sobrien fp = &res.sfr_u.sfr_reply_u; 55038494Sobrien 55138494Sobrien fp->sfrok_tsize = 1024; 55238494Sobrien fp->sfrok_bsize = 1024; 55338494Sobrien 55438494Sobrien /* check if map is browsable and show_statfs_entries=yes */ 55538494Sobrien if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && 55638494Sobrien mp->am_mnt && mp->am_mnt->mf_mopts) { 55738494Sobrien mnt.mnt_opts = mp->am_mnt->mf_mopts; 55838494Sobrien if (hasmntopt(&mnt, "browsable")) { 55938494Sobrien count_map_entries(mp, 56038494Sobrien &fp->sfrok_blocks, 56138494Sobrien &fp->sfrok_bfree, 56238494Sobrien &fp->sfrok_bavail); 56338494Sobrien } 56438494Sobrien } else { 56538494Sobrien fp->sfrok_blocks = 0; /* set to 1 if you don't want empty automounts */ 56638494Sobrien fp->sfrok_bfree = 0; 56738494Sobrien fp->sfrok_bavail = 0; 56838494Sobrien } 56938494Sobrien 57038494Sobrien res.sfr_status = NFS_OK; 57138494Sobrien mp->am_stats.s_statfs++; 57238494Sobrien } 57338494Sobrien 57438494Sobrien return &res; 57538494Sobrien} 57638494Sobrien 57738494Sobrien 57838494Sobrien/* 57938494Sobrien * count how many total entries there are in a map, and how many 58038494Sobrien * of them are in use. 58138494Sobrien */ 58238494Sobrienstatic void 58338494Sobriencount_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail) 58438494Sobrien{ 58538494Sobrien u_int blocks, bfree, bavail, i; 58638494Sobrien mntfs *mf; 58738494Sobrien mnt_map *mmp; 58838494Sobrien kv *k; 58938494Sobrien 59038494Sobrien blocks = bfree = bavail = 0; 59138494Sobrien if (!mp) 59238494Sobrien goto out; 59338494Sobrien mf = mp->am_mnt; 59438494Sobrien if (!mf) 59538494Sobrien goto out; 59638494Sobrien mmp = (mnt_map *) mf->mf_private; 59738494Sobrien if (!mmp) 59838494Sobrien goto out; 59938494Sobrien 60038494Sobrien /* iterate over keys */ 60138494Sobrien for (i = 0; i < NKVHASH; i++) { 60238494Sobrien for (k = mmp->kvhash[i]; k ; k = k->next) { 60338494Sobrien if (!k->key) 60438494Sobrien continue; 60538494Sobrien blocks++; 60638494Sobrien /* 60738494Sobrien * XXX: Need to count how many are actively in use and recompute 60838494Sobrien * bfree and bavail based on it. 60938494Sobrien */ 61038494Sobrien } 61138494Sobrien } 61238494Sobrien 61338494Sobrienout: 61438494Sobrien *out_blocks = blocks; 61538494Sobrien *out_bfree = bfree; 61638494Sobrien *out_bavail = bavail; 61738494Sobrien} 618