next up previous
Siguiente: GNU Free Documentation License Superior: Mejorando NFS Anterior: Cambios al cliente

Cambios en el servidor

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;
}




Download this document: [src.tar.gz][ps.gz][html.tar.gz][dvi.gz]

Congreso HispaLinux 2000