Add O_DIRECT flag to DD for cache bypass

FreeBSD DD utility has not had support for the O_DIRECT flag, which
is useful to bypass local caching, e.g. for unconditionally issuing
NFS IO requests during testing.

Reviewed by:	rgrimes (mentor)
Approved by:	rgrimes (mentor, blanket)
MFC after:	3 weeks
Sponsored by:	NetApp, Inc.
Differential Revision:	https://reviews.freebsd.org/D25066
This commit is contained in:
rscheff 2020-06-04 20:47:11 +00:00
parent 933837ffb5
commit a71bce46fb
4 changed files with 17 additions and 4 deletions

View File

@ -266,6 +266,7 @@ static const struct iflag {
const char *name; const char *name;
uint64_t set, noset; uint64_t set, noset;
} ilist[] = { } ilist[] = {
{ "direct", C_IDIRECT, 0 },
{ "fullblock", C_IFULLBLOCK, C_SYNC }, { "fullblock", C_IFULLBLOCK, C_SYNC },
}; };
@ -410,6 +411,7 @@ static const struct oflag {
const char *name; const char *name;
uint64_t set; uint64_t set;
} olist[] = { } olist[] = {
{ "direct", C_ODIRECT },
{ "fsync", C_OFSYNC }, { "fsync", C_OFSYNC },
{ "sync", C_OFSYNC }, { "sync", C_OFSYNC },
}; };

View File

@ -32,7 +32,7 @@
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94 .\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd March 26, 2019 .Dd June 4, 2020
.Dt DD 1 .Dt DD 1
.Os .Os
.Sh NAME .Sh NAME
@ -117,6 +117,8 @@ limits the number of times
is called on the input rather than the number of blocks copied in full. is called on the input rather than the number of blocks copied in full.
May not be combined with May not be combined with
.Cm conv=sync . .Cm conv=sync .
.It Cm direct
Set the O_DIRECT flag on the input file to make reads bypass any local caching.
.El .El
.It Cm iseek Ns = Ns Ar n .It Cm iseek Ns = Ns Ar n
Seek on the input file Seek on the input file
@ -143,7 +145,7 @@ the output file is truncated at that point.
Where Where
.Cm value .Cm value
is one of the symbols from the following list. is one of the symbols from the following list.
.Bl -tag -width "fsync" .Bl -tag -width "direct"
.It Cm fsync .It Cm fsync
Set the O_FSYNC flag on the output file to make writes synchronous. Set the O_FSYNC flag on the output file to make writes synchronous.
.It Cm sync .It Cm sync
@ -151,6 +153,8 @@ Set the O_SYNC flag on the output file to make writes synchronous.
This is synonymous with the This is synonymous with the
.Cm fsync .Cm fsync
value. value.
.It Cm direct
Set the O_DIRECT flag on the output file to make writes bypass any local caching.
.El .El
.It Cm oseek Ns = Ns Ar n .It Cm oseek Ns = Ns Ar n
Seek on the output file Seek on the output file

View File

@ -143,7 +143,7 @@ static void
setup(void) setup(void)
{ {
u_int cnt; u_int cnt;
int oflags; int iflags, oflags;
cap_rights_t rights; cap_rights_t rights;
unsigned long cmds[] = { FIODTYPE, MTIOCTOP }; unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
@ -151,7 +151,10 @@ setup(void)
in.name = "stdin"; in.name = "stdin";
in.fd = STDIN_FILENO; in.fd = STDIN_FILENO;
} else { } else {
in.fd = open(in.name, O_RDONLY, 0); iflags = 0;
if (ddflags & C_IDIRECT)
iflags |= O_DIRECT;
in.fd = open(in.name, O_RDONLY | iflags, 0);
if (in.fd == -1) if (in.fd == -1)
err(1, "%s", in.name); err(1, "%s", in.name);
} }
@ -186,6 +189,8 @@ setup(void)
oflags |= O_TRUNC; oflags |= O_TRUNC;
if (ddflags & C_OFSYNC) if (ddflags & C_OFSYNC)
oflags |= O_FSYNC; oflags |= O_FSYNC;
if (ddflags & C_ODIRECT)
oflags |= O_DIRECT;
out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE); out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE);
/* /*
* May not have read access, so try again with write only. * May not have read access, so try again with write only.

View File

@ -105,6 +105,8 @@ typedef struct {
#define C_FDATASYNC 0x0000000100000000ULL #define C_FDATASYNC 0x0000000100000000ULL
#define C_OFSYNC 0x0000000200000000ULL #define C_OFSYNC 0x0000000200000000ULL
#define C_IFULLBLOCK 0x0000000400000000ULL #define C_IFULLBLOCK 0x0000000400000000ULL
#define C_IDIRECT 0x0000000800000000ULL
#define C_ODIRECT 0x0000001000000000ULL
#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET) #define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)