Commit aea6ad0ce5e215ce99fe9e3edd9268f696862d8f

Authored by Christoph Hellwig
Committed by Lachlan McIlroy
1 parent fd0b45dfd1

[XFS] fix unaligned access in readdir

This patch should fix the issue seen on Alpha with unaligned accesses in
the new readdir code. By aligning each dirent to sizeof(u64) we'll avoid
unaligned accesses. To make doubly sure we're not hitting problems also
rearrange struct hack_dirent to avoid holes.

SGI-PV: 975411
SGI-Modid: xfs-linux-melb:xfs-kern:30302a

Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>

Showing 1 changed file with 10 additions and 6 deletions Side-by-side Diff

fs/xfs/linux-2.6/xfs_file.c
... ... @@ -261,9 +261,9 @@
261 261 #else
262 262  
263 263 struct hack_dirent {
264   - int namlen;
265   - loff_t offset;
266 264 u64 ino;
  265 + loff_t offset;
  266 + int namlen;
267 267 unsigned int d_type;
268 268 char name[];
269 269 };
270 270  
... ... @@ -285,8 +285,10 @@
285 285 {
286 286 struct hack_callback *buf = __buf;
287 287 struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);
  288 + unsigned int reclen;
288 289  
289   - if (buf->used + sizeof(struct hack_dirent) + namlen > buf->len)
  290 + reclen = ALIGN(sizeof(struct hack_dirent) + namlen, sizeof(u64));
  291 + if (buf->used + reclen > buf->len)
290 292 return -EINVAL;
291 293  
292 294 de->namlen = namlen;
... ... @@ -294,7 +296,7 @@
294 296 de->ino = ino;
295 297 de->d_type = d_type;
296 298 memcpy(de->name, name, namlen);
297   - buf->used += sizeof(struct hack_dirent) + namlen;
  299 + buf->used += reclen;
298 300 return 0;
299 301 }
300 302  
... ... @@ -334,7 +336,8 @@
334 336 offset = filp->f_pos;
335 337  
336 338 while (!eof) {
337   - int reclen;
  339 + unsigned int reclen;
  340 +
338 341 start_offset = offset;
339 342  
340 343 buf.used = 0;
... ... @@ -355,7 +358,8 @@
355 358 goto done;
356 359 }
357 360  
358   - reclen = sizeof(struct hack_dirent) + de->namlen;
  361 + reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen,
  362 + sizeof(u64));
359 363 size -= reclen;
360 364 de = (struct hack_dirent *)((char *)de + reclen);
361 365 curr_offset = de->offset /* & 0x7fffffff */;