btrfs-progs: add option to disable backtrace usage
[platform/upstream/btrfs-progs.git] / send-stream.c
index a3628e4..10b36b6 100644 (file)
@@ -204,7 +204,7 @@ out:
                int __len; \
                TLV_GET(s, attr, (void**)&__tmp, &__len); \
                TLV_CHECK_LEN(sizeof(*__tmp), __len); \
-               *v = le##bits##_to_cpu(*__tmp); \
+               *v = get_unaligned_le##bits(__tmp); \
        } while (0)
 
 #define TLV_GET_U8(s, attr, v) TLV_GET_INT(s, attr, 8, v)
@@ -410,9 +410,6 @@ static int read_and_process_cmd(struct btrfs_send_stream *s)
                break;
        case BTRFS_SEND_C_UTIMES:
                TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
-               if (strstr(path, ".bak_1.log")) {
-                       ret = 0;
-               }
                TLV_GET_TIMESPEC(s, BTRFS_SEND_A_ATIME, &at);
                TLV_GET_TIMESPEC(s, BTRFS_SEND_A_MTIME, &mt);
                TLV_GET_TIMESPEC(s, BTRFS_SEND_A_CTIME, &ct);
@@ -438,12 +435,21 @@ out:
        return ret;
 }
 
+/*
+ * If max_errors is 0, then don't stop processing the stream if one of the
+ * callbacks in btrfs_send_ops structure returns an error. If greater than
+ * zero, stop after max_errors errors happened.
+ */
 int btrfs_read_and_process_send_stream(int fd,
-                                      struct btrfs_send_ops *ops, void *user)
+                                      struct btrfs_send_ops *ops, void *user,
+                                      int honor_end_cmd,
+                                      u64 max_errors)
 {
        int ret;
        struct btrfs_send_stream s;
        struct btrfs_stream_header hdr;
+       u64 errors = 0;
+       int last_err = 0;
 
        s.fd = fd;
        s.ops = ops;
@@ -473,14 +479,21 @@ int btrfs_read_and_process_send_stream(int fd,
 
        while (1) {
                ret = read_and_process_cmd(&s);
-               if (ret < 0)
-                       goto out;
-               if (ret) {
-                       ret = 0;
+               if (ret < 0) {
+                       last_err = ret;
+                       errors++;
+                       if (max_errors > 0 && errors >= max_errors)
+                               goto out;
+               } else if (ret > 0) {
+                       if (!honor_end_cmd)
+                               ret = 0;
                        goto out;
                }
        }
 
 out:
+       if (last_err && !ret)
+               ret = last_err;
+
        return ret;
 }