summaryrefslogtreecommitdiff
path: root/fs/orangefs
diff options
context:
space:
mode:
authorMartin Brandenburg <martin@omnibond.com>2017-05-02 19:15:10 +0300
committerMike Marshall <hubcap@omnibond.com>2017-05-04 21:38:10 +0300
commitbf15ba7c1f9ad000d062968f931e80234db84a24 (patch)
tree9f5c413977e91c7fe6df153bc625833ad2ae78eb /fs/orangefs
parent907bfcd8d8a616ca794ba187f6bf1b0e12b3a8dd (diff)
downloadlinux-bf15ba7c1f9ad000d062968f931e80234db84a24.tar.xz
orangefs: skip forward to the next directory entry if seek is short
If userspace seeks to a position in the stream which is not correct, it would have returned EIO because the data in the buffer at that offset would be incorrect. This and the userspace daemon returning a corrupt directory are indistinguishable. Now if the data does not look right, skip forward to the next chunk and try again. The motivation is that if the directory changes, an application may seek to a position that was valid and no longer is valid. It is not yet possible for a directory to change. Signed-off-by: Martin Brandenburg <martin@omnibond.com> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs')
-rw-r--r--fs/orangefs/dir.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/orangefs/dir.c b/fs/orangefs/dir.c
index d5ec9ba82cef..4cfb3e5b597e 100644
--- a/fs/orangefs/dir.c
+++ b/fs/orangefs/dir.c
@@ -194,11 +194,18 @@ static int fill_from_part(struct orangefs_dir_part *part,
/* The file offset from userspace is too large. */
if (i > part->len)
- return -EIO;
+ return 1;
+
+ /*
+ * If the seek pointer is positioned just before an entry it
+ * should find the next entry.
+ */
+ if (i % 8)
+ i = i + (8 - i%8)%8;
while (i < part->len) {
if (part->len < i + sizeof *len)
- return -EIO;
+ break;
len = (void *)part + offset + i;
/*
* len is the size of the string itself. padlen is the
@@ -207,10 +214,10 @@ static int fill_from_part(struct orangefs_dir_part *part,
padlen = (sizeof *len + *len + 1) +
(8 - (sizeof *len + *len + 1)%8)%8;
if (part->len < i + padlen + sizeof *khandle)
- return -EIO;
+ goto next;
s = (void *)part + offset + i + sizeof *len;
if (s[*len] != 0)
- return -EIO;
+ goto next;
khandle = (void *)part + offset + i + padlen;
if (!dir_emit(ctx, s, *len,
orangefs_khandle_to_ino(khandle),
@@ -220,6 +227,9 @@ static int fill_from_part(struct orangefs_dir_part *part,
i = i + (8 - i%8)%8;
BUG_ON(i > part->len);
ctx->pos = (ctx->pos & PART_MASK) | i;
+ continue;
+next:
+ i += 8;
}
return 1;
}