[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180703170700.9306-7-krisman@collabora.co.uk>
Date: Tue, 3 Jul 2018 13:06:46 -0400
From: Gabriel Krisman Bertazi <krisman@...labora.co.uk>
To: tytso@....edu
Cc: linux-ext4@...r.kernel.org, darrick.wong@...cle.com,
kernel@...labora.com,
Gabriel Krisman Bertazi <krisman@...labora.co.uk>
Subject: [PATCH 06/20] nls: Add support for multiple versions of an encoding
NLS charsets wanting to use this feature can implement the load_create()
hook, which creates a nls_table for that specific encoding version. The
charset code is responsible for freeing the table memory when the module
is removed.
Signed-off-by: Gabriel Krisman Bertazi <krisman@...labora.co.uk>
---
fs/nls/nls_core.c | 45 ++++++++++++++++++++++++++++++++++++++-------
include/linux/nls.h | 5 +++++
2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/fs/nls/nls_core.c b/fs/nls/nls_core.c
index 200a7f8165e6..19a5a66fe423 100644
--- a/fs/nls/nls_core.c
+++ b/fs/nls/nls_core.c
@@ -19,10 +19,27 @@
extern struct nls_charset default_charset;
static struct nls_charset *charsets = &default_charset;
static DEFINE_SPINLOCK(nls_lock);
-static struct nls_table *nls_load_table(struct nls_charset *charset)
+
+static struct nls_table *nls_load_table(struct nls_charset *charset,
+ const char *version)
{
- /* For now, return the default table, which is the first one found. */
- return charset->tables;
+ struct nls_table *tbl;
+
+ if (!charset->load_table) {
+ /* If there is no table_create, only 1 table is
+ * supported and it must have been loaded
+ * statically.
+ */
+ return charset->tables;
+ }
+
+ tbl = charset->load_table(version);
+ if (!tbl) {
+ /* Invalid version */
+ return ERR_PTR(-EINVAL);
+ }
+
+ return tbl;
}
int __register_nls(struct nls_charset *nls, struct module *owner)
@@ -85,21 +102,35 @@ static struct nls_charset *find_nls(const char *charset)
return nls;
}
-struct nls_table *load_nls(char *charset)
+struct nls_table *load_nls_version(const char *charset, const char *version)
{
struct nls_charset *nls_charset;
nls_charset = try_then_request_module(find_nls(charset),
"nls_%s", charset);
- if (!IS_ERR(nls_charset))
+ if (IS_ERR(nls_charset))
+ return ERR_PTR(-EINVAL);
+
+ return nls_load_table(nls_charset, version);
+}
+EXPORT_SYMBOL(load_nls_version);
+
+struct nls_table *load_nls(char *charset)
+{
+ struct nls_table *table = load_nls_version(charset, NULL);
+
+ /* Pre-versioned load_nls() didn't return error pointers. Let's
+ * keep the abi for now to prevent breakage.
+ */
+ if (IS_ERR(table))
return NULL;
- return nls_load_table(nls_charset);
+ return table;
}
void unload_nls(struct nls_table *nls)
{
- if (nls)
+ if (!IS_ERR_OR_NULL(nls))
module_put(nls->charset->owner);
}
diff --git a/include/linux/nls.h b/include/linux/nls.h
index cdc95cd9e5d4..e422bd52afbb 100644
--- a/include/linux/nls.h
+++ b/include/linux/nls.h
@@ -30,6 +30,8 @@ struct nls_ops {
struct nls_table {
const struct nls_charset *charset;
+ unsigned int version;
+
const struct nls_ops *ops;
const unsigned char *charset2lower;
const unsigned char *charset2upper;
@@ -42,6 +44,7 @@ struct nls_charset {
struct module *owner;
struct nls_table *tables;
struct nls_charset *next;
+ struct nls_table *(*load_table)(const char *version);
};
/* this value hold the maximum octet of charset */
@@ -58,6 +61,8 @@ enum utf16_endian {
extern int __register_nls(struct nls_charset *, struct module *);
extern int unregister_nls(struct nls_charset *);
extern struct nls_table *load_nls(char *);
+extern struct nls_table *load_nls_version(const char *charset,
+ const char *version);
extern void unload_nls(struct nls_table *);
extern struct nls_table *load_nls_default(void);
#define register_nls(nls) __register_nls((nls), THIS_MODULE)
--
2.18.0
Powered by blists - more mailing lists