xfstest splats
Darrick J. Wong
darrick.wong at oracle.com
Wed Apr 30 10:41:06 PDT 2014
On Tue, Apr 29, 2014 at 08:56:04PM +0900, OGAWA Hirofumi wrote:
> "Darrick J. Wong" <darrick.wong at oracle.com> writes:
>
> > Hi all,
> >
> > I ran xfstests against tux3 on 3.15-rc3, with default options (primarily
> > because I don't know what options exist anyway). xfstest generic/310 spit out
> > this:
> >
> > TUX3-fs error (sda): tux_readdir:398: zero length entry at inum 8192, block 15
>
> This bug was by wrong dir f_pos from 310, and current tux3 behavior is
> error=panic. As a result, it caused of BUG().
>
> Well, this patch checks pos, and dir entry more (from ext4 checker). And
> additionally, checks f_pos alignment is valid at first.
>
> And finally, convert from error=panic to just error message if
> readdir().
This fixes the generic/310 problem, thank you!
--D
>
> [FIXME: If f_pos is invalid, SuSv4 says unspecified behavior. and now,
> skips that block, and continue at next block. What is good behavior?]
>
> Thanks.
>
> Signed-off-by: OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>
> ---
>
> user/kernel/dir.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
> user/kernel/tux3.h | 6 ++++--
> user/tux3user.h | 6 ++++--
> 3 files changed, 51 insertions(+), 8 deletions(-)
>
> diff -puN user/kernel/dir.c~dir-make-robust user/kernel/dir.c
> --- tux3/user/kernel/dir.c~dir-make-robust 2014-04-29 17:56:00.268760455 +0900
> +++ tux3-hirofumi/user/kernel/dir.c 2014-04-29 18:58:44.666310736 +0900
> @@ -363,6 +363,39 @@ static unsigned char filetype[TUX_TYPES]
> [TUX_LNK] = DT_LNK,
> };
>
> +/*
> + * Return 0 if the directory entry is OK, and 1 if there is a problem
> + */
> +static int __check_dir_entry(const char *func, int line, struct inode *dir,
> + struct buffer_head *buffer, tux_dirent *entry)
> +{
> + struct sb *sb = tux_sb(dir->i_sb);
> + const char *error_msg = NULL;
> + const void *base = bufdata(buffer);
> + const int off = (void *)entry - base;
> + const int rlen = tux_rec_len_from_disk(entry->rec_len);
> +
> + if (unlikely(rlen < TUX_REC_LEN(1)))
> + error_msg = "rec_len is smaller than minimal";
> + else if (unlikely(rlen % TUX_DIR_ALIGN != 0))
> + error_msg = "rec_len alignment error";
> + else if (unlikely(rlen < TUX_REC_LEN(entry->name_len)))
> + error_msg = "rec_len is too small for name_len";
> + else if (unlikely(off + rlen > sb->blocksize))
> + error_msg = "directory entry across range";
> + else
> + return 0;
> +
> + __tux3_err(sb, func, line,
> + "bad entry: %s: inum %Lu, block %Lu, off %d, rec_len %d",
> + error_msg, tux_inode(dir)->inum, bufindex(buffer),
> + off, rlen);
> +
> + return 1;
> +}
> +#define check_dir_entry(d, b, e) \
> + __check_dir_entry(__func__, __LINE__, d, b, e)
> +
> int tux_readdir(struct file *file, struct dir_context *ctx)
> {
> struct inode *dir = file_inode(file);
> @@ -374,6 +407,12 @@ int tux_readdir(struct file *file, struc
>
> assert(!(dir->i_size & sb->blockmask));
>
> + if (offset % TUX_DIR_ALIGN) {
> + /* Invalid offset, skip to next block */
> + ctx->pos = (ctx->pos | (sb->blocksize - 1)) + 1;
> + offset = 0;
> + }
> +
> for (block = ctx->pos >> blockbits; block < blocks; block++) {
> struct buffer_head *buffer = blockread(mapping(dir), block);
> if (!buffer)
> @@ -393,10 +432,10 @@ int tux_readdir(struct file *file, struc
> }
> tux_dirent *limit = base + sb->blocksize - TUX_REC_LEN(1);
> for (tux_dirent *entry = base + offset; entry <= limit; entry = next_entry(entry)) {
> - if (entry->rec_len == 0) {
> - blockput(buffer);
> - tux_zero_len_error(dir, block);
> - return -EIO;
> + if (check_dir_entry(dir, buffer, entry)) {
> + /* On error, skip to next block */
> + ctx->pos = (ctx->pos | (sb->blocksize - 1)) + 1;
> + break;
> }
> if (!is_deleted(entry)) {
> unsigned type = (entry->type < TUX_TYPES) ? filetype[entry->type] : DT_UNKNOWN;
> diff -puN user/kernel/tux3.h~dir-make-robust user/kernel/tux3.h
> --- tux3/user/kernel/tux3.h~dir-make-robust 2014-04-29 18:42:30.553071700 +0900
> +++ tux3-hirofumi/user/kernel/tux3.h 2014-04-29 18:51:29.007547097 +0900
> @@ -704,9 +704,11 @@ int blockio_vec(int rw, struct bufvec *b
>
> #define tux3_msg(sb, fmt, ...) \
> __tux3_msg(sb, KERN_INFO, "", fmt, ##__VA_ARGS__)
> -#define tux3_err(sb, fmt, ...) \
> +#define __tux3_err(sb, func, line, fmt, ...) \
> __tux3_msg(sb, KERN_ERR, " error", \
> - "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
> + "%s:%d: " fmt, func, line, ##__VA_ARGS__)
> +#define tux3_err(sb, fmt, ...) \
> + __tux3_err(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
> #define tux3_warn(sb, fmt, ...) \
> __tux3_msg(sb, KERN_WARNING, " warning", fmt, ##__VA_ARGS__)
>
> diff -puN user/tux3user.h~dir-make-robust user/tux3user.h
> --- tux3/user/tux3user.h~dir-make-robust 2014-04-29 18:43:13.460952866 +0900
> +++ tux3-hirofumi/user/tux3user.h 2014-04-29 18:49:57.279807808 +0900
> @@ -143,9 +143,11 @@ int blockio_vec(int rw, struct bufvec *b
>
> #define tux3_msg(sb, fmt, ...) \
> __tux3_msg(sb, "", "", fmt "\n", ##__VA_ARGS__)
> -#define tux3_err(sb, fmt, ...) \
> +#define __tux3_err(sb, func, line, fmt, ...) \
> __tux3_msg(sb, "", "", \
> - "Error: %s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
> + "Error: %s:%d: " fmt "\n", func, line, ##__VA_ARGS__)
> +#define tux3_err(sb, fmt, ...) \
> + __tux3_err(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
> #define tux3_warn(sb, fmt, ...) \
> __tux3_msg(sb, "", "", "Warning: " fmt "\n", ##__VA_ARGS__)
>
> _
> --
> OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>
More information about the Tux3
mailing list