]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
Performance tuning of AFP write operation
[netatalk.git] / etc / afpd / fork.c
index c09ff578970a52b7c52eddfb4ca5cc764e7c680d..1c2164fa1aa5c89ac385b723a47101793558e7f7 100644 (file)
@@ -846,15 +846,16 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
     LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
         of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
 
-   if (obj->options.flags & OPTION_AFP_READ_LOCK) {
-       if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, offset, reqcount, ofork->of_refnum) < 0) {
-           err = AFPERR_LOCK;
-           goto afp_read_err;
-       }
-   }
+    if (obj->options.flags & OPTION_AFP_READ_LOCK) {
+        if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, offset, reqcount, ofork->of_refnum) < 0) {
+            err = AFPERR_LOCK;
+            goto afp_read_err;
+        }
+    }
 
 #ifdef WITH_SENDFILE
-    if (!(obj->options.flags & OPTION_NOSENDFILE)) {
+    if (!(eid == ADEID_DFORK && ad_data_fileno(ofork->of_ad) == AD_SYMLINK) &&
+        !(obj->options.flags & OPTION_NOSENDFILE)) {
         int fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
         if (dsi_stream_read_file(dsi, fd, offset, reqcount, err) < 0) {
             LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s",
@@ -1103,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++;
@@ -1177,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:
@@ -1211,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;
     }
 
@@ -1222,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;