Skip to content

Commit 5edc855

Browse files
committed
file-posix: Allow byte-aligned O_DIRECT with NFS
Since commit a6b257a ('file-posix: Handle undetectable alignment'), we assume that if we open a file with O_DIRECT and alignment probing returns 1, we just couldn't find out the real alignment requirement because some filesystems make the requirement only for allocated blocks. In this case, a safe default of 4k is used. This is too strict for NFS, which does actually allow byte-aligned requests even with O_DIRECT. Because we can't distinguish both cases with generic code, let's just look at the file system magic and disable s->needs_alignment for NFS. This way, O_DIRECT can still be used on NFS for images that are not aligned to 4k. Signed-off-by: Kevin Wolf <[email protected]> Reviewed-by: Eric Blake <[email protected]> Message-Id: <[email protected]> Reviewed-by: Max Reitz <[email protected]> Signed-off-by: Kevin Wolf <[email protected]>
1 parent 9c60a5d commit 5edc855

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

block/file-posix.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@
6262
#include <sys/ioctl.h>
6363
#include <sys/param.h>
6464
#include <sys/syscall.h>
65+
#include <sys/vfs.h>
6566
#include <linux/cdrom.h>
6667
#include <linux/fd.h>
6768
#include <linux/fs.h>
6869
#include <linux/hdreg.h>
70+
#include <linux/magic.h>
6971
#include <scsi/sg.h>
7072
#ifdef __s390__
7173
#include <asm/dasd.h>
@@ -300,6 +302,28 @@ static int probe_physical_blocksize(int fd, unsigned int *blk_size)
300302
#endif
301303
}
302304

305+
/*
306+
* Returns true if no alignment restrictions are necessary even for files
307+
* opened with O_DIRECT.
308+
*
309+
* raw_probe_alignment() probes the required alignment and assume that 1 means
310+
* the probing failed, so it falls back to a safe default of 4k. This can be
311+
* avoided if we know that byte alignment is okay for the file.
312+
*/
313+
static bool dio_byte_aligned(int fd)
314+
{
315+
#ifdef __linux__
316+
struct statfs buf;
317+
int ret;
318+
319+
ret = fstatfs(fd, &buf);
320+
if (ret == 0 && buf.f_type == NFS_SUPER_MAGIC) {
321+
return true;
322+
}
323+
#endif
324+
return false;
325+
}
326+
303327
/* Check if read is allowed with given memory buffer and length.
304328
*
305329
* This function is used to check O_DIRECT memory buffer and request alignment.
@@ -629,7 +653,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
629653

630654
s->has_discard = true;
631655
s->has_write_zeroes = true;
632-
if ((bs->open_flags & BDRV_O_NOCACHE) != 0) {
656+
if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
633657
s->needs_alignment = true;
634658
}
635659

0 commit comments

Comments
 (0)