Package: busybox
Version: v1.31.1
Severity: wishlist
This implementation assumes that iflag/oflag=direct will be used only on
block devices and files that are multiples of pagesize, and makes no
effort to solve issues with unaligned or partial reads (unlike gnu
coreutils dd)
Using iflag/oflag=direct will also limit usage block sizes, which must
also be a multiple of pagesize
--
Akash Hadke
800-7474-400
diff --git a/coreutils/dd.c b/coreutils/dd.c
index b5f3cbe..b4fb71a 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -59,7 +59,7 @@
//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n"
//usage: IF_FEATURE_DD_IBS_OBS(
//usage: " [conv=notrunc|noerror|sync|fsync]\n"
-//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]"
+//usage: " [iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]"
//usage: )
//usage:#define dd_full_usage "\n\n"
//usage: "Copy a file with converting and formatting\n"
@@ -83,8 +83,10 @@
//usage: "\n conv=swab Swap every pair of bytes"
//usage: "\n iflag=skip_bytes skip=N is in bytes"
//usage: "\n iflag=fullblock Read full blocks"
+//usage: "\n iflag=direct use direct I/O for data (limited support, file and bs must be a pagesize multiple)"
//usage: "\n oflag=seek_bytes seek=N is in bytes"
//usage: "\n oflag=append Open output file in append mode"
+//usage: "\n oflag=direct use direct I/O for data (limited support, file and bs must be a pagesize multiple)"
//usage: )
//usage: IF_FEATURE_DD_STATUS(
//usage: "\n status=noxfer Suppress rate output"
@@ -137,16 +139,18 @@ enum {
FLAG_IFLAG_SHIFT = 5,
FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
/* end of input flags */
/* start of output flags */
- FLAG_OFLAG_SHIFT = 7,
- FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
- FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_OFLAG_SHIFT = 8,
+ FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS,
/* end of output flags */
- FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
- FLAG_COUNT = 1 << 10,
- FLAG_STATUS_NONE = 1 << 11,
- FLAG_STATUS_NOXFER = 1 << 12,
+ FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS,
+ FLAG_COUNT = 1 << 12,
+ FLAG_STATUS_NONE = 1 << 13,
+ FLAG_STATUS_NOXFER = 1 << 14,
};
static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -252,6 +256,13 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in)
}
return flags;
}
+
+static char *ptr_align(char *ptr, size_t alignment)
+{
+ char *p0 = ptr;
+ char *p1 = p0 + alignment - 1;
+ return p1 - (size_t) p1 % alignment;
+}
#endif
int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -267,9 +278,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
static const char conv_words[] ALIGN1 =
"notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
static const char iflag_words[] ALIGN1 =
- "skip_bytes\0""fullblock\0";
+ "skip_bytes\0""fullblock\0""direct\0";
static const char oflag_words[] ALIGN1 =
- "seek_bytes\0append\0";
+ "seek_bytes\0append\0""direct\0";
#endif
#if ENABLE_FEATURE_DD_STATUS
static const char status_words[] ALIGN1 =
@@ -310,7 +321,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
//swab swap every pair of input bytes: will abort on non-even reads
OP_iflag_skip_bytes,
OP_iflag_fullblock,
+ OP_iflag_direct,
OP_oflag_seek_bytes,
+ OP_oflag_direct,
#endif
};
smallint exitcode = EXIT_FAILURE;
@@ -320,9 +333,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_DD_IBS_OBS
size_t obs = 512;
char *obuf;
+ char *ibufptr, *obufptr;
+ int pagesize;
#else
# define obs ibs
# define obuf ibuf
+# define ibufptr ibuf
+# define obufptr ibuf
#endif
/* These are all zeroed at once! */
struct {
@@ -427,13 +444,33 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
} /* end of "for (argv[i])" */
//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
- ibuf = xmalloc(ibs);
- obuf = ibuf;
#if ENABLE_FEATURE_DD_IBS_OBS
+ /* because of O_DIRECT, block needs to be page-aligned */
+ pagesize = getpagesize();
+ ibufptr = xmalloc(ibs + pagesize);
+ obufptr = ibufptr;
if (ibs != obs) {
G.flags |= FLAG_TWOBUFS;
- obuf = xmalloc(obs);
+ obufptr = xmalloc(obs + pagesize);
}
+
+ /* most filesystems will refuse O_DIRECT if read/writes aren't pagesize aligned */
+ if ((G.flags & FLAG_IDIRECT) && (ibs % pagesize)) {
+ bb_error_msg_and_die("iflag=direct needs bs %lu to be a multiple of pagesize %d",
+ ibs, pagesize);
+ }
+ if ((G.flags & FLAG_ODIRECT) && (obs % pagesize)) {
+ bb_error_msg_and_die("oflag=direct needs bs %lu to be a multiple of pagesize %d",
+ ibs, pagesize);
+ }
+
+ ibuf = ptr_align(ibufptr, pagesize);
+ obuf = ptr_align(obufptr, pagesize);
+#else
+ ibufptr = xmalloc(ibs);
+ obufptr = ibufptr;
+ ibuf = ibufptr;
+ obuf = obufptr;
#endif
#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
@@ -444,7 +481,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
#endif
if (infile) {
- xmove_fd(xopen(infile, O_RDONLY), ifd);
+ int iflag = O_RDONLY;
+
+#if ENABLE_FEATURE_DD_IBS_OBS
+ if (G.flags & FLAG_IDIRECT)
+ iflag |= O_DIRECT;
+#endif
+
+ xmove_fd(xopen(infile, iflag), ifd);
} else {
infile = bb_msg_standard_input;
}
@@ -455,6 +499,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
oflag |= O_TRUNC;
if (G.flags & FLAG_APPEND)
oflag |= O_APPEND;
+#if ENABLE_FEATURE_DD_IBS_OBS
+ if (G.flags & FLAG_ODIRECT)
+ oflag |= O_DIRECT;
+#endif
xmove_fd(xopen(outfile, oflag), ofd);
@@ -601,9 +649,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
dd_output_status(0);
if (ENABLE_FEATURE_CLEAN_UP) {
- free(obuf);
+ free(obufptr);
if (G.flags & FLAG_TWOBUFS)
- free(ibuf);
+ free(ibufptr);
}
return exitcode;
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox