vfs: Implement logging through fs_context

Implement the ability for filesystems to log error, warning and
informational messages through the fs_context.  In the future, these will
be extractable by userspace by reading from an fd created by the fsopen()
syscall.

Error messages are prefixed with "e ", warnings with "w " and informational
messages with "i ".

In the future, inside the kernel, formatted messages will be malloc'd but
unformatted messages will not copied if they're either in the core .rodata
section or in the .rodata section of the filesystem module pinned by
fs_context::fs_type.  The messages will only be good till the fs_type is
released.

Note that the logging object will be shared between duplicated fs_context
structures.  This is so that such as NFS which do a mount within a mount
can get at least some of the errors from the inner mount.

Five logging functions are provided for this:

 (1) void logfc(struct fs_context *fc, const char *fmt, ...);

     This logs a message into the context.  If the buffer is full, the
     earliest message is discarded.

 (2) void errorf(fc, fmt, ...);

     This wraps logfc() to log an error.

 (3) void invalf(fc, fmt, ...);

     This wraps errorf() and returns -EINVAL for convenience.

 (4) void warnf(fc, fmt, ...);

     This wraps logfc() to log a warning.

 (5) void infof(fc, fmt, ...);

     This wraps logfc() to log an informational message.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
David Howells 2018-11-01 23:07:26 +00:00 committed by Al Viro
parent 5fe1890d0e
commit e7582e16a1
2 changed files with 44 additions and 4 deletions

View File

@ -378,6 +378,36 @@ err_fc:
}
EXPORT_SYMBOL(vfs_dup_fs_context);
#ifdef CONFIG_PRINTK
/**
* logfc - Log a message to a filesystem context
* @fc: The filesystem context to log to.
* @fmt: The format of the buffer.
*/
void logfc(struct fs_context *fc, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
switch (fmt[0]) {
case 'w':
vprintk_emit(0, LOGLEVEL_WARNING, NULL, 0, fmt, va);
break;
case 'e':
vprintk_emit(0, LOGLEVEL_ERR, NULL, 0, fmt, va);
break;
default:
vprintk_emit(0, LOGLEVEL_NOTICE, NULL, 0, fmt, va);
break;
}
pr_cont("\n");
va_end(va);
}
EXPORT_SYMBOL(logfc);
#endif
/**
* put_fs_context - Dispose of a superblock configuration context.
* @fc: The context to dispose of.

View File

@ -133,7 +133,17 @@ extern int vfs_get_super(struct fs_context *fc,
int (*fill_super)(struct super_block *sb,
struct fs_context *fc));
#define logfc(FC, FMT, ...) pr_notice(FMT, ## __VA_ARGS__)
extern const struct file_operations fscontext_fops;
#ifdef CONFIG_PRINTK
extern __attribute__((format(printf, 2, 3)))
void logfc(struct fs_context *fc, const char *fmt, ...);
#else
static inline __attribute__((format(printf, 2, 3)))
void logfc(struct fs_context *fc, const char *fmt, ...)
{
}
#endif
/**
* infof - Store supplementary informational message
@ -143,7 +153,7 @@ extern int vfs_get_super(struct fs_context *fc,
* Store the supplementary informational message for the process if the process
* has enabled the facility.
*/
#define infof(fc, fmt, ...) ({ logfc(fc, fmt, ## __VA_ARGS__); })
#define infof(fc, fmt, ...) ({ logfc(fc, "i "fmt, ## __VA_ARGS__); })
/**
* warnf - Store supplementary warning message
@ -153,7 +163,7 @@ extern int vfs_get_super(struct fs_context *fc,
* Store the supplementary warning message for the process if the process has
* enabled the facility.
*/
#define warnf(fc, fmt, ...) ({ logfc(fc, fmt, ## __VA_ARGS__); })
#define warnf(fc, fmt, ...) ({ logfc(fc, "w "fmt, ## __VA_ARGS__); })
/**
* errorf - Store supplementary error message
@ -163,7 +173,7 @@ extern int vfs_get_super(struct fs_context *fc,
* Store the supplementary error message for the process if the process has
* enabled the facility.
*/
#define errorf(fc, fmt, ...) ({ logfc(fc, fmt, ## __VA_ARGS__); })
#define errorf(fc, fmt, ...) ({ logfc(fc, "e "fmt, ## __VA_ARGS__); })
/**
* invalf - Store supplementary invalid argument error message