From: Frank Lahm Date: Sun, 6 May 2012 10:21:18 +0000 (+0200) Subject: Performance tuning of AFP write operation X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=f691d045c611bcb230543310f05d832d52e54463 Performance tuning of AFP write operation --- diff --git a/NEWS b/NEWS index d73830c7..3915485d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Changes in 3.0 beta1 +==================== +* UPD: afpd: Performance tuning of read/write AFP operations. New option + "afp read lock" (default: no) which disables that the server + applies UNIX byte range locks to regions of files in AFP read and + write calls. + Changes in 3.0 alpha3 ===================== diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 3e557ad6..1c2164fa 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1104,16 +1104,21 @@ static ssize_t write_file(struct ofork *ofork, int eid, } -/* FPWrite. NOTE: on an error, we always use afp_write_err as +/* + * FPWrite. NOTE: on an error, we always use afp_write_err as * the client may have sent us a bunch of data that's not reflected - * in reqcount et al. */ + * in reqcount et al. + */ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) { struct ofork *ofork; - off_t offset, saveoff, reqcount, oldsize, newsize; + off_t offset, saveoff, reqcount, oldsize, newsize; int endflag, eid, err = AFP_OK; - uint16_t ofrefnum; - ssize_t cc; + uint16_t ofrefnum; + ssize_t cc; + DSI *dsi = obj->dsi; + char *rcvbuf = dsi->buffer; + size_t rcvbuflen = dsi->dsireadbuf * dsi->server_quantum; /* figure out parameters */ ibuf++; @@ -1178,28 +1183,28 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s } saveoff = offset; - if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff, - reqcount, ofork->of_refnum) < 0) { - err = AFPERR_LOCK; - goto afp_write_err; + if (obj->options.flags & OPTION_AFP_READ_LOCK) { + if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff, reqcount, ofork->of_refnum) < 0) { + err = AFPERR_LOCK; + goto afp_write_err; + } } - DSI *dsi = obj->dsi; - /* find out what we have already and write it out. */ - cc = dsi_writeinit(dsi, rbuf, *rbuflen); + /* find out what we have already */ + cc = dsi_writeinit(dsi, rcvbuf, rcvbuflen); - if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) { + if (!cc || (cc = write_file(ofork, eid, offset, rcvbuf, cc)) < 0) { dsi_writeflush(dsi); *rbuflen = 0; - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); return cc; } offset += cc; #if 0 /*def HAVE_SENDFILE_WRITE*/ - if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket, - offset, dsi->datasize)) < 0) { + if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize)) < 0) { switch (errno) { case EDQUOT: case EFBIG: @@ -1212,8 +1217,8 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s } dsi_writeflush(dsi); *rbuflen = 0; - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, - reqcount, ofork->of_refnum); + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); return cc; } @@ -1223,18 +1228,24 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s /* loop until everything gets written. currently * dsi_write handles the end case by itself. */ - while ((cc = dsi_write(dsi, rbuf, *rbuflen))) { - if ((cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) { + while ((cc = dsi_write(dsi, rcvbuf, rcvbuflen))) { + + if ((cc = write_file(ofork, eid, offset, rcvbuf, cc)) < 0) { dsi_writeflush(dsi); *rbuflen = 0; - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, - reqcount, ofork->of_refnum); + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); return cc; } + + LOG(log_debug, logtype_afpd, "afp_write: wrote: %jd, offset: %jd", + (intmax_t)cc, (intmax_t)offset); + offset += cc; } - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */ ofork->of_flags |= AFPFORK_DIRTY; diff --git a/libatalk/dsi/dsi_write.c b/libatalk/dsi/dsi_write.c index 3e96489e..13a72347 100644 --- a/libatalk/dsi/dsi_write.c +++ b/libatalk/dsi/dsi_write.c @@ -21,10 +21,8 @@ #include #include - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif /* ! MIN */ +#include +#include /* initialize relevant things for dsi_write. this returns the amount * of data in the data buffer. the interface has been reworked to allow @@ -37,17 +35,21 @@ size_t dsi_writeinit(DSI *dsi, void *buf, const size_t buflen _U_) * data */ header = ntohl(dsi->header.dsi_code); dsi->datasize = header ? ntohl(dsi->header.dsi_len) - header : 0; + if (dsi->datasize > 0) { - len = MIN(sizeof(dsi->commands) - header, dsi->datasize); - - /* write last part of command buffer into buf */ - memcpy(buf, dsi->commands + header, len); - - /* recalculate remaining data */ - dsi->datasize -= len; + len = MIN(sizeof(dsi->commands) - header, dsi->datasize); + + /* write last part of command buffer into buf */ + memcpy(buf, dsi->commands + header, len); + + /* recalculate remaining data */ + dsi->datasize -= len; } else len = 0; + LOG(log_maxdebug, logtype_dsi, "dsi_writeinit: len: %ju, remaining DSI datasize: %jd", + (intmax_t)len, (intmax_t)dsi->datasize); + return len; } @@ -58,10 +60,14 @@ size_t dsi_write(DSI *dsi, void *buf, const size_t buflen) { size_t length; - if (((length = MIN(buflen, dsi->datasize)) > 0) && - ((length = dsi_stream_read(dsi, buf, length)) > 0)) { - dsi->datasize -= length; - return length; + LOG(log_maxdebug, logtype_dsi, "dsi_write: remaining DSI datasize: %jd", (intmax_t)dsi->datasize); + + if ((length = MIN(buflen, dsi->datasize)) > 0) { + if ((length = dsi_stream_read(dsi, buf, length)) > 0) { + LOG(log_maxdebug, logtype_dsi, "dsi_write: received: %ju", (intmax_t)length); + dsi->datasize -= length; + return length; + } } return 0; }