]>
Commit | Line | Data |
---|---|---|
3dcc8d3b | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
e4909010 WB |
2 | From: Jeff Cody <jcody@redhat.com> |
3 | Date: Tue, 23 May 2017 13:27:50 -0400 | |
3dcc8d3b | 4 | Subject: [PATCH] block/gluster: glfs_lseek() workaround |
e4909010 WB |
5 | |
6 | On current released versions of glusterfs, glfs_lseek() will sometimes | |
7 | return invalid values for SEEK_DATA or SEEK_HOLE. For SEEK_DATA and | |
8 | SEEK_HOLE, the returned value should be >= the passed offset, or < 0 in | |
9 | the case of error: | |
10 | ||
11 | LSEEK(2): | |
12 | ||
13 | off_t lseek(int fd, off_t offset, int whence); | |
14 | ||
15 | [...] | |
16 | ||
17 | SEEK_HOLE | |
18 | Adjust the file offset to the next hole in the file greater | |
19 | than or equal to offset. If offset points into the middle of | |
20 | a hole, then the file offset is set to offset. If there is no | |
21 | hole past offset, then the file offset is adjusted to the end | |
22 | of the file (i.e., there is an implicit hole at the end of | |
23 | any file). | |
24 | ||
25 | [...] | |
26 | ||
27 | RETURN VALUE | |
28 | Upon successful completion, lseek() returns the resulting | |
29 | offset location as measured in bytes from the beginning of the | |
30 | file. On error, the value (off_t) -1 is returned and errno is | |
31 | set to indicate the error | |
32 | ||
33 | However, occasionally glfs_lseek() for SEEK_HOLE/DATA will return a | |
34 | value less than the passed offset, yet greater than zero. | |
35 | ||
36 | For instance, here are example values observed from this call: | |
37 | ||
38 | offs = glfs_lseek(s->fd, start, SEEK_HOLE); | |
39 | if (offs < 0) { | |
40 | return -errno; /* D1 and (H3 or H4) */ | |
41 | } | |
42 | ||
43 | start == 7608336384 | |
44 | offs == 7607877632 | |
45 | ||
46 | This causes QEMU to abort on the assert test. When this value is | |
47 | returned, errno is also 0. | |
48 | ||
49 | This is a reported and known bug to glusterfs: | |
50 | https://bugzilla.redhat.com/show_bug.cgi?id=1425293 | |
51 | ||
52 | Although this is being fixed in gluster, we still should work around it | |
53 | in QEMU, given that multiple released versions of gluster behave this | |
54 | way. | |
55 | ||
56 | This patch treats the return case of (offs < start) the same as if an | |
57 | error value other than ENXIO is returned; we will assume we learned | |
58 | nothing, and there are no holes in the file. | |
59 | ||
60 | Signed-off-by: Jeff Cody <jcody@redhat.com> | |
61 | Reviewed-by: Eric Blake <eblake@redhat.com> | |
62 | Reviewed-by: Niels de Vos <ndevos@redhat.com> | |
63 | Message-id: 87c0140e9407c08f6e74b04131b610f2e27c014c.1495560397.git.jcody@redhat.com | |
64 | Signed-off-by: Jeff Cody <jcody@redhat.com> | |
65 | --- | |
66 | block/gluster.c | 18 ++++++++++++++++-- | |
67 | 1 file changed, 16 insertions(+), 2 deletions(-) | |
68 | ||
69 | diff --git a/block/gluster.c b/block/gluster.c | |
70 | index 4fdf68f1fc..06421ef79d 100644 | |
71 | --- a/block/gluster.c | |
72 | +++ b/block/gluster.c | |
73 | @@ -1287,7 +1287,14 @@ static int find_allocation(BlockDriverState *bs, off_t start, | |
74 | if (offs < 0) { | |
75 | return -errno; /* D3 or D4 */ | |
76 | } | |
77 | - assert(offs >= start); | |
78 | + | |
79 | + if (offs < start) { | |
80 | + /* This is not a valid return by lseek(). We are safe to just return | |
81 | + * -EIO in this case, and we'll treat it like D4. Unfortunately some | |
82 | + * versions of gluster server will return offs < start, so an assert | |
83 | + * here will unnecessarily abort QEMU. */ | |
84 | + return -EIO; | |
85 | + } | |
86 | ||
87 | if (offs > start) { | |
88 | /* D2: in hole, next data at offs */ | |
89 | @@ -1319,7 +1326,14 @@ static int find_allocation(BlockDriverState *bs, off_t start, | |
90 | if (offs < 0) { | |
91 | return -errno; /* D1 and (H3 or H4) */ | |
92 | } | |
93 | - assert(offs >= start); | |
94 | + | |
95 | + if (offs < start) { | |
96 | + /* This is not a valid return by lseek(). We are safe to just return | |
97 | + * -EIO in this case, and we'll treat it like H4. Unfortunately some | |
98 | + * versions of gluster server will return offs < start, so an assert | |
99 | + * here will unnecessarily abort QEMU. */ | |
100 | + return -EIO; | |
101 | + } | |
102 | ||
103 | if (offs > start) { | |
104 | /* | |
105 | -- | |
106 | 2.11.0 | |
107 |