openbmc/build/tmp/deploy/sdk/witherspoon-2019-08-08/sysroots/armv6-openbmc-linux-gnueabi/usr/src/debug/nbd/3.19-r0/nbd-3.19/nbd-server.c
int expwrite(off_t a, char* buf, size_t len, CLIENT* client, int fua)
{
    char pagebuf[DIFFPAGESIZE];
    off_t mapcnt, mapl, maph;
    off_t wrlen, rdlen;
    off_t pagestart;
    off_t offset;

    DEBUG("Asked to write %u bytes at %llu.\n", (unsigned int)len,
          (unsigned long long)a);

    if (!(client->server->flags & F_COPYONWRITE) &&
        !((client->server->flags & F_WAIT) && (client->export == NULL)))
        return (rawexpwrite_fully(a, buf, len, client, fua));

    mapl = a / DIFFPAGESIZE;
    maph = (a + len - 1) / DIFFPAGESIZE;

    for (mapcnt = mapl; mapcnt <= maph; mapcnt++)
    {
        pagestart = mapcnt * DIFFPAGESIZE;
        offset = a - pagestart;
        wrlen =
            (0 < DIFFPAGESIZE - offset && len < (size_t)(DIFFPAGESIZE - offset))
                ? len
                : (size_t)DIFFPAGESIZE - offset;

        if (!(client->server->flags & F_COPYONWRITE))
            pthread_rwlock_rdlock(&client->export_lock);
        if (client->difmap[mapcnt] != (u32)(-1))
        { /* the block is already there */
            DEBUG("Page %llu is at %lu\n", (unsigned long long)mapcnt,
                  (unsigned long)(client->difmap[mapcnt]));
            if (pwrite(client->difffile, buf, wrlen,
                       client->difmap[mapcnt] * DIFFPAGESIZE + offset) != wrlen)
                goto fail;
        }
        else
        { /* the block is not there */
            client->difmap[mapcnt] = (client->server->flags & F_SPARSE)
                                         ? mapcnt
                                         : client->difffilelen++;
            DEBUG("Page %llu is not here, we put it at %lu\n",
                  (unsigned long long)mapcnt,
                  (unsigned long)(client->difmap[mapcnt]));
            if ((offset != 0) || (wrlen != DIFFPAGESIZE))
            {
                if ((client->server->flags & F_WAIT) &&
                    (client->export == NULL))
                {
                    DEBUG("error: we can write only whole page while waiting "
                          "for file\n");
                    goto fail;
                }
                rdlen = DIFFPAGESIZE;
                if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
                    goto fail;
            }
            memcpy(pagebuf + offset, buf, wrlen);
            if (write(client->difffile, pagebuf, DIFFPAGESIZE) != DIFFPAGESIZE)
                goto fail;
        }
        if (!(client->server->flags & F_COPYONWRITE))
            pthread_rwlock_unlock(&client->export_lock);
        len -= wrlen;
        a += wrlen;
        buf += wrlen;
    }
    if (client->server->flags & F_SYNC)
    {
        fsync(client->difffile);
    }
    else if (fua)
    {
        /* open question: would it be cheaper to do multiple sync_file_ranges?
           as we iterate through the above?
         */
        fdatasync(client->difffile);
    }
    return 0;
fail:
    if (!(client->server->flags & F_COPYONWRITE))
        pthread_rwlock_unlock(&client->export_lock);
    return -1;
}
/**
 * Write an amount of bytes at a given offset to the right file. This
 * abstracts the write-side of the copyonwrite option, and calls
 * rawexpwrite() with the right parameters to do the actual work.
 *
 * @param a The offset where the write should start
 * @param buf The buffer to write from
 * @param len The length of buf
 * @param client The client we're going to write for.
 * @param fua Flag to indicate 'Force Unit Access'
 * @return 0 on success, nonzero on failure
 **/
Write an amount of bytes at a given offset to the right file. This
abstracts the write-side of the copyonwrite option, and calls
rawexpwrite() with the right parameters to do the actual work.

