Siguiente: GNU Free Documentation License Superior: Mejorando NFS Anterior: Cambios al cliente |
Función de atención a la petición de copy.
/* * max # of read+writes to issue. * 1 would be the traditional NFS value. * However, latency can be much better if a whole file copy be * copied within a single request. */ #define MAX_WORK 8 int nfsd_nfsproc_copy_2(copyargs *argp, struct svc_req *rqstp) { int sfd=-1,dfd=-1; nfsstat status=NFS_OK; int limit; int islcl; fhcache *sfhc,*dfhc; static char lclhost[NFS_MAXHOSTLEN+1]; static int lclknown=0; u_int nleft; struct writeargs warg; char *host=argp->hostname; CLIENT *cp=NULL; copyokres *res = &result.copyres.copyres_u.reply; if (!lclknown){ if (gethostname(lclhost,NFS_MAXHOSTLEN)) { Dprintf(L_ERROR,"gethostname failed"); return -1; } lclknown=1; } islcl=(!strcmp(host,"localhost") || !strcmp(host,lclhost)); if (islcl) Dprintf(D_CALL,"copy to %s (local)",host); else Dprintf(D_CALL,"copy to %s (remote)",host); sfd=getfd(&argp->filesrc,rqstp,argp->offsetsrc,&status,O_RDONLY,&sfhc); if (islcl) dfd=getfd(&argp->filedest,rqstp,argp->offsetdest,&status,O_WRONLY, &dfhc); else { warg.file= argp->filedest; warg.offset=argp->offsetdest; warg.beginoffset=argp->offsetdest; warg.data.data_val=iobuf; if(!(cp=clnt_create(host,NFS_PROGRAM,NFS_VERSION,"udp"))){ Dprintf(L_ERROR,"unable to create client"); clnt_pcreateerror(host); status =-1; goto failure; } } if (sfd<0 || (islcl && dfd<0)){ Dprintf(L_ERROR,"unable to open either src or dst"); goto failure; } /* Ok, got descriptors and/or the client connection: do the job */ nleft=argp->count; res->count=0; if (argp->offsetsrc == 0 && log_transfers) nfsd_xferlog(rqstp, "<", sfhc->path); for (limit=MAX_WORK ; limit>0 && nleft>0; limit--) { u_int nbytes = nleft; ssize_t rdres,wrres; attrstat *rpcres; errno=0; if (nbytes > NFS_MAXDATA) nbytes=NFS_MAXDATA; rdres= read(sfd,iobuf,nbytes); if (rdres <0) Dprintf(L_ERROR,"read failed"); else if (!rdres || errno){ status = NFS_OK; if (errno) status=nfs_errno(); break; } else res->count += rdres; if((status=fhc_getattr(sfhc, &res->attributessrc,NULL,rqstp))){ Dprintf(L_ERROR,"src fh status is not ok"); goto failure; } if (islcl) { if ((wrres=write(dfd,iobuf,rdres))!=rdres) { Dprintf(L_ERROR,"write failed (%d)",errno); goto failure; } if((status=fhc_getattr(dfhc, &res->attributesdest,NULL,rqstp))){ Dprintf(L_ERROR,"dst fh status is not ok"); goto failure; } } else { warg.totalcount=warg.data.data_len=rdres; if (!(rpcres=nfsproc_write_2(&warg,cp)) || rpcres->status != NFS_OK){ clnt_perror(cp, "write failed"); goto failure; } memcpy(&res->attributesdest, &rpcres->attrstat_u.attributes, sizeof(res->attributesdest)); warg.offset += rdres; warg.beginoffset += rdres; } nleft -= rdres; } failure: if (sfd>=0) fd_inactive(sfd); if (dfd>=0) fd_inactive(dfd); if (cp) clnt_destroy(cp); return status; }