Skip to content

Commit

Permalink
unset O_DIRECT flag on last chunk if irregular sized
Browse files Browse the repository at this point in the history
  • Loading branch information
cre4ture committed Mar 15, 2024
1 parent f8e5296 commit 2b38f71
Showing 1 changed file with 30 additions and 2 deletions.
32 changes: 30 additions & 2 deletions src/uu/dd/src/dd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat seekable oconv canonicalized fadvise Fadvise FADV DONTNEED ESPIPE bufferedoutput
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile,
// spell-checker:ignore fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty,
// spell-checker:ignore datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror,
// spell-checker:ignore nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat,
// spell-checker:ignore sigusr, wlen, wstat seekable oconv canonicalized fadvise Fadvise FADV DONTNEED ESPIPE bufferedoutput
// spell-checker:ignore GETFL SETFL

mod blocks;
mod bufferedoutput;
Expand Down Expand Up @@ -41,6 +46,8 @@ use std::time::{Duration, Instant};

use clap::{crate_version, Arg, Command};
use gcd::Gcd;
#[cfg(unix)]
use nix::fcntl::{fcntl, FcntlArg, OFlag};
#[cfg(target_os = "linux")]
use nix::{
errno::Errno,
Expand Down Expand Up @@ -509,6 +516,20 @@ enum Dest {
}

impl Dest {
fn unset_direct(&mut self) -> io::Result<()> {
match self {
#[cfg(unix)]
Self::File(f, _d) => {
let mut mode = OFlag::from_bits_retain(fcntl(f.as_raw_fd(), FcntlArg::F_GETFL)?);
mode.remove(OFlag::O_DIRECT);
nix::fcntl::fcntl(f.as_raw_fd(), FcntlArg::F_SETFL(mode))?;
}
_ => {}
}

Ok(())
}

fn fsync(&mut self) -> io::Result<()> {
match self {
Self::Stdout(stdout) => stdout.flush(),
Expand Down Expand Up @@ -774,7 +795,14 @@ impl<'a> Output<'a> {
let mut writes_partial = 0;
let mut bytes_total = 0;

for chunk in buf.chunks(self.settings.obs) {
let chunk_size = self.settings.obs;
for chunk in buf.chunks(chunk_size) {
if (self.settings.oflags.direct) && (chunk.len() < chunk_size) {
// in case of direct io, only buffers with chunk_size are accepted.
// thus, for writing a (last) buffer with irregular length, we need to switch off the direct io.
self.dst.unset_direct()?;
}

let wlen = self.dst.write(chunk)?;
if wlen < self.settings.obs {
writes_partial += 1;
Expand Down

0 comments on commit 2b38f71

Please sign in to comment.