@param a The offset where the write should start
@param buf The buffer to write from
@param len The length of buf
@param client The client we're going to write for.
@param fua Flag to indicate 'Force Unit Access'
@return 0 on success, nonzero on failure
Write an amount of bytes at a given offset to the right file . This abstracts the write - side of the copyonwrite option and calls rawexpwrite () with the right parameters to do the actual work . @param a The offset where the write should start @param buf The buffer to write from @param len The length of buf @param client The client we ' re going to write for . @param fua Flag to indicate ' Force Unit Access ' @return 0 on success nonzero on failure
int expwrite(off_t a, char* buf, size_t len, CLIENT* client, int fua)
{
    char pagebuf[DIFFPAGESIZE];
    off_t mapcnt, mapl, maph;
    off_t wrlen, rdlen;
    off_t pagestart;
    off_t offset;
    DEBUG("Asked to write %u bytes at %llu.\n", (unsigned int)len,
          (unsigned long long)a);
    if (!(client->server->flags & F_COPYONWRITE) &&
        !((client->server->flags & F_WAIT) && (client->export == NULL)))
        return (rawexpwrite_fully(a, buf, len, client, fua));
    mapl = a / DIFFPAGESIZE;
    maph = (a + len - 1) / DIFFPAGESIZE;
    for (mapcnt = mapl; mapcnt <= maph; mapcnt++)
    {
        pagestart = mapcnt * DIFFPAGESIZE;
        offset = a - pagestart;
        wrlen =
            (0 < DIFFPAGESIZE - offset && len < (size_t)(DIFFPAGESIZE - offset))
                ? len
                : (size_t)DIFFPAGESIZE - offset;
        if (!(client->server->flags & F_COPYONWRITE))
            pthread_rwlock_rdlock(&client->export_lock);
        if (client->difmap[mapcnt] != (u32)(-1))
        { 
            DEBUG("Page %llu is at %lu\n", (unsigned long long)mapcnt,
                  (unsigned long)(client->difmap[mapcnt]));
            if (pwrite(client->difffile, buf, wrlen,
                       client->difmap[mapcnt] * DIFFPAGESIZE + offset) != wrlen)
                goto fail;
        }
        else
        { 
            client->difmap[mapcnt] = (client->server->flags & F_SPARSE)
                                         ? mapcnt
                                         : client->difffilelen++;
            DEBUG("Page %llu is not here, we put it at %lu\n",
                  (unsigned long long)mapcnt,
                  (unsigned long)(client->difmap[mapcnt]));
            if ((offset != 0) || (wrlen != DIFFPAGESIZE))
            {
                if ((client->server->flags & F_WAIT) &&
                    (client->export == NULL))
                {
                    DEBUG("error: we can write only whole page while waiting "
                          "for file\n");
                    goto fail;
                }
                rdlen = DIFFPAGESIZE;
                if (rawexpread_fully(pagestart, pagebuf, rdlen, client))
                    goto fail;
            }
            memcpy(pagebuf + offset, buf, wrlen);
            if (write(client->difffile, pagebuf, DIFFPAGESIZE) != DIFFPAGESIZE)
                goto fail;
        }
        if (!(client->server->flags & F_COPYONWRITE))
            pthread_rwlock_unlock(&client->export_lock);
        len -= wrlen;
        a += wrlen;
        buf += wrlen;
    }
    if (client->server->flags & F_SYNC)
    {
        fsync(client->difffile);
    }
    else if (fua)
    {
        fdatasync(client->difffile);
    }
    return 0;
fail:
    if (!(client->server->flags & F_COPYONWRITE))
        pthread_rwlock_unlock(&client->export_lock);
    return -1;
}
int expwrite ( off_t a , char * buf , size_t len , CLIENT * client , int fua ) { char pagebuf [ DIFFPAGESIZE ] ; off_t mapcnt , mapl , maph ; off_t wrlen , rdlen ; off_t pagestart ; off_t offset ; DEBUG ( " \n " , ( unsigned int ) len , ( unsigned long long ) a ) ; if ( ! ( client -> server -> flags & F_COPYONWRITE ) && ! ( ( client -> server -> flags & F_WAIT ) && ( client -> export == NULL ) ) ) return ( rawexpwrite_fully ( a , buf , len , client , fua ) ) ; mapl = a / DIFFPAGESIZE ; maph = ( a + len - 1 ) / DIFFPAGESIZE ; for ( mapcnt = mapl ; mapcnt <= maph ; mapcnt ++ ) { pagestart = mapcnt * DIFFPAGESIZE ; offset = a - pagestart ; wrlen = ( 0 < DIFFPAGESIZE - offset && len < ( size_t ) ( DIFFPAGESIZE - offset ) ) ? len : ( size_t ) DIFFPAGESIZE - offset ; if ( ! ( client -> server -> flags & F_COPYONWRITE ) ) pthread_rwlock_rdlock ( & client -> export_lock ) ; if ( client -> difmap [ mapcnt ] != ( u32 ) ( -1 ) ) { DEBUG ( " \n " , ( unsigned long long ) mapcnt , ( unsigned long ) ( client -> difmap [ mapcnt ] ) ) ; if ( pwrite ( client -> difffile , buf , wrlen , client -> difmap [ mapcnt ] * DIFFPAGESIZE + offset ) != wrlen ) goto fail ; } else { client -> difmap [ mapcnt ] = ( client -> server -> flags & F_SPARSE ) ? mapcnt : client -> difffilelen ++ ; DEBUG ( " \n " , ( unsigned long long ) mapcnt , ( unsigned long ) ( client -> difmap [ mapcnt ] ) ) ; if ( ( offset != 0 ) || ( wrlen != DIFFPAGESIZE ) ) { if ( ( client -> server -> flags & F_WAIT ) && ( client -> export == NULL ) ) { DEBUG ( " " " \n " ) ; goto fail ; } rdlen = DIFFPAGESIZE ; if ( rawexpread_fully ( pagestart , pagebuf , rdlen , client ) ) goto fail ; } memcpy ( pagebuf + offset , buf , wrlen ) ; if ( write ( client -> difffile , pagebuf , DIFFPAGESIZE ) != DIFFPAGESIZE ) goto fail ; } if ( ! ( client -> server -> flags & F_COPYONWRITE ) ) pthread_rwlock_unlock ( & client -> export_lock ) ; len -= wrlen ; a += wrlen ; buf += wrlen ; } if ( client -> server -> flags & F_SYNC ) { fsync ( client -> difffile ) ; } else if ( fua ) { fdatasync ( client -> difffile ) ; } return 0 ; fail : if ( ! ( client -> server -> flags & F_COPYONWRITE ) ) pthread_rwlock_unlock ( & client -> export_lock ) ; return -1 ; }
Write an amount of bytes at a given offset to the right file.
Write an amount of bytes at a given offset to the right file .
/* the block is already there */ /* the block is not there */ /* open question: would it be cheaper to do multiple sync_file_ranges?
           as we iterate through the above?
         */