12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922 |
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/kernel.h>
- #include <sys/mount.h>
- #include <sys/vnode.h>
- #include <sys/namei.h>
- #include <sys/mbuf.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/stat.h>
- #include <sys/pool.h>
- #include <sys/time.h>
- #include <nfs/rpcv2.h>
- #include <nfs/nfsproto.h>
- #include <nfs/nfsnode.h>
- #include <nfs/nfs.h>
- #include <nfs/xdr_subs.h>
- #include <nfs/nfsm_subs.h>
- #include <nfs/nfsmount.h>
- #include <nfs/nfs_var.h>
- #include <uvm/uvm_extern.h>
- #include <netinet/in.h>
- #include <crypto/idgen.h>
- int nfs_attrtimeo(struct nfsnode *np);
- u_int32_t nfs_xdrneg1;
- u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
- u_int32_t nfs_prog, nfs_true, nfs_false;
- nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
- NFCHR, NFNON };
- nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
- NFFIFO, NFNON };
- enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
- enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
- int nfs_ticks;
- struct nfsstats nfsstats;
- int nfsv3_procid[NFS_NPROCS] = {
- NFSPROC_NULL,
- NFSPROC_GETATTR,
- NFSPROC_SETATTR,
- NFSPROC_NOOP,
- NFSPROC_LOOKUP,
- NFSPROC_READLINK,
- NFSPROC_READ,
- NFSPROC_NOOP,
- NFSPROC_WRITE,
- NFSPROC_CREATE,
- NFSPROC_REMOVE,
- NFSPROC_RENAME,
- NFSPROC_LINK,
- NFSPROC_SYMLINK,
- NFSPROC_MKDIR,
- NFSPROC_RMDIR,
- NFSPROC_READDIR,
- NFSPROC_FSSTAT,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP
- };
- int nfsv2_procid[NFS_NPROCS] = {
- NFSV2PROC_NULL,
- NFSV2PROC_GETATTR,
- NFSV2PROC_SETATTR,
- NFSV2PROC_LOOKUP,
- NFSV2PROC_NOOP,
- NFSV2PROC_READLINK,
- NFSV2PROC_READ,
- NFSV2PROC_WRITE,
- NFSV2PROC_CREATE,
- NFSV2PROC_MKDIR,
- NFSV2PROC_SYMLINK,
- NFSV2PROC_CREATE,
- NFSV2PROC_REMOVE,
- NFSV2PROC_RMDIR,
- NFSV2PROC_RENAME,
- NFSV2PROC_LINK,
- NFSV2PROC_READDIR,
- NFSV2PROC_NOOP,
- NFSV2PROC_STATFS,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP,
- NFSV2PROC_NOOP
- };
- static u_char nfsrv_v2errmap[] = {
- NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
- NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
- NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
- NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE
-
- };
- static short nfsv3err_null[] = {
- 0,
- 0,
- };
- static short nfsv3err_getattr[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_setattr[] = {
- NFSERR_IO,
- NFSERR_PERM,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOT_SYNC,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_lookup[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_access[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_readlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_read[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_NXIO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_write[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_FBIG,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_create[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_mkdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_symlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_mknod[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- NFSERR_BADTYPE,
- 0,
- };
- static short nfsv3err_remove[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_rmdir[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_rename[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_ISDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_link[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_readdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_readdirplus[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_NOTSUPP,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_fsstat[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_fsinfo[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_pathconf[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short nfsv3err_commit[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
- };
- static short *nfsrv_v3errmap[] = {
- nfsv3err_null,
- nfsv3err_getattr,
- nfsv3err_setattr,
- nfsv3err_lookup,
- nfsv3err_access,
- nfsv3err_readlink,
- nfsv3err_read,
- nfsv3err_write,
- nfsv3err_create,
- nfsv3err_mkdir,
- nfsv3err_symlink,
- nfsv3err_mknod,
- nfsv3err_remove,
- nfsv3err_rmdir,
- nfsv3err_rename,
- nfsv3err_link,
- nfsv3err_readdir,
- nfsv3err_readdirplus,
- nfsv3err_fsstat,
- nfsv3err_fsinfo,
- nfsv3err_pathconf,
- nfsv3err_commit,
- };
- struct pool nfsreqpl;
- struct mbuf *
- nfsm_reqhead(int hsiz)
- {
- struct mbuf *mb;
- MGET(mb, M_WAIT, MT_DATA);
- if (hsiz > MLEN)
- MCLGET(mb, M_WAIT);
- mb->m_len = 0;
-
-
- return (mb);
- }
- u_int32_t
- nfs_get_xid(void)
- {
- static struct idgen32_ctx nfs_xid_ctx;
- static int called = 0;
- if (!called) {
- called = 1;
- idgen32_init(&nfs_xid_ctx);
- }
- return (txdr_unsigned(idgen32(&nfs_xid_ctx)));
- }
- void
- nfsm_rpchead(struct nfsreq *req, struct ucred *cr, int auth_type)
- {
- struct mbuf *mb;
- u_int32_t *tl;
- int i, authsiz, auth_len, ngroups;
- KASSERT(auth_type == RPCAUTH_UNIX);
-
- mb = req->r_mreq;
-
- switch (auth_type) {
- case RPCAUTH_UNIX:
-
- if (cr->cr_ngroups > req->r_nmp->nm_numgrps)
- ngroups = req->r_nmp->nm_numgrps;
- else
- ngroups = cr->cr_ngroups;
- auth_len = (ngroups << 2) + 5 * NFSX_UNSIGNED;
- authsiz = nfsm_rndup(auth_len);
-
- MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- break;
- }
- mb->m_len = 0;
-
- tl = nfsm_build(&mb, 6 * NFSX_UNSIGNED);
-
- *tl++ = req->r_xid = nfs_get_xid();
- *tl++ = rpc_call;
- *tl++ = rpc_vers;
- *tl++ = nfs_prog;
- if (ISSET(req->r_nmp->nm_flag, NFSMNT_NFSV3)) {
- *tl++ = txdr_unsigned(NFS_VER3);
- *tl = txdr_unsigned(req->r_procnum);
- } else {
- *tl++ = txdr_unsigned(NFS_VER2);
- *tl = txdr_unsigned(nfsv2_procid[req->r_procnum]);
- }
-
- switch (auth_type) {
- case RPCAUTH_UNIX:
- tl = nfsm_build(&mb, auth_len + 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(RPCAUTH_UNIX);
- *tl++ = txdr_unsigned(authsiz);
-
- *tl++ = 0;
- *tl++ = 0;
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl++ = txdr_unsigned(cr->cr_gid);
- *tl++ = txdr_unsigned(ngroups);
- for (i = 0; i < ngroups; i++)
- *tl++ = txdr_unsigned(cr->cr_groups[i]);
-
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- break;
- }
- mb->m_pkthdr.len += authsiz + 10 * NFSX_UNSIGNED;
- mb->m_pkthdr.ph_ifidx = 0;
- }
- int
- nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
- {
- char *mbufcp, *uiocp;
- int xfer, left, len;
- struct mbuf *mp;
- long uiosiz, rem;
- int error = 0;
- mp = *mrep;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- rem = nfsm_padlen(siz);
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
- if (uiop->uio_segflg == UIO_SYSSPACE)
- memcpy(uiocp, mbufcp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- }
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- if (rem > 0) {
- if (len < rem)
- error = nfs_adv(mrep, dpos, rem, len);
- else
- *dpos += rem;
- }
- return (error);
- }
- void
- nfsm_uiotombuf(struct mbuf **mp, struct uio *uiop, size_t len)
- {
- struct mbuf *mb, *mb2;
- size_t xfer, pad;
- mb = *mp;
- pad = nfsm_padlen(len);
-
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_WRITE;
- while (len) {
- xfer = min(len, M_TRAILINGSPACE(mb));
- uiomovei(mb_offset(mb), xfer, uiop);
- mb->m_len += xfer;
- len -= xfer;
- if (len > 0) {
- MGET(mb2, M_WAIT, MT_DATA);
- if (len > MLEN)
- MCLGET(mb2, M_WAIT);
- mb2->m_len = 0;
- mb->m_next = mb2;
- mb = mb2;
- }
- }
- if (pad > 0) {
- if (pad > M_TRAILINGSPACE(mb)) {
- MGET(mb2, M_WAIT, MT_DATA);
- mb2->m_len = 0;
- mb->m_next = mb2;
- mb = mb2;
- }
- memset(mb_offset(mb), 0, pad);
- mb->m_len += pad;
- }
- *mp = mb;
- }
- void
- nfsm_buftombuf(struct mbuf **mp, void *buf, size_t len)
- {
- struct iovec iov;
- struct uio io;
- iov.iov_base = buf;
- iov.iov_len = len;
- io.uio_iov = &iov;
- io.uio_iovcnt = 1;
- io.uio_resid = len;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_WRITE;
- nfsm_uiotombuf(mp, &io, len);
- }
- void
- nfsm_strtombuf(struct mbuf **mp, void *str, size_t len)
- {
- struct iovec iov[2];
- struct uio io;
- uint32_t strlen;
- strlen = txdr_unsigned(len);
- iov[0].iov_base = &strlen;
- iov[0].iov_len = sizeof(uint32_t);
- iov[1].iov_base = str;
- iov[1].iov_len = len;
- io.uio_iov = iov;
- io.uio_iovcnt = 2;
- io.uio_resid = sizeof(uint32_t) + len;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_WRITE;
- nfsm_uiotombuf(mp, &io, io.uio_resid);
- }
- int
- nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
- {
- struct mbuf *mp, *mp2;
- int siz2, xfer;
- caddr_t p;
- mp = *mdp;
- while (left == 0) {
- *mdp = mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- left = mp->m_len;
- *dposp = mtod(mp, caddr_t);
- }
- if (left >= siz) {
- *cp2 = *dposp;
- *dposp += siz;
- } else if (mp->m_next == NULL) {
- return (EBADRPC);
- } else if (siz > MHLEN) {
- panic("nfs S too big");
- } else {
- MGET(mp2, M_WAIT, MT_DATA);
- mp2->m_next = mp->m_next;
- mp->m_next = mp2;
- mp->m_len -= left;
- mp = mp2;
- *cp2 = p = mtod(mp, caddr_t);
- bcopy(*dposp, p, left);
- siz2 = siz-left;
- p += left;
- mp2 = mp->m_next;
-
- while (siz2 > 0) {
- if (mp2 == NULL)
- return (EBADRPC);
- xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
- if (xfer > 0) {
- bcopy(mtod(mp2, caddr_t), p, xfer);
- mp2->m_data += xfer;
- mp2->m_len -= xfer;
- p += xfer;
- siz2 -= xfer;
- }
- if (siz2 > 0)
- mp2 = mp2->m_next;
- }
- mp->m_len = siz;
- *mdp = mp2;
- *dposp = mtod(mp2, caddr_t);
- }
- return (0);
- }
- int
- nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
- {
- struct mbuf *m;
- int s;
- m = *mdp;
- s = left;
- while (s < offs) {
- offs -= s;
- m = m->m_next;
- if (m == NULL)
- return (EBADRPC);
- s = m->m_len;
- }
- *mdp = m;
- *dposp = mtod(m, caddr_t)+offs;
- return (0);
- }
- void
- nfs_init(void)
- {
- rpc_vers = txdr_unsigned(RPC_VER2);
- rpc_call = txdr_unsigned(RPC_CALL);
- rpc_reply = txdr_unsigned(RPC_REPLY);
- rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
- rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
- rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
- rpc_autherr = txdr_unsigned(RPC_AUTHERR);
- rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
- nfs_prog = txdr_unsigned(NFS_PROG);
- nfs_true = txdr_unsigned(1);
- nfs_false = txdr_unsigned(0);
- nfs_xdrneg1 = txdr_unsigned(-1);
- nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
- if (nfs_ticks < 1)
- nfs_ticks = 1;
- #ifdef NFSSERVER
- nfsrv_init(0);
- nfsrv_initcache();
- #endif
- pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, 0, PR_WAITOK,
- "nfsreqpl", NULL);
- }
- #ifdef NFSCLIENT
- int
- nfs_vfs_init(struct vfsconf *vfsp)
- {
- extern struct pool nfs_node_pool;
- TAILQ_INIT(&nfs_bufq);
- pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, PR_WAITOK,
- "nfsnodepl", NULL);
- return (0);
- }
- int
- nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
- struct vattr *vaper)
- {
- struct vnode *vp = *vpp;
- struct vattr *vap;
- struct nfs_fattr *fp;
- extern struct vops nfs_specvops;
- struct nfsnode *np;
- int32_t t1;
- caddr_t cp2;
- int error = 0;
- int32_t rdev;
- struct mbuf *md;
- enum vtype vtyp;
- mode_t vmode;
- struct timespec mtime;
- struct vnode *nvp;
- int v3 = NFS_ISV3(vp);
- uid_t uid;
- gid_t gid;
- md = *mdp;
- t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
- error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
- if (error)
- return (error);
- fp = (struct nfs_fattr *)cp2;
- if (v3) {
- vtyp = nfsv3tov_type(fp->fa_type);
- vmode = fxdr_unsigned(mode_t, fp->fa_mode);
- rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1),
- fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2));
- fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
- } else {
- vtyp = nfsv2tov_type(fp->fa_type);
- vmode = fxdr_unsigned(mode_t, fp->fa_mode);
- if (vtyp == VNON || vtyp == VREG)
- vtyp = IFTOVT(vmode);
- rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
- fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
-
- if (vtyp == VCHR && rdev == 0xffffffff)
- vtyp = VFIFO;
- }
-
- np = VTONFS(vp);
- if (vp->v_type != vtyp) {
- cache_purge(vp);
- vp->v_type = vtyp;
- if (vp->v_type == VFIFO) {
- #ifndef FIFO
- return (EOPNOTSUPP);
- #else
- extern struct vops nfs_fifovops;
- vp->v_op = &nfs_fifovops;
- #endif
- }
- if (vp->v_type == VCHR || vp->v_type == VBLK) {
- vp->v_op = &nfs_specvops;
- nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
- if (nvp) {
-
- nvp->v_data = vp->v_data;
- vp->v_data = NULL;
- vp->v_op = &spec_vops;
- vrele(vp);
- vgone(vp);
-
- np->n_vnode = nvp;
- *vpp = vp = nvp;
- }
- }
- np->n_mtime = mtime;
- }
- vap = &np->n_vattr;
- vap->va_type = vtyp;
- vap->va_rdev = (dev_t)rdev;
- vap->va_mtime = mtime;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- uid = fxdr_unsigned(uid_t, fp->fa_uid);
- gid = fxdr_unsigned(gid_t, fp->fa_gid);
-
- if (np->n_accstamp != -1 &&
- (gid != vap->va_gid || uid != vap->va_uid ||
- (vmode & 07777) != vap->va_mode))
- np->n_accstamp = -1;
- vap->va_mode = (vmode & 07777);
- switch (vtyp) {
- case VBLK:
- vap->va_blocksize = BLKDEV_IOSIZE;
- break;
- case VCHR:
- vap->va_blocksize = MAXBSIZE;
- break;
- default:
- vap->va_blocksize = v3 ? vp->v_mount->mnt_stat.f_iosize :
- fxdr_unsigned(int32_t, fp->fa2_blocksize);
- break;
- }
- if (v3) {
- vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_hyper(&fp->fa3_size);
- vap->va_bytes = fxdr_hyper(&fp->fa3_used);
- vap->va_fileid = fxdr_hyper(&fp->fa3_fileid);
- fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
- fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
- vap->va_flags = 0;
- vap->va_filerev = 0;
- } else {
- vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
- vap->va_bytes =
- (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
- NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
- fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
- vap->va_flags = 0;
- vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
- fp->fa2_ctime.nfsv2_sec);
- vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
- vap->va_filerev = 0;
- }
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (np->n_flag & NMODIFIED) {
- if (vap->va_size < np->n_size)
- vap->va_size = np->n_size;
- else
- np->n_size = vap->va_size;
- } else
- np->n_size = vap->va_size;
- uvm_vnp_setsize(vp, np->n_size);
- } else
- np->n_size = vap->va_size;
- }
- np->n_attrstamp = time_second;
- if (vaper != NULL) {
- bcopy(vap, vaper, sizeof(*vap));
- if (np->n_flag & NCHG) {
- if (np->n_flag & NACC)
- vaper->va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vaper->va_mtime = np->n_mtim;
- }
- }
- return (0);
- }
- int
- nfs_attrtimeo(struct nfsnode *np)
- {
- struct vnode *vp = np->n_vnode;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int tenthage = (time_second - np->n_mtime.tv_sec) / 10;
- int minto, maxto;
- if (vp->v_type == VDIR) {
- maxto = nmp->nm_acdirmax;
- minto = nmp->nm_acdirmin;
- }
- else {
- maxto = nmp->nm_acregmax;
- minto = nmp->nm_acregmin;
- }
- if (np->n_flag & NMODIFIED || tenthage < minto)
- return minto;
- else if (tenthage < maxto)
- return tenthage;
- else
- return maxto;
- }
- int
- nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
- {
- struct nfsnode *np = VTONFS(vp);
- struct vattr *vap;
- if (np->n_attrstamp == 0 ||
- (time_second - np->n_attrstamp) >= nfs_attrtimeo(np)) {
- nfsstats.attrcache_misses++;
- return (ENOENT);
- }
- nfsstats.attrcache_hits++;
- vap = &np->n_vattr;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (np->n_flag & NMODIFIED) {
- if (vap->va_size < np->n_size)
- vap->va_size = np->n_size;
- else
- np->n_size = vap->va_size;
- } else
- np->n_size = vap->va_size;
- uvm_vnp_setsize(vp, np->n_size);
- } else
- np->n_size = vap->va_size;
- }
- bcopy(vap, vaper, sizeof(struct vattr));
- if (np->n_flag & NCHG) {
- if (np->n_flag & NACC)
- vaper->va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vaper->va_mtime = np->n_mtim;
- }
- return (0);
- }
- #endif
- int
- nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
- struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp,
- caddr_t *dposp, struct vnode **retdirp, struct proc *p)
- {
- int i, rem;
- struct mbuf *md;
- char *fromcp, *tocp;
- struct vnode *dp;
- int error, rdonly;
- struct componentname *cnp = &ndp->ni_cnd;
- *retdirp = NULL;
- cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
-
- fromcp = *dposp;
- tocp = cnp->cn_pnbuf;
- md = *mdp;
- rem = mtod(md, caddr_t) + md->m_len - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = md->m_next;
- if (md == NULL) {
- error = EBADRPC;
- goto out;
- }
- fromcp = mtod(md, caddr_t);
- rem = md->m_len;
- }
- if (*fromcp == '\0' || *fromcp == '/') {
- error = EACCES;
- goto out;
- }
- *tocp++ = *fromcp++;
- rem--;
- }
- *tocp = '\0';
- *mdp = md;
- *dposp = fromcp;
- len = nfsm_padlen(len);
- if (len > 0) {
- if (rem >= len)
- *dposp += len;
- else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out;
- }
- ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
- cnp->cn_nameptr = cnp->cn_pnbuf;
-
- error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly);
- if (error)
- goto out;
- if (dp->v_type != VDIR) {
- vrele(dp);
- error = ENOTDIR;
- goto out;
- }
- vref(dp);
- *retdirp = dp;
- ndp->ni_startdir = dp;
- if (rdonly)
- cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
- else
- cnp->cn_flags |= NOCROSSMOUNT;
-
- cnp->cn_proc = p;
- error = vfs_lookup(ndp);
- if (error)
- goto out;
-
- if (cnp->cn_flags & ISSYMLINK) {
- if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- vput(ndp->ni_dvp);
- else
- vrele(ndp->ni_dvp);
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
- error = EINVAL;
- goto out;
- }
-
- if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
- cnp->cn_flags |= HASBUF;
- return (0);
- }
- out:
- pool_put(&namei_pool, cnp->cn_pnbuf);
- return (error);
- }
- void
- nfsm_adj(struct mbuf *mp, int len, int nul)
- {
- struct mbuf *m;
- int count, i;
- char *cp;
-
- count = 0;
- m = mp;
- for (;;) {
- count += m->m_len;
- if (m->m_next == NULL)
- break;
- m = m->m_next;
- }
- if (m->m_len > len) {
- m->m_len -= len;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
-
- for (m = mp; m; m = m->m_next) {
- if (m->m_len >= count) {
- m->m_len = count;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- break;
- }
- count -= m->m_len;
- }
- for (m = m->m_next;m;m = m->m_next)
- m->m_len = 0;
- }
- void
- nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
- struct vattr *before_vap, int after_ret, struct vattr *after_vap,
- struct nfsm_info *info)
- {
- u_int32_t *tl;
- if (before_ret) {
- tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- txdr_hyper(before_vap->va_size, tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_mtime), tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_ctime), tl);
- }
- nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info);
- }
- void
- nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret,
- struct vattr *after_vap, struct nfsm_info *info)
- {
- u_int32_t *tl;
- struct nfs_fattr *fp;
- if (after_ret) {
- tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR);
- *tl++ = nfs_true;
- fp = (struct nfs_fattr *)tl;
- nfsm_srvfattr(nfsd, after_vap, fp);
- }
- }
- void
- nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
- struct nfs_fattr *fp)
- {
- fp->fa_nlink = txdr_unsigned(vap->va_nlink);
- fp->fa_uid = txdr_unsigned(vap->va_uid);
- fp->fa_gid = txdr_unsigned(vap->va_gid);
- if (nfsd->nd_flag & ND_NFSV3) {
- fp->fa_type = vtonfsv3_type(vap->va_type);
- fp->fa_mode = vtonfsv3_mode(vap->va_mode);
- txdr_hyper(vap->va_size, &fp->fa3_size);
- txdr_hyper(vap->va_bytes, &fp->fa3_used);
- fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
- fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
- fp->fa3_fsid.nfsuquad[0] = 0;
- fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
- txdr_hyper(vap->va_fileid, &fp->fa3_fileid);
- txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
- txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
- txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
- } else {
- fp->fa_type = vtonfsv2_type(vap->va_type);
- fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- fp->fa2_size = txdr_unsigned(vap->va_size);
- fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
- if (vap->va_type == VFIFO)
- fp->fa2_rdev = 0xffffffff;
- else
- fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
- fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
- fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
- fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid);
- txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
- txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
- txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
- }
- }
- int
- nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
- struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam,
- int *rdonlyp)
- {
- struct proc *p = curproc;
- struct mount *mp;
- int i;
- struct ucred *credanon;
- int error, exflags;
- struct sockaddr_in *saddr;
- *vpp = NULL;
- mp = vfs_getvfs(&fhp->fh_fsid);
- if (!mp)
- return (ESTALE);
- error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
- if (error)
- return (error);
- error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
- if (error)
- return (error);
- saddr = mtod(nam, struct sockaddr_in *);
- if (saddr->sin_family == AF_INET &&
- (ntohs(saddr->sin_port) >= IPPORT_RESERVED ||
- (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) {
- vput(*vpp);
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
- }
-
- if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
- cred->cr_uid = credanon->cr_uid;
- cred->cr_gid = credanon->cr_gid;
- for (i = 0; i < credanon->cr_ngroups && i < NGROUPS_MAX; i++)
- cred->cr_groups[i] = credanon->cr_groups[i];
- cred->cr_ngroups = i;
- }
- if (exflags & MNT_EXRDONLY)
- *rdonlyp = 1;
- else
- *rdonlyp = 0;
- if (!lockflag)
- VOP_UNLOCK(*vpp, 0, p);
- return (0);
- }
- int
- netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam)
- {
- struct sockaddr_in *inetaddr;
- switch (family) {
- case AF_INET:
- inetaddr = mtod(nam, struct sockaddr_in *);
- if (inetaddr->sin_family == AF_INET &&
- inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
- return (1);
- break;
- default:
- break;
- };
- return (0);
- }
- void
- nfs_clearcommit(struct mount *mp)
- {
- struct vnode *vp, *nvp;
- struct buf *bp, *nbp;
- int s;
- s = splbio();
- loop:
- for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
- if (vp->v_mount != mp)
- goto loop;
- nvp = LIST_NEXT(vp, v_mntvnodes);
- for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
- nbp = LIST_NEXT(bp, b_vnbufs);
- if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bp->b_flags &= ~B_NEEDCOMMIT;
- }
- }
- splx(s);
- }
- void
- nfs_merge_commit_ranges(struct vnode *vp)
- {
- struct nfsnode *np = VTONFS(vp);
- if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
- np->n_pushedlo = np->n_pushlo;
- np->n_pushedhi = np->n_pushhi;
- np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
- } else {
- if (np->n_pushlo < np->n_pushedlo)
- np->n_pushedlo = np->n_pushlo;
- if (np->n_pushhi > np->n_pushedhi)
- np->n_pushedhi = np->n_pushhi;
- }
- np->n_pushlo = np->n_pushhi = 0;
- np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID;
- }
- int
- nfs_in_committed_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
- return 0;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- return (lo >= np->n_pushedlo && hi <= np->n_pushedhi);
- }
- int
- nfs_in_tobecommitted_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
- return 0;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- return (lo >= np->n_pushlo && hi <= np->n_pushhi);
- }
- void
- nfs_add_committed_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
- np->n_pushedlo = lo;
- np->n_pushedhi = hi;
- np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
- } else {
- if (hi > np->n_pushedhi)
- np->n_pushedhi = hi;
- if (lo < np->n_pushedlo)
- np->n_pushedlo = lo;
- }
- }
- void
- nfs_del_committed_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
- return;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- if (lo > np->n_pushedhi || hi < np->n_pushedlo)
- return;
- if (lo <= np->n_pushedlo)
- np->n_pushedlo = hi;
- else if (hi >= np->n_pushedhi)
- np->n_pushedhi = lo;
- else {
-
- if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi))
- np->n_pushedhi = lo;
- else
- np->n_pushedlo = hi;
- }
- }
- void
- nfs_add_tobecommitted_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) {
- np->n_pushlo = lo;
- np->n_pushhi = hi;
- np->n_commitflags |= NFS_COMMIT_PUSH_VALID;
- } else {
- if (lo < np->n_pushlo)
- np->n_pushlo = lo;
- if (hi > np->n_pushhi)
- np->n_pushhi = hi;
- }
- }
- void
- nfs_del_tobecommitted_range(struct vnode *vp, struct buf *bp)
- {
- struct nfsnode *np = VTONFS(vp);
- off_t lo, hi;
- if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
- return;
- lo = (off_t)bp->b_blkno * DEV_BSIZE;
- hi = lo + bp->b_dirtyend;
- if (lo > np->n_pushhi || hi < np->n_pushlo)
- return;
- if (lo <= np->n_pushlo)
- np->n_pushlo = hi;
- else if (hi >= np->n_pushhi)
- np->n_pushhi = lo;
- else {
-
- if ((np->n_pushlo - lo) > (hi - np->n_pushhi))
- np->n_pushhi = lo;
- else
- np->n_pushlo = hi;
- }
- }
- int
- nfsrv_errmap(struct nfsrv_descript *nd, int err)
- {
- short *defaulterrp, *errp;
- if (nd->nd_flag & ND_NFSV3) {
- if (nd->nd_procnum <= NFSPROC_COMMIT) {
- errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
- while (*++errp) {
- if (*errp == err)
- return (err);
- else if (*errp > err)
- break;
- }
- return ((int)*defaulterrp);
- } else
- return (err & 0xffff);
- }
- if (err <= nitems(nfsrv_v2errmap))
- return ((int)nfsrv_v2errmap[err - 1]);
- return (NFSERR_IO);
- }
- void
- nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full)
- {
- struct mbuf *mb;
- u_int32_t *tl;
- mb = *mp;
- if (a->va_mode != (mode_t)VNOVAL) {
- tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- *tl = txdr_unsigned(a->va_mode);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- }
- if (full && a->va_uid != (uid_t)VNOVAL) {
- tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- *tl = txdr_unsigned(a->va_uid);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- }
- if (full && a->va_gid != (gid_t)VNOVAL) {
- tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- *tl = txdr_unsigned((a)->va_gid);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- }
- if (full && a->va_size != VNOVAL) {
- tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
- *tl++ = nfs_true;
- txdr_hyper(a->va_size, tl);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = nfs_false;
- }
- if (a->va_atime.tv_nsec != VNOVAL) {
- if (a->va_atime.tv_sec != time_second) {
- tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
- txdr_nfsv3time(&a->va_atime, tl);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
- }
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- }
- if (a->va_mtime.tv_nsec != VNOVAL) {
- if (a->va_mtime.tv_sec != time_second) {
- tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
- txdr_nfsv3time(&a->va_mtime, tl);
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
- }
- } else {
- tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- }
- *mp = mb;
- }
- void *
- nfsm_build(struct mbuf **mp, u_int len)
- {
- struct mbuf *mb, *mb2;
- caddr_t bpos;
- mb = *mp;
- bpos = mb_offset(mb);
- if (len > M_TRAILINGSPACE(mb)) {
- MGET(mb2, M_WAIT, MT_DATA);
- if (len > MLEN)
- panic("build > MLEN");
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- mb->m_len += len;
- *mp = mb;
- return (bpos);
- }
- void
- nfsm_fhtom(struct nfsm_info *info, struct vnode *v, int v3)
- {
- struct nfsnode *n = VTONFS(v);
- if (v3) {
- nfsm_strtombuf(&info->nmi_mb, n->n_fhp, n->n_fhsize);
- } else {
- nfsm_buftombuf(&info->nmi_mb, n->n_fhp, NFSX_V2FH);
- }
- }
- void
- nfsm_srvfhtom(struct mbuf **mp, fhandle_t *f, int v3)
- {
- if (v3) {
- nfsm_strtombuf(mp, f, NFSX_V3FH);
- } else {
- nfsm_buftombuf(mp, f, NFSX_V2FH);
- }
- }
- int
- nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep,
- caddr_t *dposp)
- {
- struct nfsm_info info;
- uint32_t *tl, t1;
- caddr_t cp2;
- int error = 0;
- info.nmi_md = *mp;
- info.nmi_dpos = *dposp;
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl == nfs_true) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- va->va_mode = nfstov_mode(*tl);
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl == nfs_true) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- va->va_uid = fxdr_unsigned(uid_t, *tl);
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl == nfs_true) {
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- va->va_gid = fxdr_unsigned(gid_t, *tl);
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl == nfs_true) {
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- va->va_size = fxdr_hyper(tl);
- }
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- switch (fxdr_unsigned(int, *tl)) {
- case NFSV3SATTRTIME_TOCLIENT:
- va->va_vaflags |= VA_UTIMES_CHANGE;
- va->va_vaflags &= ~VA_UTIMES_NULL;
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- fxdr_nfsv3time(tl, &va->va_atime);
- break;
- case NFSV3SATTRTIME_TOSERVER:
- va->va_vaflags |= VA_UTIMES_CHANGE;
- getnanotime(&va->va_atime);
- break;
- };
- nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
- switch (fxdr_unsigned(int, *tl)) {
- case NFSV3SATTRTIME_TOCLIENT:
- va->va_vaflags |= VA_UTIMES_CHANGE;
- va->va_vaflags &= ~VA_UTIMES_NULL;
- nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- fxdr_nfsv3time(tl, &va->va_mtime);
- break;
- case NFSV3SATTRTIME_TOSERVER:
- va->va_vaflags |= VA_UTIMES_CHANGE;
- getnanotime(&va->va_mtime);
- break;
- };
- *dposp = info.nmi_dpos;
- *mp = info.nmi_md;
- nfsmout:
- return (error);
- }
- void
- txdr_nfsv2time(const struct timespec *from, struct nfsv2_time *to)
- {
- if (from->tv_nsec == VNOVAL) {
- to->nfsv2_sec = nfs_xdrneg1;
- to->nfsv2_usec = nfs_xdrneg1;
- } else if (from->tv_sec == -1) {
-
- to->nfsv2_sec = htonl(-2);
- to->nfsv2_usec = htonl(999999);
- } else {
- to->nfsv2_sec = htonl(from->tv_sec);
- to->nfsv2_usec = htonl(from->tv_nsec / 1000);
- }
- }
|