[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>

authored by Christoph Hellwig and committed by Lachlan McIlroy aea6ad0c fd0b45df

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