diff options
Diffstat (limited to 'fs/fs_context.c')
-rw-r--r-- | fs/fs_context.c | 79 |
1 files changed, 27 insertions, 52 deletions
diff --git a/fs/fs_context.c b/fs/fs_context.c index 138b5b4d621d..fc9f6ef93b55 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -45,6 +45,7 @@ static const struct constant_table common_set_sb_flag[] = { { "posixacl", SB_POSIXACL }, { "ro", SB_RDONLY }, { "sync", SB_SYNCHRONOUS }, + { }, }; static const struct constant_table common_clear_sb_flag[] = { @@ -53,6 +54,7 @@ static const struct constant_table common_clear_sb_flag[] = { { "nomand", SB_MANDLOCK }, { "rw", SB_RDONLY }, { "silent", SB_SILENT }, + { }, }; static const char *const forbidden_sb_flag[] = { @@ -175,14 +177,15 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key, struct fs_parameter param = { .key = key, - .type = fs_value_is_string, + .type = fs_value_is_flag, .size = v_size, }; - if (v_size > 0) { + if (value) { param.string = kmemdup_nul(value, v_size, GFP_KERNEL); if (!param.string) return -ENOMEM; + param.type = fs_value_is_string; } ret = vfs_parse_fs_param(fc, ¶m); @@ -268,6 +271,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type, fc->fs_type = get_filesystem(fs_type); fc->cred = get_current_cred(); fc->net_ns = get_net(current->nsproxy->net_ns); + fc->log.prefix = fs_type->name; mutex_init(&fc->uapi_mutex); @@ -361,8 +365,8 @@ struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc) get_net(fc->net_ns); get_user_ns(fc->user_ns); get_cred(fc->cred); - if (fc->log) - refcount_inc(&fc->log->usage); + if (fc->log.log) + refcount_inc(&fc->log.log->usage); /* Can't call put until we've called ->dup */ ret = fc->ops->dup(fc, src_fc); @@ -385,64 +389,33 @@ EXPORT_SYMBOL(vfs_dup_fs_context); * @fc: The filesystem context to log to. * @fmt: The format of the buffer. */ -void logfc(struct fs_context *fc, const char *fmt, ...) +void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...) { - static const char store_failure[] = "OOM: Can't store error string"; - struct fc_log *log = fc ? fc->log : NULL; - const char *p; va_list va; - char *q; - u8 freeable; + struct va_format vaf = {.fmt = fmt, .va = &va}; va_start(va, fmt); - if (!strchr(fmt, '%')) { - p = fmt; - goto unformatted_string; - } - if (strcmp(fmt, "%s") == 0) { - p = va_arg(va, const char *); - goto unformatted_string; - } - - q = kvasprintf(GFP_KERNEL, fmt, va); -copied_string: - if (!q) - goto store_failure; - freeable = 1; - goto store_string; - -unformatted_string: - if ((unsigned long)p >= (unsigned long)__start_rodata && - (unsigned long)p < (unsigned long)__end_rodata) - goto const_string; - if (log && within_module_core((unsigned long)p, log->owner)) - goto const_string; - q = kstrdup(p, GFP_KERNEL); - goto copied_string; - -store_failure: - p = store_failure; -const_string: - q = (char *)p; - freeable = 0; -store_string: if (!log) { - switch (fmt[0]) { + switch (level) { case 'w': - printk(KERN_WARNING "%s\n", q + 2); + printk(KERN_WARNING "%s%s%pV\n", prefix ? prefix : "", + prefix ? ": " : "", &vaf); break; case 'e': - printk(KERN_ERR "%s\n", q + 2); + printk(KERN_ERR "%s%s%pV\n", prefix ? prefix : "", + prefix ? ": " : "", &vaf); break; default: - printk(KERN_NOTICE "%s\n", q + 2); + printk(KERN_NOTICE "%s%s%pV\n", prefix ? prefix : "", + prefix ? ": " : "", &vaf); break; } - if (freeable) - kfree(q); } else { unsigned int logsize = ARRAY_SIZE(log->buffer); u8 index; + char *q = kasprintf(GFP_KERNEL, "%c %s%s%pV\n", level, + prefix ? prefix : "", + prefix ? ": " : "", &vaf); index = log->head & (logsize - 1); BUILD_BUG_ON(sizeof(log->head) != sizeof(u8) || @@ -454,9 +427,11 @@ store_string: log->tail++; } - log->buffer[index] = q; - log->need_free &= ~(1 << index); - log->need_free |= freeable << index; + log->buffer[index] = q ? q : "OOM: Can't store error string"; + if (q) + log->need_free |= 1 << index; + else + log->need_free &= ~(1 << index); log->head++; } va_end(va); @@ -468,12 +443,12 @@ EXPORT_SYMBOL(logfc); */ static void put_fc_log(struct fs_context *fc) { - struct fc_log *log = fc->log; + struct fc_log *log = fc->log.log; int i; if (log) { if (refcount_dec_and_test(&log->usage)) { - fc->log = NULL; + fc->log.log = NULL; for (i = 0; i <= 7; i++) if (log->need_free & (1 << i)) kfree(log->buffer[i]); |