Skip to content

Commit

Permalink
btrfs: add varargs to btrfs_error
Browse files Browse the repository at this point in the history
 btrfs currently handles most errors with BUG_ON. This patch is a work-in-
 progress but aims to handle most errors other than internal logic
 errors and ENOMEM more gracefully.

 This iteration prevents most crashes but can run into lockups with
 the page lock on occasion when the timing "works out."

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
  • Loading branch information
Jeff Mahoney authored and David Sterba committed Mar 22, 2012
1 parent 3acd395 commit 4da3511
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 9 deletions.
12 changes: 10 additions & 2 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2964,13 +2964,21 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
/* super.c */
int btrfs_parse_options(struct btrfs_root *root, char *options);
int btrfs_sync_fs(struct super_block *sb, int wait);
void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...);
void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
unsigned int line, int errno);
unsigned int line, int errno, const char *fmt, ...);

#define btrfs_std_error(fs_info, errno) \
do { \
if ((errno)) \
__btrfs_std_error((fs_info), __func__, __LINE__, (errno));\
__btrfs_std_error((fs_info), __func__, \
__LINE__, (errno), NULL); \
} while (0)

#define btrfs_error(fs_info, errno, fmt, args...) \
do { \
__btrfs_std_error((fs_info), __func__, __LINE__, \
(errno), fmt, ##args); \
} while (0)

void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function,
Expand Down
63 changes: 56 additions & 7 deletions fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,25 +127,74 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
* invokes the approciate error response.
*/
void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
unsigned int line, int errno)
unsigned int line, int errno, const char *fmt, ...)
{
struct super_block *sb = fs_info->sb;
char nbuf[16];
const char *errstr;
va_list args;
va_start(args, fmt);

/*
* Special case: if the error is EROFS, and we're already
* under MS_RDONLY, then it is safe here.
*/
if (errno == -EROFS && (sb->s_flags & MS_RDONLY))
return;
return;

errstr = btrfs_decode_error(fs_info, errno, nbuf);
printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s\n",
sb->s_id, function, line, errstr);
save_error_info(fs_info);
errstr = btrfs_decode_error(fs_info, errno, nbuf);
if (fmt) {
struct va_format vaf = {
.fmt = fmt,
.va = &args,
};

printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s (%pV)\n",
sb->s_id, function, line, errstr, &vaf);
} else {
printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s\n",
sb->s_id, function, line, errstr);
}

/* Don't go through full error handling during mount */
if (sb->s_flags & MS_BORN) {
save_error_info(fs_info);
btrfs_handle_error(fs_info);
}
va_end(args);
}

btrfs_handle_error(fs_info);
const char *logtypes[] = {
"emergency",
"alert",
"critical",
"error",
"warning",
"notice",
"info",
"debug",
};

void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...)
{
struct super_block *sb = fs_info->sb;
char lvl[4];
struct va_format vaf;
va_list args;
const char *type = logtypes[4];

va_start(args, fmt);

if (fmt[0] == '<' && isdigit(fmt[1]) && fmt[2] == '>') {
strncpy(lvl, fmt, 3);
fmt += 3;
type = logtypes[fmt[1] - '0'];
} else
*lvl = '\0';

vaf.fmt = fmt;
vaf.va = &args;
printk("%sBTRFS %s (device %s): %pV", lvl, type, sb->s_id, &vaf);
}

/*
Expand Down

0 comments on commit 4da3511

Please sign in to comment.