* [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations
2026-02-06 19:11 [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Viacheslav Dubeyko
@ 2026-02-06 19:11 ` Viacheslav Dubeyko
2026-02-07 15:52 ` Greg KH
2026-02-06 19:11 ` [RFC PATCH v1 2/4] ml-lib: Implement PoC of Machine Learning (ML) library functionality Viacheslav Dubeyko
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-06 19:11 UTC (permalink / raw)
To: linux-fsdevel, linux-mm, bpf; +Cc: Slava.Dubeyko, slava, linux-kernel
Any kernel subsystem can be extended by one or several ML model(s).
ML model is represented by struct ml_lib_model that contains:
(1) ML model mode, (2) ML model state, (3) pointer on parent kernel
subsystem, (4) parent kernel subsystem state, (5) ML model options,
(6) current dataset, (7) ML model specialized operations,
(8) dataset specialized operations.
Any kernel subsystem can be in several modes that define
how this subsystem interacts with ML model in user-space:
(1) EMERGENCY_MODE - ignore ML model and run default algorithm(s),
(2) LEARNING_MODE - ML model is learning and any recommendations
requires of checking and errors back-propagation,
(3) COLLABORATION_MODE - ML model has good prediction but still
requires correction by default algorithm(s),
(4) RECOMMENDATION_MODE - ML model is capable to substitute
the default algorithm(s).
ML model can be: (1) created, (2) initialized, (3) started,
(4) running, (5) stopped, (6) shutted down.
The API of ML model includes:
(1) ml_model_create() - create ML model and initialize generic field
(2) ml_model_init() - execute specialized logic of ML model initialization
(3) ml_model_re_init() - execute specialized logic of ML model re-init
(4) ml_model_start() - start ML model activity
(5) ml_model_stop() - stop ML model activity
(6) ml_model_destroy() - destroy ML model and free all allocated memory
(7) get_system_state() - get current state of parent kernel subsystem
(8) ml_model_get_dataset() - prepare dataset for extraction by user-space agent
(9) ml_model_discard_dataset() - discard/obsolete dataset by user-space agent
(10) ml_model_preprocess_data() - preprocess data of current dataset
(11) ml_model_publish_data() - notify user-space agent about new dataset
(12) ml_model_preprocess_recommendation() - preprocess ML model recommendations
(13) estimate_system_state() - estimate parent kernel subsystem mode
(14) apply_ml_model_recommendation() - apply ML model recommendations
(15) execute_ml_model_operation() - execute logic following ML model mode
(16) estimate_ml_model_efficiency() - estimate ML model efficiency
(17) ml_model_error_backpropagation() - execute error backpropagation
(18) correct_system_state() - correct parent kernel subsystem mode
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
---
include/linux/ml-lib/ml_lib.h | 425 ++++++++++++++++++++++++++++++++++
1 file changed, 425 insertions(+)
create mode 100644 include/linux/ml-lib/ml_lib.h
diff --git a/include/linux/ml-lib/ml_lib.h b/include/linux/ml-lib/ml_lib.h
new file mode 100644
index 000000000000..001e781e0bf1
--- /dev/null
+++ b/include/linux/ml-lib/ml_lib.h
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Machine Learning (ML) library
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#ifndef _LINUX_ML_LIB_H
+#define _LINUX_ML_LIB_H
+
+/*
+ * Any kernel subsystem can be in several modes
+ * that define how this subsystem interacts with
+ * ML model in user-space:
+ * (1) EMERGENCY_MODE - ignore ML model and run default algorithm(s).
+ * (2) LEARNING_MODE - ML model is learning and any recommendations
+ * requires of checking and errors back-propagation.
+ * (3) COLLABORATION_MODE - ML model has good prediction but still
+ * requires correction by default algorithm(s).
+ * (4) RECOMMENDATION_MODE - ML model is capable to substitute
+ * the default algorithm(s).
+ */
+enum ml_lib_system_mode {
+ ML_LIB_UNKNOWN_MODE,
+ ML_LIB_EMERGENCY_MODE,
+ ML_LIB_LEARNING_MODE,
+ ML_LIB_COLLABORATION_MODE,
+ ML_LIB_RECOMMENDATION_MODE,
+ ML_LIB_MODE_MAX
+};
+
+enum {
+ ML_LIB_UNKNOWN_MODEL_STATE,
+ ML_LIB_MODEL_CREATED,
+ ML_LIB_MODEL_INITIALIZED,
+ ML_LIB_MODEL_STARTED,
+ ML_LIB_MODEL_RUNNING,
+ ML_LIB_MODEL_STOPPED,
+ ML_LIB_MODEL_SHUTTING_DOWN,
+ ML_LIB_MODEL_STATE_MAX
+};
+
+struct ml_lib_model;
+
+#define ML_LIB_SLEEP_TIMEOUT_DEFAULT (10)
+
+/*
+ * struct ml_lib_model_options - ML model global options
+ * @sleep_timeout: main thread's sleep timeout
+ *
+ * These options define behavior of ML model.
+ * The options can be defined during init() or re-init() call.
+ */
+struct ml_lib_model_options {
+ u32 sleep_timeout;
+};
+
+/*
+ * struct ml_lib_model_run_config - ML model run config
+ * @sleep_timeout: main thread's sleep timeout
+ *
+ * The run config is used for correction of ML model options
+ * by means of start/stop methods pair.
+ */
+struct ml_lib_model_run_config {
+ u32 sleep_timeout;
+};
+
+/*
+ * struct ml_lib_subsystem - kernel subsystem object
+ * @type: object type
+ * @size: number of bytes in allocated object
+ * @private: private data of subsystem
+ */
+struct ml_lib_subsystem {
+ atomic_t type;
+ size_t size;
+
+ void *private;
+};
+
+enum {
+ ML_LIB_UNKNOWN_SUBSYSTEM_TYPE,
+ ML_LIB_GENERIC_SUBSYSTEM,
+ ML_LIB_SPECIALIZED_SUBSYSTEM,
+ ML_LIB_SUBSYSTEM_TYPE_MAX
+};
+
+/*
+ * struct ml_lib_subsystem_state - shared kernel subsystem state
+ * @state: object state
+ * @size: number of bytes in allocated object
+ */
+struct ml_lib_subsystem_state {
+ atomic_t state;
+ size_t size;
+};
+
+enum {
+ ML_LIB_UNKNOWN_SUBSYSTEM_STATE,
+ ML_LIB_SUBSYSTEM_CREATED,
+ ML_LIB_SUBSYSTEM_INITIALIZED,
+ ML_LIB_SUBSYSTEM_STARTED,
+ ML_LIB_SUBSYSTEM_RUNNING,
+ ML_LIB_SUBSYSTEM_SHUTTING_DOWN,
+ ML_LIB_SUBSYSTEM_STOPPED,
+ ML_LIB_SUBSYSTEM_STATE_MAX
+};
+
+struct ml_lib_subsystem_state_operations {
+ void *(*allocate)(size_t size, gfp_t gfp);
+ void (*free)(struct ml_lib_subsystem_state *state);
+ int (*init)(struct ml_lib_subsystem_state *state);
+ int (*destroy)(struct ml_lib_subsystem_state *state);
+ int (*check_state)(struct ml_lib_subsystem_state *state);
+ struct ml_lib_subsystem_state *
+ (*snapshot_state)(struct ml_lib_subsystem *object);
+ int (*estimate_system_state)(struct ml_lib_model *ml_model);
+ int (*correct_system_state)(struct ml_lib_model *ml_model);
+};
+
+/*
+ * struct ml_lib_dataset - exported subsystem's dataset
+ * @type: object type
+ * @state: object state
+ * @allocated_size: number of bytes in allocated object
+ * @portion_offset: portion offset in the data stream
+ * @portion_size: extracted portion size
+ */
+struct ml_lib_dataset {
+ atomic_t type;
+ atomic_t state;
+ size_t allocated_size;
+
+ u64 portion_offset;
+ u32 portion_size;
+};
+
+enum {
+ ML_LIB_UNKNOWN_DATASET_TYPE,
+ ML_LIB_EMPTY_DATASET,
+ ML_LIB_VALUE_DATASET,
+ ML_LIB_STRUCTURE_DATASET,
+ ML_LIB_MEMORY_STREAM_DATASET,
+ ML_LIB_DATASET_TYPE_MAX
+};
+
+enum {
+ ML_LIB_UNKNOWN_DATASET_STATE,
+ ML_LIB_DATASET_ALLOCATED,
+ ML_LIB_DATASET_CLEAN,
+ ML_LIB_DATASET_EXTRACTED_PARTIALLY,
+ ML_LIB_DATASET_EXTRACTED_COMPLETELY,
+ ML_LIB_DATASET_OBSOLETE,
+ ML_LIB_DATASET_EXTRACTION_FAILURE,
+ ML_LIB_DATASET_CORRUPTED,
+ ML_LIB_DATASET_STATE_MAX
+};
+
+struct ml_lib_dataset_operations {
+ void *(*allocate)(size_t size, gfp_t gfp);
+ void (*free)(struct ml_lib_dataset *dataset);
+ int (*init)(struct ml_lib_dataset *dataset);
+ int (*destroy)(struct ml_lib_dataset *dataset);
+ int (*extract)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+ int (*preprocess_data)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+ int (*publish_data)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+};
+
+/*
+ * struct ml_lib_request_config - dataset operation configuration
+ * @type: object type
+ * @state: object state
+ * @size: number of bytes in allocated object
+ */
+struct ml_lib_request_config {
+ atomic_t type;
+ atomic_t state;
+ size_t size;
+};
+
+enum {
+ ML_LIB_UNKNOWN_REQUEST_CONFIG_TYPE,
+ ML_LIB_EMPTY_REQUEST_CONFIG,
+ ML_LIB_REQUEST_CONFIG_TYPE_MAX
+};
+
+enum {
+ ML_LIB_UNKNOWN_REQUEST_CONFIG_STATE,
+ ML_LIB_REQUEST_CONFIG_ALLOCATED,
+ ML_LIB_REQUEST_CONFIG_INITIALIZED,
+ ML_LIB_REQUEST_CONFIG_STATE_MAX
+};
+
+struct ml_lib_request_config_operations {
+ void *(*allocate)(size_t size, gfp_t gfp);
+ void (*free)(struct ml_lib_request_config *config);
+ int (*init)(struct ml_lib_request_config *config);
+ int (*destroy)(struct ml_lib_request_config *config);
+};
+
+struct ml_lib_user_space_request {
+};
+
+struct ml_lib_user_space_request_operations {
+ int (*operation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_request *request);
+};
+
+struct ml_lib_user_space_notification {
+};
+
+struct ml_lib_user_space_notification_operations {
+ int (*operation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_notification *notify);
+};
+
+struct ml_lib_user_space_recommendation {
+};
+
+struct ml_lib_user_space_recommendation_operations {
+ int (*operation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+};
+
+struct ml_lib_backpropagation_feedback {
+};
+
+struct ml_lib_backpropagation_operations {
+ int (*operation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+};
+
+/*
+ * struct ml_lib_model_operations - ML model operations
+ * @create: specialized method of ML model creation
+ * @init: specialized method of ML model initialization
+ * @re_init: specialized method of ML model re-initialization
+ * @start: specialized method of ML model start
+ * @stop: specialized method of ML model stop
+ * @destroy: specialized method of ML model destroy
+ * @get_system_state: specialized method of getting subsystem state
+ * @get_dataset: specialized method of getting a dataset
+ * @preprocess_data: specialized method of data preprocessing
+ * @publish_data: specialized method of sharing data with user-space
+ * @preprocess_recommendation: specialized method of preprocess recomendations
+ * @estimate_system_state: specialized method of system state estimation
+ * @apply_recommendation: specialized method of recommendations applying
+ * @execute_operation: specialized method of operation execution
+ * @estimate_efficiency: specialized method of operation efficiency estimation
+ * @error_backpropagation: specialized method of error backpropagation
+ * @correct_system_state: specialized method of subsystem state correction
+ */
+struct ml_lib_model_operations {
+ int (*create)(struct ml_lib_model *ml_model);
+ int (*init)(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+ int (*re_init)(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+ int (*start)(struct ml_lib_model *ml_model,
+ struct ml_lib_model_run_config *config);
+ int (*stop)(struct ml_lib_model *ml_model);
+ void (*destroy)(struct ml_lib_model *ml_model);
+ struct ml_lib_subsystem_state *
+ (*get_system_state)(struct ml_lib_model *ml_model);
+ int (*get_dataset)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+ int (*preprocess_data)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+ int (*publish_data)(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset,
+ struct ml_lib_user_space_notification *notify);
+ int (*preprocess_recommendation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+ int (*estimate_system_state)(struct ml_lib_model *ml_model);
+ int (*apply_recommendation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+ int (*execute_operation)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+ int (*estimate_efficiency)(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+ int (*error_backpropagation)(struct ml_lib_model *ml_model,
+ struct ml_lib_backpropagation_feedback *feedback,
+ struct ml_lib_user_space_notification *notify);
+ int (*correct_system_state)(struct ml_lib_model *ml_model);
+};
+
+/*
+ * struct ml_lib_model - ML model declaration
+ * @mode: ML model mode (enum ml_lib_system_mode)
+ * @state: ML model state
+ * @subsystem_name: name of susbsystem
+ * @model_name: name of the ML model
+ * @parent: parent kernel subsystem
+ * @parent_state: parent kernel subsystem's state
+ * @options: ML model options
+ * @model_ops: ML model specialized operations
+ * @system_state_ops: subsystem state specialized operations
+ * @dataset_ops: dataset specialized operations
+ * @request_config_ops: specialized dataset configuration operations
+ * @kobj: /sys/<subsystem>/<ml_model>/ ML model object
+ * @kobj_unregister: completion state for <ml_model> kernel object
+ */
+struct ml_lib_model {
+ atomic_t mode;
+ atomic_t state;
+ const char *subsystem_name;
+ const char *model_name;
+
+ struct ml_lib_subsystem *parent;
+
+ spinlock_t parent_state_lock;
+ struct ml_lib_subsystem_state * __rcu parent_state;
+
+ spinlock_t options_lock;
+ struct ml_lib_model_options * __rcu options;
+
+ spinlock_t dataset_lock;
+ struct ml_lib_dataset * __rcu dataset;
+
+ struct ml_lib_model_operations *model_ops;
+ struct ml_lib_subsystem_state_operations *system_state_ops;
+ struct ml_lib_dataset_operations *dataset_ops;
+ struct ml_lib_request_config_operations *request_config_ops;
+
+ /* /sys/<subsystem>/<ml_model>/ */
+ struct kobject kobj;
+ struct completion kobj_unregister;
+};
+
+/* ML library API */
+
+void *allocate_ml_model(size_t size, gfp_t gfp);
+void free_ml_model(struct ml_lib_model *ml_model);
+void *allocate_subsystem_object(size_t size, gfp_t gfp);
+void free_subsystem_object(struct ml_lib_subsystem *object);
+void *allocate_ml_model_options(size_t size, gfp_t gfp);
+void free_ml_model_options(struct ml_lib_model_options *options);
+void *allocate_subsystem_state(size_t size, gfp_t gfp);
+void free_subsystem_state(struct ml_lib_subsystem_state *state);
+void *allocate_dataset(size_t size, gfp_t gfp);
+void free_dataset(struct ml_lib_dataset *dataset);
+void *allocate_request_config(size_t size, gfp_t gfp);
+void free_request_config(struct ml_lib_request_config *config);
+
+int ml_model_create(struct ml_lib_model *ml_model,
+ const char *subsystem_name,
+ const char *model_name,
+ struct kobject *subsystem_kobj);
+int ml_model_init(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+int ml_model_re_init(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+int ml_model_start(struct ml_lib_model *ml_model,
+ struct ml_lib_model_run_config *config);
+int ml_model_stop(struct ml_lib_model *ml_model);
+void ml_model_destroy(struct ml_lib_model *ml_model);
+struct ml_lib_subsystem_state *get_system_state(struct ml_lib_model *ml_model);
+int ml_model_get_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_request_config *config,
+ struct ml_lib_user_space_request *request);
+int ml_model_discard_dataset(struct ml_lib_model *ml_model);
+int ml_model_preprocess_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+int ml_model_publish_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset,
+ struct ml_lib_user_space_notification *notify);
+int ml_model_preprocess_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+int estimate_system_state(struct ml_lib_model *ml_model);
+int apply_ml_model_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+int execute_ml_model_operation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+int estimate_ml_model_efficiency(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+int ml_model_error_backpropagation(struct ml_lib_model *ml_model,
+ struct ml_lib_backpropagation_feedback *feedback,
+ struct ml_lib_user_space_notification *notify);
+int correct_system_state(struct ml_lib_model *ml_model);
+
+/* Generic implementation of ML model's methods */
+
+int generic_create_ml_model(struct ml_lib_model *ml_model);
+int generic_init_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+int generic_re_init_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options);
+int generic_start_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_run_config *config);
+int generic_stop_ml_model(struct ml_lib_model *ml_model);
+void generic_destroy_ml_model(struct ml_lib_model *ml_model);
+struct ml_lib_subsystem_state *
+generic_get_system_state(struct ml_lib_model *ml_model);
+int generic_get_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+int generic_preprocess_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+int generic_publish_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset,
+ struct ml_lib_user_space_notification *notify);
+int generic_preprocess_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+int generic_estimate_system_state(struct ml_lib_model *ml_model);
+int generic_apply_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint);
+int generic_execute_operation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+int generic_estimate_efficiency(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request);
+int generic_error_backpropagation(struct ml_lib_model *ml_model,
+ struct ml_lib_backpropagation_feedback *feedback,
+ struct ml_lib_user_space_notification *notify);
+int generic_correct_system_state(struct ml_lib_model *ml_model);
+
+#endif /* _LINUX_ML_LIB_H */
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations
2026-02-06 19:11 ` [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations Viacheslav Dubeyko
@ 2026-02-07 15:52 ` Greg KH
2026-02-09 20:48 ` Viacheslav Dubeyko
0 siblings, 1 reply; 14+ messages in thread
From: Greg KH @ 2026-02-07 15:52 UTC (permalink / raw)
To: Viacheslav Dubeyko
Cc: linux-fsdevel, linux-mm, bpf, Slava.Dubeyko, linux-kernel
On Fri, Feb 06, 2026 at 11:11:33AM -0800, Viacheslav Dubeyko wrote:
> + * @kobj: /sys/<subsystem>/<ml_model>/ ML model object
> + * @kobj_unregister: completion state for <ml_model> kernel object
> + */
> +struct ml_lib_model {
> + atomic_t mode;
> + atomic_t state;
> + const char *subsystem_name;
> + const char *model_name;
> +
> + struct ml_lib_subsystem *parent;
> +
> + spinlock_t parent_state_lock;
> + struct ml_lib_subsystem_state * __rcu parent_state;
> +
> + spinlock_t options_lock;
> + struct ml_lib_model_options * __rcu options;
> +
> + spinlock_t dataset_lock;
> + struct ml_lib_dataset * __rcu dataset;
> +
> + struct ml_lib_model_operations *model_ops;
> + struct ml_lib_subsystem_state_operations *system_state_ops;
> + struct ml_lib_dataset_operations *dataset_ops;
> + struct ml_lib_request_config_operations *request_config_ops;
> +
> + /* /sys/<subsystem>/<ml_model>/ */
> + struct kobject kobj;
> + struct completion kobj_unregister;
> +};
Do NOT abuse sysfs for something like this. Please make your own
filesystem or char device or something else, but this is not what sysfs
is for at all, sorry.
greg k-h
^ permalink raw reply [flat|nested] 14+ messages in thread* RE: [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations
2026-02-07 15:52 ` Greg KH
@ 2026-02-09 20:48 ` Viacheslav Dubeyko
2026-02-10 5:20 ` gregkh
0 siblings, 1 reply; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-09 20:48 UTC (permalink / raw)
To: gregkh, slava; +Cc: linux-mm, linux-fsdevel, linux-kernel, bpf
On Sat, 2026-02-07 at 16:52 +0100, Greg KH wrote:
> On Fri, Feb 06, 2026 at 11:11:33AM -0800, Viacheslav Dubeyko wrote:
> > + * @kobj: /sys/<subsystem>/<ml_model>/ ML model object
> > + * @kobj_unregister: completion state for <ml_model> kernel object
> > + */
> > +struct ml_lib_model {
> > + atomic_t mode;
> > + atomic_t state;
> > + const char *subsystem_name;
> > + const char *model_name;
> > +
> > + struct ml_lib_subsystem *parent;
> > +
> > + spinlock_t parent_state_lock;
> > + struct ml_lib_subsystem_state * __rcu parent_state;
> > +
> > + spinlock_t options_lock;
> > + struct ml_lib_model_options * __rcu options;
> > +
> > + spinlock_t dataset_lock;
> > + struct ml_lib_dataset * __rcu dataset;
> > +
> > + struct ml_lib_model_operations *model_ops;
> > + struct ml_lib_subsystem_state_operations *system_state_ops;
> > + struct ml_lib_dataset_operations *dataset_ops;
> > + struct ml_lib_request_config_operations *request_config_ops;
> > +
> > + /* /sys/<subsystem>/<ml_model>/ */
> > + struct kobject kobj;
> > + struct completion kobj_unregister;
> > +};
>
> Do NOT abuse sysfs for something like this. Please make your own
> filesystem or char device or something else, but this is not what sysfs
> is for at all, sorry.
>
Currently, sysfs entry is used for sending commands (start, stop,
prepare_dataset, discard_dataset) from user-space on the kernel-space side. And
the intention of using sysfs entries is the export information about kernel
subsystem and exchanging by commands and notifications between user-space and
kernel-space sides. Do you mean that it is wrong using of sysfs? Have I
misunderstood your point?
Thanks,
Slava.
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations
2026-02-09 20:48 ` Viacheslav Dubeyko
@ 2026-02-10 5:20 ` gregkh
2026-02-10 22:44 ` Viacheslav Dubeyko
0 siblings, 1 reply; 14+ messages in thread
From: gregkh @ 2026-02-10 5:20 UTC (permalink / raw)
To: Viacheslav Dubeyko; +Cc: slava, linux-mm, linux-fsdevel, linux-kernel, bpf
On Mon, Feb 09, 2026 at 08:48:17PM +0000, Viacheslav Dubeyko wrote:
> On Sat, 2026-02-07 at 16:52 +0100, Greg KH wrote:
> > On Fri, Feb 06, 2026 at 11:11:33AM -0800, Viacheslav Dubeyko wrote:
> > > + * @kobj: /sys/<subsystem>/<ml_model>/ ML model object
> > > + * @kobj_unregister: completion state for <ml_model> kernel object
> > > + */
> > > +struct ml_lib_model {
> > > + atomic_t mode;
> > > + atomic_t state;
> > > + const char *subsystem_name;
> > > + const char *model_name;
> > > +
> > > + struct ml_lib_subsystem *parent;
> > > +
> > > + spinlock_t parent_state_lock;
> > > + struct ml_lib_subsystem_state * __rcu parent_state;
> > > +
> > > + spinlock_t options_lock;
> > > + struct ml_lib_model_options * __rcu options;
> > > +
> > > + spinlock_t dataset_lock;
> > > + struct ml_lib_dataset * __rcu dataset;
> > > +
> > > + struct ml_lib_model_operations *model_ops;
> > > + struct ml_lib_subsystem_state_operations *system_state_ops;
> > > + struct ml_lib_dataset_operations *dataset_ops;
> > > + struct ml_lib_request_config_operations *request_config_ops;
> > > +
> > > + /* /sys/<subsystem>/<ml_model>/ */
> > > + struct kobject kobj;
> > > + struct completion kobj_unregister;
> > > +};
> >
> > Do NOT abuse sysfs for something like this. Please make your own
> > filesystem or char device or something else, but this is not what sysfs
> > is for at all, sorry.
> >
>
> Currently, sysfs entry is used for sending commands (start, stop,
> prepare_dataset, discard_dataset) from user-space on the kernel-space side. And
> the intention of using sysfs entries is the export information about kernel
> subsystem and exchanging by commands and notifications between user-space and
> kernel-space sides. Do you mean that it is wrong using of sysfs? Have I
> misunderstood your point?
Yes, this is NOT the correct use of sysfs, do NOT use it for an api like
this at all. Use the correct ones instead.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 14+ messages in thread* RE: [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations
2026-02-10 5:20 ` gregkh
@ 2026-02-10 22:44 ` Viacheslav Dubeyko
0 siblings, 0 replies; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-10 22:44 UTC (permalink / raw)
To: gregkh; +Cc: linux-mm, slava, linux-fsdevel, linux-kernel, bpf
On Tue, 2026-02-10 at 06:20 +0100, gregkh@linuxfoundation.org wrote:
> On Mon, Feb 09, 2026 at 08:48:17PM +0000, Viacheslav Dubeyko wrote:
> > On Sat, 2026-02-07 at 16:52 +0100, Greg KH wrote:
> > > On Fri, Feb 06, 2026 at 11:11:33AM -0800, Viacheslav Dubeyko wrote:
> > > > + * @kobj: /sys/<subsystem>/<ml_model>/ ML model object
> > > > + * @kobj_unregister: completion state for <ml_model> kernel object
> > > > + */
> > > > +struct ml_lib_model {
> > > > + atomic_t mode;
> > > > + atomic_t state;
> > > > + const char *subsystem_name;
> > > > + const char *model_name;
> > > > +
> > > > + struct ml_lib_subsystem *parent;
> > > > +
> > > > + spinlock_t parent_state_lock;
> > > > + struct ml_lib_subsystem_state * __rcu parent_state;
> > > > +
> > > > + spinlock_t options_lock;
> > > > + struct ml_lib_model_options * __rcu options;
> > > > +
> > > > + spinlock_t dataset_lock;
> > > > + struct ml_lib_dataset * __rcu dataset;
> > > > +
> > > > + struct ml_lib_model_operations *model_ops;
> > > > + struct ml_lib_subsystem_state_operations *system_state_ops;
> > > > + struct ml_lib_dataset_operations *dataset_ops;
> > > > + struct ml_lib_request_config_operations *request_config_ops;
> > > > +
> > > > + /* /sys/<subsystem>/<ml_model>/ */
> > > > + struct kobject kobj;
> > > > + struct completion kobj_unregister;
> > > > +};
> > >
> > > Do NOT abuse sysfs for something like this. Please make your own
> > > filesystem or char device or something else, but this is not what sysfs
> > > is for at all, sorry.
> > >
> >
> > Currently, sysfs entry is used for sending commands (start, stop,
> > prepare_dataset, discard_dataset) from user-space on the kernel-space side. And
> > the intention of using sysfs entries is the export information about kernel
> > subsystem and exchanging by commands and notifications between user-space and
> > kernel-space sides. Do you mean that it is wrong using of sysfs? Have I
> > misunderstood your point?
>
> Yes, this is NOT the correct use of sysfs, do NOT use it for an api like
> this at all. Use the correct ones instead.
>
>
So, to summarize your recommendations:
(1) Do not use sysfs;
(2) Do not use character device but misc device instead;
(3) Implement specialized file system;
(4) eBPF?
Would you like to share any other recommendations?
Thanks,
Slava.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v1 2/4] ml-lib: Implement PoC of Machine Learning (ML) library functionality
2026-02-06 19:11 [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Viacheslav Dubeyko
2026-02-06 19:11 ` [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations Viacheslav Dubeyko
@ 2026-02-06 19:11 ` Viacheslav Dubeyko
2026-02-06 19:11 ` [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver Viacheslav Dubeyko
` (2 subsequent siblings)
4 siblings, 0 replies; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-06 19:11 UTC (permalink / raw)
To: linux-fsdevel, linux-mm, bpf; +Cc: Slava.Dubeyko, slava, linux-kernel
ML model can be represented by process/thread running in user-space.
Particular kernel subsystem needs to implement ML model proxy
on kernel-space side. The process of loading kernel subsystem
creates and intializes the ML model proxy, create sysfs entries,
and character device, for example. The sysfs entries and character
device create the mechanism of interaction and collaboration of
kernel subsystem and ML model in user-space.
The simplest model of collaboration could include such steps:
(1) user-space process/thread (ML model) sends START command
to kernel subsystem through sysfs control entry;
(2) user-space process/thread (ML model) requests to prepare
a dataset by means of PREPARE_DATASET command through
sysfs control entry;
(3) user-space process/thread (ML model) extracts the dataset
by means of reading data from character device;
(4) dataset can be marked as obsolete after extraction
by means of DISCARD_DATASET command through sysfs control entry
and new dataset can be requested and extracted;
(5) extracted data can be used as training data by ML model
on user-space side;
(6) ML model can execute the inference after some number of
training cycles and to elaborate some recommendations or
optimized logic for kernel subsystem;
(7) ML model's recommendations can be written into character
device, for example, by user-space process/thread and
kernel subsystem can use this recommendations for
optimization or changing the logic;
(8) based on kernel subsystem's mode, recommendations can be
completely ignored, partially applied, tested, or
used instead of default configuration/logic;
(9) every time efficiency of applied recommendations or
logic needs to be estimated;
(10) if ML model recommendations degrade efficiency of kernel
subsystem, then error backpropagation needs to be used
for ML model correction on user-space side.
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
---
lib/Kconfig | 6 +
lib/Makefile | 2 +
lib/ml-lib/Kconfig | 18 +
lib/ml-lib/Makefile | 7 +
lib/ml-lib/ml_lib_main.c | 758 +++++++++++++++++++++++++++++++++++++++
lib/ml-lib/sysfs.c | 187 ++++++++++
lib/ml-lib/sysfs.h | 17 +
7 files changed, 995 insertions(+)
create mode 100644 lib/ml-lib/Kconfig
create mode 100644 lib/ml-lib/Makefile
create mode 100644 lib/ml-lib/ml_lib_main.c
create mode 100644 lib/ml-lib/sysfs.c
create mode 100644 lib/ml-lib/sysfs.h
diff --git a/lib/Kconfig b/lib/Kconfig
index 2923924bea78..2d56977c0638 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -604,6 +604,12 @@ config LWQ_TEST
help
Run boot-time test of light-weight queuing.
+#
+# Machine Learning (ML) library configuration
+#
+
+source "lib/ml-lib/Kconfig"
+
endmenu
config GENERIC_IOREMAP
diff --git a/lib/Makefile b/lib/Makefile
index aaf677cf4527..154e7fd220ab 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -332,3 +332,5 @@ obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
obj-$(CONFIG_FIRMWARE_TABLE) += fw_table.o
subdir-$(CONFIG_FORTIFY_SOURCE) += test_fortify
+
+obj-$(CONFIG_ML_LIB) += ml-lib/
diff --git a/lib/ml-lib/Kconfig b/lib/ml-lib/Kconfig
new file mode 100644
index 000000000000..d2f2ea40a833
--- /dev/null
+++ b/lib/ml-lib/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+#
+# Machine Learning (ML) library configuration
+#
+
+config ML_LIB
+ tristate "ML library support"
+ help
+ Machine Learning (ML) library has goal to provide
+ the interaction and communication of ML models in
+ user-space with kernel subsystems. It implements
+ the basic code primitives that builds the way of
+ ML models integration into Linux kernel functionality.
+
+ If unsure, say N.
+
+source "lib/ml-lib/test_driver/Kconfig"
diff --git a/lib/ml-lib/Makefile b/lib/ml-lib/Makefile
new file mode 100644
index 000000000000..b1103ab3e1c8
--- /dev/null
+++ b/lib/ml-lib/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_ML_LIB) += ml_lib.o
+
+ml_lib-y := sysfs.o ml_lib_main.o
+
+obj-$(CONFIG_ML_LIB_TEST_DRIVER) += test_driver/
diff --git a/lib/ml-lib/ml_lib_main.c b/lib/ml-lib/ml_lib_main.c
new file mode 100644
index 000000000000..ef336d6a83fb
--- /dev/null
+++ b/lib/ml-lib/ml_lib_main.c
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Machine Learning (ML) library
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/ml-lib/ml_lib.h>
+
+#include "sysfs.h"
+
+#define UNKNOWN_SUBSYSTEM_NAME "unknown_subsystem"
+#define UNKNOWN_ML_MODEL_NAME "unknown_model"
+
+/*
+ * default_ml_model_ops - default ML model operations
+ */
+struct ml_lib_model_operations default_ml_model_ops = {
+ .create = generic_create_ml_model,
+ .init = generic_init_ml_model,
+ .re_init = generic_re_init_ml_model,
+ .start = generic_start_ml_model,
+ .stop = generic_stop_ml_model,
+ .destroy = generic_destroy_ml_model,
+ .get_system_state = generic_get_system_state,
+ .get_dataset = generic_get_dataset,
+ .preprocess_data = generic_preprocess_data,
+ .publish_data = generic_publish_data,
+ .preprocess_recommendation = generic_preprocess_recommendation,
+ .estimate_system_state = generic_estimate_system_state,
+ .apply_recommendation = generic_apply_recommendation,
+ .execute_operation = generic_execute_operation,
+ .estimate_efficiency = generic_estimate_efficiency,
+ .error_backpropagation = generic_error_backpropagation,
+ .correct_system_state = generic_correct_system_state,
+};
+
+/******************************************************************************
+ * ML library API *
+ ******************************************************************************/
+
+void *allocate_ml_model(size_t size, gfp_t gfp)
+{
+ struct ml_lib_model *ml_model;
+
+ if (size < sizeof(struct ml_lib_model))
+ return ERR_PTR(-EINVAL);
+
+ ml_model = kzalloc(size, gfp);
+ if (unlikely(!ml_model))
+ return ERR_PTR(-ENOMEM);
+
+ atomic_set(&ml_model->mode, ML_LIB_UNKNOWN_MODE);
+ atomic_set(&ml_model->state, ML_LIB_UNKNOWN_MODEL_STATE);
+ ml_model->model_ops = &default_ml_model_ops;
+
+ return (void *)ml_model;
+}
+EXPORT_SYMBOL(allocate_ml_model);
+
+void free_ml_model(struct ml_lib_model *ml_model)
+{
+ if (!ml_model)
+ return;
+
+ free_subsystem_object(ml_model->parent);
+ kfree(ml_model);
+}
+EXPORT_SYMBOL(free_ml_model);
+
+void *allocate_subsystem_object(size_t size, gfp_t gfp)
+{
+ struct ml_lib_subsystem *subsystem;
+
+ if (size < sizeof(struct ml_lib_subsystem))
+ return ERR_PTR(-EINVAL);
+
+ subsystem = kzalloc(size, gfp);
+ if (unlikely(!subsystem))
+ return ERR_PTR(-ENOMEM);
+
+ subsystem->size = size;
+ atomic_set(&subsystem->type, ML_LIB_UNKNOWN_SUBSYSTEM_TYPE);
+
+ return (void *)subsystem;
+}
+EXPORT_SYMBOL(allocate_subsystem_object);
+
+void free_subsystem_object(struct ml_lib_subsystem *object)
+{
+ if (!object)
+ return;
+
+ kfree(object);
+}
+EXPORT_SYMBOL(free_subsystem_object);
+
+void *allocate_ml_model_options(size_t size, gfp_t gfp)
+{
+ struct ml_lib_model_options *options;
+
+ if (size < sizeof(struct ml_lib_model_options))
+ return ERR_PTR(-EINVAL);
+
+ options = kzalloc(size, gfp);
+ if (unlikely(!options))
+ return ERR_PTR(-ENOMEM);
+
+ options->sleep_timeout = U32_MAX;
+
+ return (void *)options;
+}
+EXPORT_SYMBOL(allocate_ml_model_options);
+
+void free_ml_model_options(struct ml_lib_model_options *options)
+{
+ if (!options)
+ return;
+
+ kfree(options);
+}
+EXPORT_SYMBOL(free_ml_model_options);
+
+void *allocate_subsystem_state(size_t size, gfp_t gfp)
+{
+ return NULL;
+}
+EXPORT_SYMBOL(allocate_subsystem_state);
+
+void free_subsystem_state(struct ml_lib_subsystem_state *state)
+{
+}
+EXPORT_SYMBOL(free_subsystem_state);
+
+void *allocate_dataset(size_t size, gfp_t gfp)
+{
+ struct ml_lib_dataset *dataset;
+
+ if (size < sizeof(struct ml_lib_dataset))
+ return ERR_PTR(-EINVAL);
+
+ dataset = kzalloc(size, gfp);
+ if (unlikely(!dataset))
+ return ERR_PTR(-ENOMEM);
+
+ atomic_set(&dataset->type, ML_LIB_UNKNOWN_DATASET_TYPE);
+ atomic_set(&dataset->state, ML_LIB_UNKNOWN_DATASET_STATE);
+
+ return (void *)dataset;
+}
+EXPORT_SYMBOL(allocate_dataset);
+
+void free_dataset(struct ml_lib_dataset *dataset)
+{
+ if (!dataset)
+ return;
+
+ kfree(dataset);
+}
+EXPORT_SYMBOL(free_dataset);
+
+void *allocate_request_config(size_t size, gfp_t gfp)
+{
+ return NULL;
+}
+EXPORT_SYMBOL(allocate_request_config);
+
+void free_request_config(struct ml_lib_request_config *config)
+{
+}
+EXPORT_SYMBOL(free_request_config);
+
+int ml_model_create(struct ml_lib_model *ml_model,
+ const char *subsystem_name,
+ const char *model_name,
+ struct kobject *subsystem_kobj)
+{
+ struct kobject *parent = NULL;
+ size_t size;
+ int err = 0;
+
+ if (!ml_model)
+ return -EINVAL;
+
+ if (!subsystem_name)
+ ml_model->subsystem_name = UNKNOWN_SUBSYSTEM_NAME;
+ else
+ ml_model->subsystem_name = subsystem_name;
+
+ if (!model_name)
+ ml_model->model_name = UNKNOWN_ML_MODEL_NAME;
+ else
+ ml_model->model_name = model_name;
+
+ if (!subsystem_kobj)
+ parent = kernel_kobj;
+ else
+ parent = subsystem_kobj;
+
+ spin_lock_init(&ml_model->parent_state_lock);
+ spin_lock_init(&ml_model->options_lock);
+ spin_lock_init(&ml_model->dataset_lock);
+
+ err = ml_model_create_sysfs_group(ml_model, parent);
+ if (err) {
+ pr_err("ml_lib: failed to create sysfs group: err %d\n", err);
+ goto finish_model_create;
+ }
+
+ if (!ml_model->model_ops || !ml_model->model_ops->create) {
+ size = sizeof(struct ml_lib_subsystem);
+
+ ml_model->parent = allocate_subsystem_object(size, GFP_KERNEL);
+ if (unlikely(!ml_model->parent)) {
+ err = -ENOMEM;
+ goto remove_sysfs_group;
+ }
+
+ atomic_set(&ml_model->parent->type, ML_LIB_GENERIC_SUBSYSTEM);
+ } else {
+ err = ml_model->model_ops->create(ml_model);
+ if (unlikely(err)) {
+ pr_err("ml_lib: failed to create ML model: err %d\n",
+ err);
+ goto remove_sysfs_group;
+ }
+ }
+
+ atomic_set(&ml_model->state, ML_LIB_MODEL_CREATED);
+
+ return 0;
+
+remove_sysfs_group:
+ ml_model_delete_sysfs_group(ml_model);
+
+finish_model_create:
+ return err;
+}
+EXPORT_SYMBOL(ml_model_create);
+
+int ml_model_init(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options)
+{
+ struct ml_lib_model_options *old_options;
+ int err = 0;
+
+ if (!ml_model)
+ return -EINVAL;
+
+ if (!ml_model->model_ops || !ml_model->model_ops->init)
+ options->sleep_timeout = ML_LIB_SLEEP_TIMEOUT_DEFAULT;
+ else {
+ err = ml_model->model_ops->init(ml_model, options);
+ if (unlikely(err)) {
+ pr_err("ml_lib: failed to init ML model: err %d\n",
+ err);
+ goto finish_model_init;
+ }
+ }
+
+ spin_lock(&ml_model->options_lock);
+ old_options = rcu_dereference_protected(ml_model->options,
+ lockdep_is_held(&ml_model->options_lock));
+ rcu_assign_pointer(ml_model->options, options);
+ spin_unlock(&ml_model->options_lock);
+ synchronize_rcu();
+ free_ml_model_options(old_options);
+
+ atomic_set(&ml_model->state, ML_LIB_MODEL_INITIALIZED);
+
+finish_model_init:
+ return err;
+}
+EXPORT_SYMBOL(ml_model_init);
+
+int ml_model_re_init(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options)
+{
+ struct ml_lib_model_options *old_options;
+
+ if (!ml_model)
+ return -EINVAL;
+
+ spin_lock(&ml_model->options_lock);
+ old_options = rcu_dereference_protected(ml_model->options,
+ lockdep_is_held(&ml_model->options_lock));
+ rcu_assign_pointer(ml_model->options, options);
+ spin_unlock(&ml_model->options_lock);
+ synchronize_rcu();
+ free_ml_model_options(old_options);
+
+ return 0;
+}
+EXPORT_SYMBOL(ml_model_re_init);
+
+int ml_model_start(struct ml_lib_model *ml_model,
+ struct ml_lib_model_run_config *config)
+{
+ if (!ml_model)
+ return -EINVAL;
+
+ /* TODO: implement ML model start logic*/
+ atomic_set(&ml_model->state, ML_LIB_MODEL_STARTED);
+ pr_err("ml_lib: TODO: implement start ML model\n");
+ return 0;
+}
+EXPORT_SYMBOL(ml_model_start);
+
+int ml_model_stop(struct ml_lib_model *ml_model)
+{
+ if (!ml_model)
+ return -EINVAL;
+
+ /* TODO: implement ML model stop logic*/
+ atomic_set(&ml_model->state, ML_LIB_MODEL_STOPPED);
+ pr_err("ml_lib: TODO: implement stop ML model\n");
+ return 0;
+}
+EXPORT_SYMBOL(ml_model_stop);
+
+void ml_model_destroy(struct ml_lib_model *ml_model)
+{
+ struct ml_lib_model_options *old_options;
+ struct ml_lib_dataset *old_dataset;
+
+ if (!ml_model)
+ return;
+
+ atomic_set(&ml_model->state, ML_LIB_MODEL_SHUTTING_DOWN);
+
+ ml_model_delete_sysfs_group(ml_model);
+
+ spin_lock(&ml_model->options_lock);
+ old_options = rcu_dereference_protected(ml_model->options,
+ lockdep_is_held(&ml_model->options_lock));
+ rcu_assign_pointer(ml_model->options, NULL);
+ spin_unlock(&ml_model->options_lock);
+ synchronize_rcu();
+ free_ml_model_options(old_options);
+
+ spin_lock(&ml_model->dataset_lock);
+ old_dataset = rcu_dereference_protected(ml_model->dataset,
+ lockdep_is_held(&ml_model->dataset_lock));
+ rcu_assign_pointer(ml_model->dataset, NULL);
+ spin_unlock(&ml_model->dataset_lock);
+ synchronize_rcu();
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->destroy) {
+ /*
+ * Do nothing
+ */
+ } else
+ ml_model->dataset_ops->destroy(old_dataset);
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->free)
+ free_dataset(old_dataset);
+ else
+ ml_model->dataset_ops->free(old_dataset);
+
+ if (!ml_model->model_ops || !ml_model->model_ops->destroy) {
+ atomic_set(&ml_model->parent->type,
+ ML_LIB_UNKNOWN_SUBSYSTEM_TYPE);
+ } else
+ ml_model->model_ops->destroy(ml_model);
+
+ atomic_set(&ml_model->state, ML_LIB_MODEL_STATE_MAX);
+}
+EXPORT_SYMBOL(ml_model_destroy);
+
+struct ml_lib_subsystem_state *get_system_state(struct ml_lib_model *ml_model)
+{
+ return NULL;
+}
+EXPORT_SYMBOL(get_system_state);
+
+int ml_model_get_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_request_config *config,
+ struct ml_lib_user_space_request *request)
+{
+ struct ml_lib_dataset *old_dataset;
+ struct ml_lib_dataset *new_dataset;
+ size_t desc_size = sizeof(struct ml_lib_dataset);
+ int state;
+ int err = 0;
+
+ if (!ml_model)
+ return -EINVAL;
+
+ atomic_set(&ml_model->state, ML_LIB_MODEL_RUNNING);
+
+ rcu_read_lock();
+ old_dataset = rcu_dereference(ml_model->dataset);
+ if (old_dataset)
+ state = atomic_read(&old_dataset->state);
+ else
+ state = ML_LIB_UNKNOWN_DATASET_STATE;
+ rcu_read_unlock();
+
+ switch (state) {
+ case ML_LIB_DATASET_CLEAN:
+ case ML_LIB_DATASET_EXTRACTED_PARTIALLY:
+ case ML_LIB_DATASET_EXTRACTED_COMPLETELY:
+ /* nothing should be done */
+ goto finish_get_dataset;
+
+ default:
+ /* continue logic */
+ break;
+ }
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->allocate)
+ new_dataset = allocate_dataset(desc_size, GFP_KERNEL);
+ else {
+ new_dataset = ml_model->dataset_ops->allocate(desc_size,
+ GFP_KERNEL);
+ }
+
+ if (IS_ERR(new_dataset)) {
+ err = PTR_ERR(new_dataset);
+ pr_err("ml_lib: Failed to allocate dataset\n");
+ return err;
+ } else if (!new_dataset) {
+ err = -ENOMEM;
+ pr_err("ml_lib: Failed to allocate dataset\n");
+ return err;
+ }
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->init) {
+ /*
+ * Do nothing
+ */
+ } else {
+ err = ml_model->dataset_ops->init(new_dataset);
+ if (err) {
+ pr_err("ml_lib: Failed to init dataset: err %d\n",
+ err);
+ goto fail_get_dataset;
+ }
+ }
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->extract) {
+ atomic_set(&new_dataset->type, ML_LIB_EMPTY_DATASET);
+ atomic_set(&new_dataset->state, ML_LIB_DATASET_CLEAN);
+ new_dataset->allocated_size = 0;
+ new_dataset->portion_offset = 0;
+ new_dataset->portion_size = 0;
+ } else {
+ err = ml_model->dataset_ops->extract(ml_model, new_dataset);
+ if (err) {
+ pr_err("ml_lib: Failed to extract dataset: err %d\n",
+ err);
+ goto fail_get_dataset;
+ }
+ }
+
+ spin_lock(&ml_model->dataset_lock);
+ old_dataset = rcu_dereference_protected(ml_model->dataset,
+ lockdep_is_held(&ml_model->dataset_lock));
+ rcu_assign_pointer(ml_model->dataset, new_dataset);
+ spin_unlock(&ml_model->dataset_lock);
+ synchronize_rcu();
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->destroy) {
+ /*
+ * Do nothing
+ */
+ } else
+ ml_model->dataset_ops->destroy(old_dataset);
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->free)
+ free_dataset(old_dataset);
+ else
+ ml_model->dataset_ops->free(old_dataset);
+
+finish_get_dataset:
+ return 0;
+
+fail_get_dataset:
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->destroy) {
+ /*
+ * Do nothing
+ */
+ } else
+ ml_model->dataset_ops->destroy(new_dataset);
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->free)
+ free_dataset(new_dataset);
+ else
+ ml_model->dataset_ops->free(new_dataset);
+
+ return err;
+}
+EXPORT_SYMBOL(ml_model_get_dataset);
+
+int ml_model_discard_dataset(struct ml_lib_model *ml_model)
+{
+ struct ml_lib_dataset *old_dataset;
+ struct ml_lib_dataset *new_dataset;
+ size_t desc_size = sizeof(struct ml_lib_dataset);
+ int err;
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->allocate)
+ new_dataset = allocate_dataset(desc_size, GFP_KERNEL);
+ else {
+ new_dataset = ml_model->dataset_ops->allocate(desc_size,
+ GFP_KERNEL);
+ }
+
+ if (IS_ERR(new_dataset)) {
+ err = PTR_ERR(new_dataset);
+ pr_err("ml_lib: Failed to allocate dataset\n");
+ return err;
+ } else if (!new_dataset) {
+ err = -ENOMEM;
+ pr_err("ml_lib: Failed to allocate dataset\n");
+ return err;
+ }
+
+ spin_lock(&ml_model->dataset_lock);
+ old_dataset = rcu_dereference_protected(ml_model->dataset,
+ lockdep_is_held(&ml_model->dataset_lock));
+ if (old_dataset) {
+ atomic_set(&new_dataset->type, atomic_read(&old_dataset->type));
+ new_dataset->allocated_size = old_dataset->allocated_size;
+ new_dataset->portion_offset = old_dataset->portion_offset;
+ new_dataset->portion_size = old_dataset->portion_size;
+ } else {
+ atomic_set(&new_dataset->type, ML_LIB_EMPTY_DATASET);
+ new_dataset->allocated_size = 0;
+ new_dataset->portion_offset = 0;
+ new_dataset->portion_size = 0;
+ }
+ atomic_set(&new_dataset->state, ML_LIB_DATASET_OBSOLETE);
+ rcu_assign_pointer(ml_model->dataset, new_dataset);
+ spin_unlock(&ml_model->dataset_lock);
+ synchronize_rcu();
+
+ if (!ml_model->dataset_ops || !ml_model->dataset_ops->free)
+ free_dataset(old_dataset);
+ else
+ ml_model->dataset_ops->free(old_dataset);
+
+ return 0;
+}
+EXPORT_SYMBOL(ml_model_discard_dataset);
+
+int ml_model_preprocess_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(ml_model_preprocess_data);
+
+int ml_model_publish_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset,
+ struct ml_lib_user_space_notification *notify)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(ml_model_publish_data);
+
+int ml_model_preprocess_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(ml_model_preprocess_recommendation);
+
+int estimate_system_state(struct ml_lib_model *ml_model)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(estimate_system_state);
+
+int apply_ml_model_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(apply_ml_model_recommendation);
+
+int execute_ml_model_operation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(execute_ml_model_operation);
+
+int estimate_ml_model_efficiency(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(estimate_ml_model_efficiency);
+
+int ml_model_error_backpropagation(struct ml_lib_model *ml_model,
+ struct ml_lib_backpropagation_feedback *feedback,
+ struct ml_lib_user_space_notification *notify)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(ml_model_error_backpropagation);
+
+int correct_system_state(struct ml_lib_model *ml_model)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(correct_system_state);
+
+/******************************************************************************
+ * Generic implementation of ML model's methods *
+ ******************************************************************************/
+
+int generic_create_ml_model(struct ml_lib_model *ml_model)
+{
+ size_t size = sizeof(struct ml_lib_subsystem);
+
+ ml_model->parent = allocate_subsystem_object(size, GFP_KERNEL);
+ if (unlikely(!ml_model->parent))
+ return -ENOMEM;
+
+ atomic_set(&ml_model->parent->type, ML_LIB_GENERIC_SUBSYSTEM);
+ atomic_set(&ml_model->mode, ML_LIB_EMERGENCY_MODE);
+
+ return 0;
+}
+EXPORT_SYMBOL(generic_create_ml_model);
+
+int generic_init_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options)
+{
+ options->sleep_timeout = ML_LIB_SLEEP_TIMEOUT_DEFAULT;
+ return 0;
+}
+EXPORT_SYMBOL(generic_init_ml_model);
+
+int generic_re_init_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_options *options)
+{
+ options->sleep_timeout = ML_LIB_SLEEP_TIMEOUT_DEFAULT;
+ return 0;
+}
+EXPORT_SYMBOL(generic_re_init_ml_model);
+
+int generic_start_ml_model(struct ml_lib_model *ml_model,
+ struct ml_lib_model_run_config *config)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_start_ml_model);
+
+int generic_stop_ml_model(struct ml_lib_model *ml_model)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_stop_ml_model);
+
+void generic_destroy_ml_model(struct ml_lib_model *ml_model)
+{
+ atomic_set(&ml_model->parent->type, ML_LIB_UNKNOWN_SUBSYSTEM_TYPE);
+ atomic_set(&ml_model->mode, ML_LIB_UNKNOWN_MODE);
+}
+EXPORT_SYMBOL(generic_destroy_ml_model);
+
+struct ml_lib_subsystem_state *
+generic_get_system_state(struct ml_lib_model *ml_model)
+{
+ return NULL;
+}
+EXPORT_SYMBOL(generic_get_system_state);
+
+int generic_get_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset)
+{
+ atomic_set(&dataset->type, ML_LIB_EMPTY_DATASET);
+ atomic_set(&dataset->state, ML_LIB_DATASET_CLEAN);
+ dataset->allocated_size = 0;
+ dataset->portion_offset = 0;
+ dataset->portion_size = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(generic_get_dataset);
+
+int generic_preprocess_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_preprocess_data);
+
+int generic_publish_data(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset,
+ struct ml_lib_user_space_notification *notify)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_publish_data);
+
+int generic_preprocess_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_preprocess_recommendation);
+
+int generic_estimate_system_state(struct ml_lib_model *ml_model)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_estimate_system_state);
+
+int generic_apply_recommendation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_apply_recommendation);
+
+int generic_execute_operation(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_execute_operation);
+
+int generic_estimate_efficiency(struct ml_lib_model *ml_model,
+ struct ml_lib_user_space_recommendation *hint,
+ struct ml_lib_user_space_request *request)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_estimate_efficiency);
+
+int generic_error_backpropagation(struct ml_lib_model *ml_model,
+ struct ml_lib_backpropagation_feedback *feedback,
+ struct ml_lib_user_space_notification *notify)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_error_backpropagation);
+
+int generic_correct_system_state(struct ml_lib_model *ml_model)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(generic_correct_system_state);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Viacheslav Dubeyko <slava@dubeyko.com>");
+MODULE_DESCRIPTION("ML library");
+MODULE_VERSION("1.0");
diff --git a/lib/ml-lib/sysfs.c b/lib/ml-lib/sysfs.c
new file mode 100644
index 000000000000..fb4b7f44f793
--- /dev/null
+++ b/lib/ml-lib/sysfs.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Machine Learning (ML) library
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/ml-lib/ml_lib.h>
+
+#include "sysfs.h"
+
+struct ml_lib_feature_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct ml_lib_feature_attr *,
+ struct ml_lib_model *,
+ char *);
+ ssize_t (*store)(struct ml_lib_feature_attr *,
+ struct ml_lib_model *,
+ const char *, size_t);
+};
+
+#define ML_LIB_ATTR(type, name, mode, show, store) \
+ static struct ml_lib_##type##_attr ml_lib_##type##_attr_##name = \
+ __ATTR(name, mode, show, store)
+
+#define ML_LIB_FEATURE_INFO_ATTR(name) \
+ ML_LIB_ATTR(feature, name, 0444, NULL, NULL)
+#define ML_LIB_FEATURE_RO_ATTR(name) \
+ ML_LIB_ATTR(feature, name, 0444, ml_lib_feature_##name##_show, NULL)
+#define ML_LIB_FEATURE_W_ATTR(name) \
+ ML_LIB_ATTR(feature, name, 0220, NULL, ml_lib_feature_##name##_store)
+#define ML_LIB_FEATURE_RW_ATTR(name) \
+ ML_LIB_ATTR(feature, name, 0644, \
+ ml_lib_feature_##name##_show, ml_lib_feature_##name##_store)
+
+enum {
+ ML_LIB_START_COMMAND,
+ ML_LIB_STOP_COMMAND,
+ ML_LIB_PREPARE_DATASET_COMMAND,
+ ML_LIB_DISCARD_DATASET_COMMAND,
+ ML_LIB_COMMAND_NUMBER
+};
+
+static const char *control_command_str[ML_LIB_COMMAND_NUMBER] = {
+ "start",
+ "stop",
+ "prepare_dataset",
+ "discard_dataset",
+};
+
+static ssize_t ml_lib_feature_control_store(struct ml_lib_feature_attr *attr,
+ struct ml_lib_model *ml_model,
+ const char *buf, size_t len)
+{
+ struct ml_lib_model_run_config config = {0};
+ int i;
+ int err;
+
+ for (i = 0; i < ML_LIB_COMMAND_NUMBER; i++) {
+ size_t iter_len = min(len, strlen(control_command_str[i]));
+
+ if (strncmp(control_command_str[i], buf, iter_len) == 0)
+ break;
+ }
+
+ if (i >= ML_LIB_COMMAND_NUMBER)
+ return -EOPNOTSUPP;
+
+ switch (i) {
+ case ML_LIB_START_COMMAND:
+ err = ml_model_start(ml_model, &config);
+ break;
+
+ case ML_LIB_STOP_COMMAND:
+ err = ml_model_stop(ml_model);
+ break;
+
+ case ML_LIB_PREPARE_DATASET_COMMAND:
+ err = ml_model_get_dataset(ml_model, NULL, NULL);
+ break;
+
+ case ML_LIB_DISCARD_DATASET_COMMAND:
+ err = ml_model_discard_dataset(ml_model);
+ break;
+ }
+
+ if (unlikely(err))
+ return err;
+
+ return len;
+}
+
+ML_LIB_FEATURE_W_ATTR(control);
+
+static struct attribute *ml_model_attrs[] = {
+ &ml_lib_feature_attr_control.attr,
+ NULL,
+};
+
+static const struct attribute_group ml_model_group = {
+ .attrs = ml_model_attrs,
+};
+
+static const struct attribute_group *ml_model_groups[] = {
+ &ml_model_group,
+ NULL,
+};
+
+static
+ssize_t ml_model_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct ml_lib_model *ml_model = container_of(kobj,
+ struct ml_lib_model,
+ kobj);
+ struct ml_lib_feature_attr *ml_model_attr =
+ container_of(attr, struct ml_lib_feature_attr, attr);
+
+ if (!ml_model_attr->show)
+ return -EIO;
+
+ return ml_model_attr->show(ml_model_attr, ml_model, buf);
+}
+
+static
+ssize_t ml_model_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf, size_t len)
+{
+ struct ml_lib_model *ml_model = container_of(kobj,
+ struct ml_lib_model,
+ kobj);
+ struct ml_lib_feature_attr *ml_model_attr =
+ container_of(attr, struct ml_lib_feature_attr, attr);
+
+ if (!ml_model_attr->store)
+ return -EIO;
+
+ return ml_model_attr->store(ml_model_attr, ml_model, buf, len);
+}
+
+static const struct sysfs_ops ml_model_attr_ops = {
+ .show = ml_model_attr_show,
+ .store = ml_model_attr_store,
+};
+
+static inline
+void ml_model_kobj_release(struct kobject *kobj)
+{
+ struct ml_lib_model *ml_model = container_of(kobj,
+ struct ml_lib_model,
+ kobj);
+ complete(&ml_model->kobj_unregister);
+}
+
+static struct kobj_type ml_model_ktype = {
+ .default_groups = ml_model_groups,
+ .sysfs_ops = &ml_model_attr_ops,
+ .release = ml_model_kobj_release,
+};
+
+int ml_model_create_sysfs_group(struct ml_lib_model *ml_model,
+ struct kobject *subsystem_kobj)
+{
+ int err;
+
+ init_completion(&ml_model->kobj_unregister);
+
+ err = kobject_init_and_add(&ml_model->kobj, &ml_model_ktype,
+ subsystem_kobj,
+ "%s", ml_model->model_name);
+ if (err)
+ pr_err("ml_lib: failed to create sysfs group: err %d\n", err);
+
+ return err;
+}
+
+void ml_model_delete_sysfs_group(struct ml_lib_model *ml_model)
+{
+ kobject_del(&ml_model->kobj);
+ kobject_put(&ml_model->kobj);
+ wait_for_completion(&ml_model->kobj_unregister);
+}
diff --git a/lib/ml-lib/sysfs.h b/lib/ml-lib/sysfs.h
new file mode 100644
index 000000000000..6bd3ab64a1c0
--- /dev/null
+++ b/lib/ml-lib/sysfs.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Machine Learning (ML) library
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#ifndef _LINUX_ML_LIB_SYSFS_H
+#define _LINUX_ML_LIB_SYSFS_H
+
+#include <linux/sysfs.h>
+
+int ml_model_create_sysfs_group(struct ml_lib_model *ml_model,
+ struct kobject *subsystem_kobj);
+void ml_model_delete_sysfs_group(struct ml_lib_model *ml_model);
+
+#endif /* _LINUX_ML_LIB_SYSFS_H */
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver
2026-02-06 19:11 [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Viacheslav Dubeyko
2026-02-06 19:11 ` [RFC PATCH v1 1/4] ml-lib: Introduce Machine Learning (ML) library declarations Viacheslav Dubeyko
2026-02-06 19:11 ` [RFC PATCH v1 2/4] ml-lib: Implement PoC of Machine Learning (ML) library functionality Viacheslav Dubeyko
@ 2026-02-06 19:11 ` Viacheslav Dubeyko
2026-02-07 15:55 ` Greg KH
2026-02-06 19:11 ` [RFC PATCH v1 4/4] ml-lib: Implement simple user-space testing application Viacheslav Dubeyko
2026-02-06 22:59 ` [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Jonathan Corbet
4 siblings, 1 reply; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-06 19:11 UTC (permalink / raw)
To: linux-fsdevel, linux-mm, bpf; +Cc: Slava.Dubeyko, slava, linux-kernel
Implement simple testing character device driver
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
---
lib/ml-lib/test_driver/Kconfig | 22 +
lib/ml-lib/test_driver/Makefile | 5 +
lib/ml-lib/test_driver/README.md | 233 ++++++++++
lib/ml-lib/test_driver/ml_lib_char_dev.c | 530 +++++++++++++++++++++++
4 files changed, 790 insertions(+)
create mode 100644 lib/ml-lib/test_driver/Kconfig
create mode 100644 lib/ml-lib/test_driver/Makefile
create mode 100644 lib/ml-lib/test_driver/README.md
create mode 100644 lib/ml-lib/test_driver/ml_lib_char_dev.c
diff --git a/lib/ml-lib/test_driver/Kconfig b/lib/ml-lib/test_driver/Kconfig
new file mode 100644
index 000000000000..183fc1de57a8
--- /dev/null
+++ b/lib/ml-lib/test_driver/Kconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ML_LIB_TEST_DRIVER
+ tristate "ML library testing character device driver"
+ depends on ML_LIB
+ default n
+ help
+ This is a ML library testing character device driver for
+ testing generic ML library functionality. It provides:
+
+ - Basic read/write operations
+ - IOCTL interface for device control
+ - Sysfs attributes for runtime information
+ - Procfs entry for debugging
+
+ The driver creates a /dev/mllibdev device node that can be
+ used to read and write data to a kernel buffer.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mllibdev.
diff --git a/lib/ml-lib/test_driver/Makefile b/lib/ml-lib/test_driver/Makefile
new file mode 100644
index 000000000000..6444bcf8985b
--- /dev/null
+++ b/lib/ml-lib/test_driver/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_ML_LIB_TEST_DRIVER) += ml_lib_test_dev.o
+
+ml_lib_test_dev-y := ml_lib_char_dev.o
diff --git a/lib/ml-lib/test_driver/README.md b/lib/ml-lib/test_driver/README.md
new file mode 100644
index 000000000000..0bb4105c8aa4
--- /dev/null
+++ b/lib/ml-lib/test_driver/README.md
@@ -0,0 +1,233 @@
+# ML Library Testing Device Driver (mllibdev)
+
+ML library testing character device driver for the Linux kernel:
+- Basic read/write operations
+- IOCTL interface for device control
+- Sysfs attributes for runtime information
+- Procfs entry for debugging
+
+## Features
+
+### Character Device Operations
+- **Open/Close**: Device can be opened and closed multiple times
+- **Read**: Read data from a kernel buffer
+- **Write**: Write data to a kernel buffer (1KB capacity)
+- **Seek**: Support for lseek() operations
+
+### IOCTL Commands
+- `ML_LIB_TEST_DEV_IOCRESET`: Clear the device buffer
+- `ML_LIB_TEST_DEV_IOCGETSIZE`: Get current data size
+- `ML_LIB_TEST_DEV_IOCSETSIZE`: Set data size
+
+### Sysfs Attributes
+Located at `/sys/class/ml_lib_test/mllibdev`:
+- `buffer_size`: Maximum buffer capacity (read-only)
+- `data_size`: Current amount of data in buffer (read-only)
+- `access_count`: Number of times device has been opened (read-only)
+- `stats`: Comprehensive statistics (opens, reads, writes)
+
+### Procfs Entry
+Located at `/proc/mllibdev`: Provides formatted driver information
+
+## Building the Driver
+
+### Option 1: Build as a Module
+
+1. Configure the kernel to build mllibdev as a module:
+ ```bash
+ make menuconfig
+ # Navigate to: Library routines -> ML library testing character device driver
+ # Select: <M> ML library testing character device driver
+ ```
+
+2. Build the module:
+ ```bash
+ make -j$(nproc) M=lib/ml-lib/test_driver
+ ```
+
+### Option 2: Build into Kernel
+
+1. Configure the kernel:
+ ```bash
+ make menuconfig
+ # Navigate to: Library routines -> ML library testing character device driver
+ # Select: <*> ML library testing character device driver
+ ```
+
+2. Build the kernel:
+ ```bash
+ make -j$(nproc)
+ ```
+
+### Option 3: Quick Module Build (Out-of-Tree)
+
+For quick testing, you can build just the module:
+
+```bash
+cd lib/ml-lib/test_driver
+make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
+```
+
+## Loading the Driver
+
+If built as a module:
+
+```bash
+# Load the module
+sudo insmod /lib/modules/$(uname -r)/build/lib/ml-lib/test_driver/ml_lib_test_dev.ko
+
+# Verify it's loaded
+sudo lsmod | grep ml_lib_test_dev
+
+# Check kernel messages
+sudo dmesg | tail -20
+```
+
+You should see messages like:
+```
+ml_lib_test_dev: Initializing driver
+ml_lib_test_dev: Device number allocated: XXX:0
+ml_lib_test_dev: Driver initialized successfully
+ml_lib_test_dev: Device created at /dev/mllibdev
+ml_lib_test_dev: Proc entry created at /proc/mllibdev
+```
+
+## Testing the Driver
+
+### Quick Manual Test
+
+```bash
+# Write data to the device
+sudo su
+echo "Hello, kernel!" > /dev/mllibdev
+
+# Read data back
+sudo su
+cat /dev/mllibdev
+
+# Check sysfs attributes
+cat /sys/class/ml_lib_test/mllibdev/stats
+
+# Check proc entry
+cat /proc/mllibdev
+```
+
+### Using the Test Program
+
+1. Compile the test program:
+ ```bash
+ cd lib/ml-lib/test_driver/test_application
+ gcc -o ml_lib_test_dev test_ml_lib_char_dev.c
+ ```
+
+2. Run the test program:
+ ```bash
+ sudo ./ml_lib_test_dev
+ ```
+
+The test program will:
+- Open the device
+- Write test data
+- Read the data back
+- Test all IOCTL commands
+- Display sysfs attributes
+- Show procfs information
+
+### Example Test Output
+
+```
+ML Library Testing Device Driver Test Program
+==================================
+Device opened successfully: /dev/mllibdev
+
+========== Write Test ==========
+Successfully wrote 62 bytes
+Data: "Hello from userspace! This is a test of the mllibdev driver."
+
+========== Read Test ==========
+Successfully read 62 bytes
+Data: "Hello from userspace! This is a test of the mllibdev driver."
+
+========== IOCTL Tests ==========
+Current data size: 62 bytes
+Set data size to: 50 bytes
+Verified new size: 50 bytes
+Buffer reset successfully
+Size after reset: 0 bytes
+
+========== Sysfs Attributes ==========
+buffer_size: 1024
+data_size: 0
+access_count: 1
+
+stats: Opens: 1
+Reads: 1
+Writes: 1
+
+========== Procfs Information ==========
+ML Library Testing Device Driver Information
+=================================
+Device name: mllibdev
+Buffer size: 1024 bytes
+Data size: 0 bytes
+Access count: 1
+Read count: 1
+Write count: 1
+
+========== Final Test ==========
+All tests completed successfully!
+```
+
+## Unloading the Driver
+
+```bash
+# Remove the module
+sudo rmmod ml_lib_test_dev
+
+# Verify it's unloaded
+sudo lsmod | grep ml_lib_test_dev
+
+# Check cleanup messages
+sudo dmesg | tail -10
+```
+
+## Troubleshooting
+
+### Device node doesn't exist
+```bash
+# Check if udev created the device
+ls -l /dev/mllibdev
+
+# Manually create if needed (shouldn't be necessary)
+sudo mknod /dev/mllibdev c MAJOR MINOR
+```
+
+### Permission denied
+```bash
+# Run commands with sudo
+sudo cat /dev/mllibdev
+
+# Or change permissions
+sudo chmod 666 /dev/mllibdev
+```
+
+### Module won't load
+```bash
+# Check kernel messages for errors
+dmesg | tail -20
+
+# Verify module dependencies
+modinfo lib/ml-lib/test_driver/ml_lib_test_dev.ko
+```
+
+## License
+
+This driver is licensed under GPL-2.0.
+
+## Author
+
+Viacheslav Dubeyko <slava@dubeyko.com>
+
+## Version
+
+1.0
diff --git a/lib/ml-lib/test_driver/ml_lib_char_dev.c b/lib/ml-lib/test_driver/ml_lib_char_dev.c
new file mode 100644
index 000000000000..b2d6e27ece28
--- /dev/null
+++ b/lib/ml-lib/test_driver/ml_lib_char_dev.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Machine Learning (ML) library
+ * Testing Character Device Driver
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mutex.h>
+#include <linux/ml-lib/ml_lib.h>
+
+#define DEVICE_NAME "mllibdev"
+#define CLASS_NAME "ml_lib_test"
+#define BUFFER_SIZE 1024
+
+/* IOCTL commands */
+#define ML_LIB_TEST_DEV_IOC_MAGIC 'M'
+#define ML_LIB_TEST_DEV_IOCRESET _IO(ML_LIB_TEST_DEV_IOC_MAGIC, 0)
+#define ML_LIB_TEST_DEV_IOCGETSIZE _IOR(ML_LIB_TEST_DEV_IOC_MAGIC, 1, int)
+#define ML_LIB_TEST_DEV_IOCSETSIZE _IOW(ML_LIB_TEST_DEV_IOC_MAGIC, 2, int)
+
+/* Device data structure */
+struct ml_lib_test_dev_data {
+ struct cdev cdev;
+ struct device *device;
+ char *dataset_buf;
+ size_t dataset_buf_size;
+ size_t dataset_size;
+ char *recommendations_buf;
+ size_t recommendations_buf_size;
+ size_t recommendations_size;
+ struct mutex lock;
+ unsigned long access_count;
+ unsigned long read_count;
+ unsigned long write_count;
+
+ struct ml_lib_model *ml_model1;
+};
+
+#define ML_MODEL_1_NAME "ml_model1"
+
+static
+int ml_lib_test_dev_extract_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset);
+
+static struct ml_lib_dataset_operations ml_lib_test_dev_dataset_ops = {
+ .extract = ml_lib_test_dev_extract_dataset,
+};
+
+static dev_t dev_number;
+static struct class *ml_lib_test_dev_class;
+static struct ml_lib_test_dev_data *dev_data;
+static struct proc_dir_entry *proc_entry;
+
+/* ML model operations */
+static
+int ml_lib_test_dev_extract_dataset(struct ml_lib_model *ml_model,
+ struct ml_lib_dataset *dataset)
+{
+ struct ml_lib_test_dev_data *data =
+ (struct ml_lib_test_dev_data *)ml_model->parent->private;
+ u8 pattern;
+
+ mutex_lock(&data->lock);
+ get_random_bytes(&pattern, 1);
+ memset(data->dataset_buf, pattern, data->dataset_buf_size);
+ data->dataset_size = data->dataset_buf_size;
+ atomic_set(&dataset->type, ML_LIB_MEMORY_STREAM_DATASET);
+ atomic_set(&dataset->state, ML_LIB_DATASET_CLEAN);
+ dataset->allocated_size = data->dataset_buf_size;
+ dataset->portion_offset = 0;
+ dataset->portion_size = data->dataset_buf_size;
+ mutex_unlock(&data->lock);
+
+ return 0;
+}
+
+/* File operations */
+static int ml_lib_test_dev_open(struct inode *inode, struct file *file)
+{
+ struct ml_lib_test_dev_data *data = container_of(inode->i_cdev,
+ struct ml_lib_test_dev_data,
+ cdev);
+
+ file->private_data = data;
+
+ mutex_lock(&data->lock);
+ data->access_count++;
+ mutex_unlock(&data->lock);
+
+ pr_info("ml_lib_test_dev: Device opened (total opens: %lu)\n",
+ data->access_count);
+
+ return 0;
+}
+
+static int ml_lib_test_dev_release(struct inode *inode, struct file *file)
+{
+ pr_info("ml_lib_test_dev: Device closed\n");
+ return 0;
+}
+
+static ssize_t ml_lib_test_dev_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ml_lib_test_dev_data *data = file->private_data;
+ size_t to_read;
+ int ret;
+
+ mutex_lock(&data->lock);
+
+ if (*ppos >= data->dataset_size) {
+ mutex_unlock(&data->lock);
+ return 0;
+ }
+
+ to_read = min(count, data->dataset_size - (size_t)*ppos);
+
+ ret = copy_to_user(buf, data->dataset_buf + *ppos, to_read);
+ if (ret) {
+ mutex_unlock(&data->lock);
+ return -EFAULT;
+ }
+
+ *ppos += to_read;
+ data->read_count++;
+
+ mutex_unlock(&data->lock);
+
+ pr_info("ml_lib_test_dev: Read %zu bytes\n", to_read);
+
+ return to_read;
+}
+
+static ssize_t ml_lib_test_dev_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ml_lib_test_dev_data *data = file->private_data;
+ size_t to_write;
+ int ret;
+
+ mutex_lock(&data->lock);
+
+ if (*ppos >= data->recommendations_buf_size) {
+ mutex_unlock(&data->lock);
+ return -ENOSPC;
+ }
+
+ to_write = min(count, data->recommendations_buf_size - (size_t)*ppos);
+
+ ret = copy_from_user(data->recommendations_buf + *ppos, buf, to_write);
+ if (ret) {
+ mutex_unlock(&data->lock);
+ return -EFAULT;
+ }
+
+ *ppos += to_write;
+ if (*ppos > data->recommendations_size)
+ data->recommendations_size = *ppos;
+
+ data->write_count++;
+
+ mutex_unlock(&data->lock);
+
+ pr_info("ml_lib_test_dev: Wrote %zu bytes\n", to_write);
+
+ return to_write;
+}
+
+static long ml_lib_test_dev_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct ml_lib_test_dev_data *data = file->private_data;
+ int size;
+
+ switch (cmd) {
+ case ML_LIB_TEST_DEV_IOCRESET:
+ mutex_lock(&data->lock);
+ memset(data->dataset_buf,
+ 0, data->dataset_buf_size);
+ data->dataset_size = 0;
+ memset(data->recommendations_buf,
+ 0, data->recommendations_buf_size);
+ data->recommendations_size = 0;
+ mutex_unlock(&data->lock);
+ pr_info("ml_lib_test_dev: Buffer reset via IOCTL\n");
+ break;
+
+ case ML_LIB_TEST_DEV_IOCGETSIZE:
+ mutex_lock(&data->lock);
+ size = data->dataset_size;
+ mutex_unlock(&data->lock);
+ if (copy_to_user((int __user *)arg, &size, sizeof(size)))
+ return -EFAULT;
+ break;
+
+ case ML_LIB_TEST_DEV_IOCSETSIZE:
+ if (copy_from_user(&size, (int __user *)arg, sizeof(size)))
+ return -EFAULT;
+ if (size < 0 || size > data->recommendations_buf_size)
+ return -EINVAL;
+ mutex_lock(&data->lock);
+ data->recommendations_size = size;
+ mutex_unlock(&data->lock);
+ pr_info("ml_lib_test_dev: Data size set to %d via IOCTL\n", size);
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static const struct file_operations ml_lib_test_dev_fops = {
+ .owner = THIS_MODULE,
+ .open = ml_lib_test_dev_open,
+ .release = ml_lib_test_dev_release,
+ .read = ml_lib_test_dev_read,
+ .write = ml_lib_test_dev_write,
+ .unlocked_ioctl = ml_lib_test_dev_ioctl,
+ .llseek = default_llseek,
+};
+
+/* Sysfs attributes */
+static ssize_t buffer_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%zu\n", data->dataset_buf_size);
+}
+
+static ssize_t data_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+ size_t size;
+
+ mutex_lock(&data->lock);
+ size = data->dataset_size;
+ mutex_unlock(&data->lock);
+
+ return sprintf(buf, "%zu\n", size);
+}
+
+static ssize_t access_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%lu\n", data->access_count);
+}
+
+static ssize_t stats_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "Opens: %lu\nReads: %lu\nWrites: %lu\n",
+ data->access_count, data->read_count,
+ data->write_count);
+}
+
+static DEVICE_ATTR_RO(buffer_size);
+static DEVICE_ATTR_RO(data_size);
+static DEVICE_ATTR_RO(access_count);
+static DEVICE_ATTR_RO(stats);
+
+static struct attribute *ml_lib_test_dev_attrs[] = {
+ &dev_attr_buffer_size.attr,
+ &dev_attr_data_size.attr,
+ &dev_attr_access_count.attr,
+ &dev_attr_stats.attr,
+ NULL,
+};
+
+static const struct attribute_group ml_lib_test_dev_attr_group = {
+ .attrs = ml_lib_test_dev_attrs,
+};
+
+/* Procfs operations */
+static int ml_lib_test_dev_proc_show(struct seq_file *m, void *v)
+{
+ struct ml_lib_test_dev_data *data = dev_data;
+
+ seq_printf(m, "ML Library Testing Device Driver Information\n");
+ seq_printf(m, "=================================\n");
+ seq_printf(m, "Device name: %s\n", DEVICE_NAME);
+ seq_printf(m, "Buffer size: %zu bytes\n", data->dataset_buf_size);
+ seq_printf(m, "Data size: %zu bytes\n", data->dataset_size);
+ seq_printf(m, "Access count: %lu\n", data->access_count);
+ seq_printf(m, "Read count: %lu\n", data->read_count);
+ seq_printf(m, "Write count: %lu\n", data->write_count);
+
+ return 0;
+}
+
+static int ml_lib_test_dev_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ml_lib_test_dev_proc_show, NULL);
+}
+
+static const struct proc_ops ml_lib_test_dev_proc_ops = {
+ .proc_open = ml_lib_test_dev_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+};
+
+/* Module initialization */
+static int __init ml_lib_test_dev_init(void)
+{
+ struct ml_lib_model_options *options;
+ int ret;
+
+ pr_info("ml_lib_test_dev: Initializing driver\n");
+
+ /* Allocate device data */
+ dev_data = kzalloc(sizeof(struct ml_lib_test_dev_data), GFP_KERNEL);
+ if (!dev_data)
+ return -ENOMEM;
+
+ /* Allocate dataset buffer */
+ dev_data->dataset_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+ if (!dev_data->dataset_buf) {
+ ret = -ENOMEM;
+ goto err_free_data;
+ }
+
+ dev_data->dataset_buf_size = BUFFER_SIZE;
+ dev_data->dataset_size = 0;
+
+ /* Allocate recomendations buffer */
+ dev_data->recommendations_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+ if (!dev_data->recommendations_buf) {
+ ret = -ENOMEM;
+ goto err_free_dataset_buffer;
+ }
+
+ dev_data->recommendations_buf_size = BUFFER_SIZE;
+ dev_data->recommendations_size = 0;
+
+ mutex_init(&dev_data->lock);
+
+ /* Allocate device number */
+ ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME);
+ if (ret < 0) {
+ pr_err("ml_lib_test_dev: Failed to allocate device number\n");
+ goto err_free_recommendations_buffer;
+ }
+
+ pr_info("ml_lib_test_dev: Device number allocated: %d:%d\n",
+ MAJOR(dev_number), MINOR(dev_number));
+
+ /* Create device class */
+ ml_lib_test_dev_class = class_create(CLASS_NAME);
+ if (IS_ERR(ml_lib_test_dev_class)) {
+ ret = PTR_ERR(ml_lib_test_dev_class);
+ pr_err("ml_lib_test_dev: Failed to create class\n");
+ goto err_unregister_chrdev;
+ }
+
+ /* Initialize and add cdev */
+ cdev_init(&dev_data->cdev, &ml_lib_test_dev_fops);
+ dev_data->cdev.owner = THIS_MODULE;
+
+ ret = cdev_add(&dev_data->cdev, dev_number, 1);
+ if (ret < 0) {
+ pr_err("ml_lib_test_dev: Failed to add cdev\n");
+ goto err_class_destroy;
+ }
+
+ /* Create device */
+ dev_data->device = device_create(ml_lib_test_dev_class,
+ NULL, dev_number,
+ dev_data, DEVICE_NAME);
+ if (IS_ERR(dev_data->device)) {
+ ret = PTR_ERR(dev_data->device);
+ pr_err("ml_lib_test_dev: Failed to create device\n");
+ goto err_cdev_del;
+ }
+
+ /* Create sysfs attributes */
+ ret = sysfs_create_group(&dev_data->device->kobj,
+ &ml_lib_test_dev_attr_group);
+ if (ret < 0) {
+ pr_err("ml_lib_test_dev: Failed to create sysfs group\n");
+ goto err_device_destroy;
+ }
+
+ /* Create procfs entry */
+ proc_entry = proc_create(DEVICE_NAME, 0444, NULL,
+ &ml_lib_test_dev_proc_ops);
+ if (!proc_entry) {
+ pr_err("ml_lib_test_dev: Failed to create proc entry\n");
+ ret = -ENOMEM;
+ goto err_sysfs_remove;
+ }
+
+ dev_data->ml_model1 = allocate_ml_model(sizeof(struct ml_lib_model),
+ GFP_KERNEL);
+ if (IS_ERR(dev_data->ml_model1)) {
+ ret = PTR_ERR(dev_data->ml_model1);
+ pr_err("ml_lib_test_dev: Failed to allocate ML model\n");
+ goto err_procfs_remove;
+ } else if (!dev_data->ml_model1) {
+ ret = -ENOMEM;
+ pr_err("ml_lib_test_dev: Failed to allocate ML model\n");
+ goto err_procfs_remove;
+ }
+
+ ret = ml_model_create(dev_data->ml_model1, CLASS_NAME,
+ ML_MODEL_1_NAME, &dev_data->device->kobj);
+ if (ret < 0) {
+ pr_err("ml_lib_test_dev: Failed to create ML model\n");
+ goto err_ml_model_free;
+ }
+
+ dev_data->ml_model1->parent->private = dev_data;
+ dev_data->ml_model1->model_ops = NULL;
+ dev_data->ml_model1->dataset_ops = &ml_lib_test_dev_dataset_ops;
+
+ options = allocate_ml_model_options(sizeof(struct ml_lib_model_options),
+ GFP_KERNEL);
+ if (IS_ERR(options)) {
+ ret = PTR_ERR(options);
+ pr_err("ml_lib_test_dev: Failed to allocate ML model options\n");
+ goto err_ml_model_destroy;
+ } else if (!options) {
+ ret = -ENOMEM;
+ pr_err("ml_lib_test_dev: Failed to allocate ML model options\n");
+ goto err_ml_model_destroy;
+ }
+
+ ret = ml_model_init(dev_data->ml_model1, options);
+ if (ret < 0) {
+ pr_err("ml_lib_test_dev: Failed to init ML model\n");
+ goto err_ml_model_options_free;
+ }
+
+ pr_info("ml_lib_test_dev: Driver initialized successfully\n");
+ pr_info("ml_lib_test_dev: Device created at /dev/%s\n",
+ DEVICE_NAME);
+ pr_info("ml_lib_test_dev: Proc entry created at /proc/%s\n",
+ DEVICE_NAME);
+
+ return 0;
+
+err_ml_model_options_free:
+ free_ml_model_options(options);
+err_ml_model_destroy:
+ ml_model_destroy(dev_data->ml_model1);
+err_ml_model_free:
+ free_ml_model(dev_data->ml_model1);
+err_procfs_remove:
+ proc_remove(proc_entry);
+err_sysfs_remove:
+ sysfs_remove_group(&dev_data->device->kobj,
+ &ml_lib_test_dev_attr_group);
+err_device_destroy:
+ device_destroy(ml_lib_test_dev_class, dev_number);
+err_cdev_del:
+ cdev_del(&dev_data->cdev);
+err_class_destroy:
+ class_destroy(ml_lib_test_dev_class);
+err_unregister_chrdev:
+ unregister_chrdev_region(dev_number, 1);
+err_free_recommendations_buffer:
+ kfree(dev_data->recommendations_buf);
+err_free_dataset_buffer:
+ kfree(dev_data->dataset_buf);
+err_free_data:
+ kfree(dev_data);
+ return ret;
+}
+
+/* Module cleanup */
+static void __exit ml_lib_test_dev_exit(void)
+{
+ pr_info("ml_lib_test_dev: Cleaning up driver\n");
+
+ /* Destroy ML model */
+ ml_model_destroy(dev_data->ml_model1);
+ free_ml_model(dev_data->ml_model1);
+
+ /* Remove procfs entry */
+ proc_remove(proc_entry);
+
+ /* Remove sysfs attributes */
+ sysfs_remove_group(&dev_data->device->kobj,
+ &ml_lib_test_dev_attr_group);
+
+ /* Destroy device */
+ device_destroy(ml_lib_test_dev_class, dev_number);
+
+ /* Delete cdev */
+ cdev_del(&dev_data->cdev);
+
+ /* Destroy class */
+ class_destroy(ml_lib_test_dev_class);
+
+ /* Unregister device number */
+ unregister_chrdev_region(dev_number, 1);
+
+ /* Free buffers */
+ kfree(dev_data->recommendations_buf);
+ kfree(dev_data->dataset_buf);
+ kfree(dev_data);
+
+ pr_info("ml_lib_test_dev: Driver removed successfully\n");
+}
+
+module_init(ml_lib_test_dev_init);
+module_exit(ml_lib_test_dev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Viacheslav Dubeyko <slava@dubeyko.com>");
+MODULE_DESCRIPTION("ML libraray testing character device driver");
+MODULE_VERSION("1.0");
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver
2026-02-06 19:11 ` [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver Viacheslav Dubeyko
@ 2026-02-07 15:55 ` Greg KH
2026-02-09 20:56 ` Viacheslav Dubeyko
0 siblings, 1 reply; 14+ messages in thread
From: Greg KH @ 2026-02-07 15:55 UTC (permalink / raw)
To: Viacheslav Dubeyko
Cc: linux-fsdevel, linux-mm, bpf, Slava.Dubeyko, linux-kernel
On Fri, Feb 06, 2026 at 11:11:35AM -0800, Viacheslav Dubeyko wrote:
> Implement simple testing character device driver
>
> Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
It's hard to tell if this is just an early april-fools joke or not, but
if it's not:
> +### Character Device Operations
> +- **Open/Close**: Device can be opened and closed multiple times
> +- **Read**: Read data from a kernel buffer
> +- **Write**: Write data to a kernel buffer (1KB capacity)
> +- **Seek**: Support for lseek() operations
> +
> +### IOCTL Commands
> +- `ML_LIB_TEST_DEV_IOCRESET`: Clear the device buffer
> +- `ML_LIB_TEST_DEV_IOCGETSIZE`: Get current data size
> +- `ML_LIB_TEST_DEV_IOCSETSIZE`: Set data size
> +
> +### Sysfs Attributes
> +Located at `/sys/class/ml_lib_test/mllibdev`:
> +- `buffer_size`: Maximum buffer capacity (read-only)
> +- `data_size`: Current amount of data in buffer (read-only)
> +- `access_count`: Number of times device has been opened (read-only)
> +- `stats`: Comprehensive statistics (opens, reads, writes)
Again, this is not an acceptable use of sysfs.
> + /* Allocate device number */
> + ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME);
Don't burn a cdev for this, please use the misc device api.
good luck!
greg k-h
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver
2026-02-07 15:55 ` Greg KH
@ 2026-02-09 20:56 ` Viacheslav Dubeyko
2026-02-10 5:21 ` greg
0 siblings, 1 reply; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-09 20:56 UTC (permalink / raw)
To: greg, slava; +Cc: linux-mm, linux-fsdevel, linux-kernel, bpf
On Sat, 2026-02-07 at 16:55 +0100, Greg KH wrote:
> On Fri, Feb 06, 2026 at 11:11:35AM -0800, Viacheslav Dubeyko wrote:
> > Implement simple testing character device driver
> >
> > Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
>
> It's hard to tell if this is just an early april-fools joke or not, but
> if it's not:
>
> > +### Character Device Operations
> > +- **Open/Close**: Device can be opened and closed multiple times
> > +- **Read**: Read data from a kernel buffer
> > +- **Write**: Write data to a kernel buffer (1KB capacity)
> > +- **Seek**: Support for lseek() operations
> > +
> > +### IOCTL Commands
> > +- `ML_LIB_TEST_DEV_IOCRESET`: Clear the device buffer
> > +- `ML_LIB_TEST_DEV_IOCGETSIZE`: Get current data size
> > +- `ML_LIB_TEST_DEV_IOCSETSIZE`: Set data size
> > +
> > +### Sysfs Attributes
> > +Located at `/sys/class/ml_lib_test/mllibdev`:
> > +- `buffer_size`: Maximum buffer capacity (read-only)
> > +- `data_size`: Current amount of data in buffer (read-only)
> > +- `access_count`: Number of times device has been opened (read-only)
> > +- `stats`: Comprehensive statistics (opens, reads, writes)
>
> Again, this is not an acceptable use of sysfs.
Maybe, I am missing your point. Are you assuming that I am going to share huge
pieces of data by means of sysfs? If so, then I am not going to use sysfs for
it.
>
> > + /* Allocate device number */
> > + ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME);
>
> Don't burn a cdev for this, please use the misc device api.
>
It is not real-life driver. It is only testing driver with the goal to
check/test the ML library infrastructure and to show the potential way of using
the ML library.
As the next step, I am planning to use the ML library for two potential real-
life use-case: (1) GC subsystem of LFS file system, (2) ML-based DAMON approach.
So, this driver is only testing engine of implementing and testing the vision of
ML library.
Thanks,
Slava.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver
2026-02-09 20:56 ` Viacheslav Dubeyko
@ 2026-02-10 5:21 ` greg
0 siblings, 0 replies; 14+ messages in thread
From: greg @ 2026-02-10 5:21 UTC (permalink / raw)
To: Viacheslav Dubeyko; +Cc: slava, linux-mm, linux-fsdevel, linux-kernel, bpf
On Mon, Feb 09, 2026 at 08:56:47PM +0000, Viacheslav Dubeyko wrote:
> On Sat, 2026-02-07 at 16:55 +0100, Greg KH wrote:
> > On Fri, Feb 06, 2026 at 11:11:35AM -0800, Viacheslav Dubeyko wrote:
> > > Implement simple testing character device driver
> > >
> > > Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
> >
> > It's hard to tell if this is just an early april-fools joke or not, but
> > if it's not:
> >
> > > +### Character Device Operations
> > > +- **Open/Close**: Device can be opened and closed multiple times
> > > +- **Read**: Read data from a kernel buffer
> > > +- **Write**: Write data to a kernel buffer (1KB capacity)
> > > +- **Seek**: Support for lseek() operations
> > > +
> > > +### IOCTL Commands
> > > +- `ML_LIB_TEST_DEV_IOCRESET`: Clear the device buffer
> > > +- `ML_LIB_TEST_DEV_IOCGETSIZE`: Get current data size
> > > +- `ML_LIB_TEST_DEV_IOCSETSIZE`: Set data size
> > > +
> > > +### Sysfs Attributes
> > > +Located at `/sys/class/ml_lib_test/mllibdev`:
> > > +- `buffer_size`: Maximum buffer capacity (read-only)
> > > +- `data_size`: Current amount of data in buffer (read-only)
> > > +- `access_count`: Number of times device has been opened (read-only)
> > > +- `stats`: Comprehensive statistics (opens, reads, writes)
> >
> > Again, this is not an acceptable use of sysfs.
>
> Maybe, I am missing your point. Are you assuming that I am going to share huge
> pieces of data by means of sysfs? If so, then I am not going to use sysfs for
> it.
Please do not use sysfs for this at all.
> > > + /* Allocate device number */
> > > + ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME);
> >
> > Don't burn a cdev for this, please use the misc device api.
> >
>
> It is not real-life driver. It is only testing driver with the goal to
> check/test the ML library infrastructure and to show the potential way of using
> the ML library.
>
> As the next step, I am planning to use the ML library for two potential real-
> life use-case: (1) GC subsystem of LFS file system, (2) ML-based DAMON approach.
>
> So, this driver is only testing engine of implementing and testing the vision of
> ML library.
We don't take code that uses apis incorrectly. Please do not use a cdev
for this type of "testing" driver, that is the incorrect thing to do and
actually makes your code more complex than it needs to.
good luck!
greg k-h
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v1 4/4] ml-lib: Implement simple user-space testing application
2026-02-06 19:11 [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Viacheslav Dubeyko
` (2 preceding siblings ...)
2026-02-06 19:11 ` [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver Viacheslav Dubeyko
@ 2026-02-06 19:11 ` Viacheslav Dubeyko
2026-02-06 22:59 ` [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Jonathan Corbet
4 siblings, 0 replies; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-06 19:11 UTC (permalink / raw)
To: linux-fsdevel, linux-mm, bpf; +Cc: Slava.Dubeyko, slava, linux-kernel
Implement simple user-space testing application
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
---
.../test_application/ml_lib_char_dev_ioctl.h | 21 ++
.../test_application/test_ml_lib_char_dev.c | 206 ++++++++++++++++++
2 files changed, 227 insertions(+)
create mode 100644 lib/ml-lib/test_driver/test_application/ml_lib_char_dev_ioctl.h
create mode 100644 lib/ml-lib/test_driver/test_application/test_ml_lib_char_dev.c
diff --git a/lib/ml-lib/test_driver/test_application/ml_lib_char_dev_ioctl.h b/lib/ml-lib/test_driver/test_application/ml_lib_char_dev_ioctl.h
new file mode 100644
index 000000000000..7ea74e840fda
--- /dev/null
+++ b/lib/ml-lib/test_driver/test_application/ml_lib_char_dev_ioctl.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Machine Learning (ML) library
+ *
+ * Userspace API for ml_lib_dev testing driver
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ */
+
+#ifndef _ML_LIB_TEST_DEV_IOCTL_H
+#define _ML_LIB_TEST_DEV_IOCTL_H
+
+#include <linux/ioctl.h>
+
+/* IOCTL commands */
+#define ML_LIB_TEST_DEV_IOC_MAGIC 'M'
+#define ML_LIB_TEST_DEV_IOCRESET _IO(ML_LIB_TEST_DEV_IOC_MAGIC, 0)
+#define ML_LIB_TEST_DEV_IOCGETSIZE _IOR(ML_LIB_TEST_DEV_IOC_MAGIC, 1, int)
+#define ML_LIB_TEST_DEV_IOCSETSIZE _IOW(ML_LIB_TEST_DEV_IOC_MAGIC, 2, int)
+
+#endif /* _ML_LIB_TEST_DEV_IOCTL_H */
diff --git a/lib/ml-lib/test_driver/test_application/test_ml_lib_char_dev.c b/lib/ml-lib/test_driver/test_application/test_ml_lib_char_dev.c
new file mode 100644
index 000000000000..432b8a0ad068
--- /dev/null
+++ b/lib/ml-lib/test_driver/test_application/test_ml_lib_char_dev.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Machine Learning (ML) library
+ *
+ * Test program for ml_lib_dev testing driver
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Compile with: gcc -o test_ml_lib_char_dev test_ml_lib_char_dev.c
+ * Run with: sudo ./test_ml_lib_char_dev
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "ml_lib_char_dev_ioctl.h"
+
+#define DEVICE_PATH "/dev/mllibdev"
+#define SYSFS_BASE "/sys/class/ml_lib_test/mllibdev"
+#define PROC_PATH "/proc/mllibdev"
+
+static void print_separator(const char *title)
+{
+ printf("\n========== %s ==========\n", title);
+}
+
+static void read_sysfs_attr(const char *attr_name)
+{
+ char path[256];
+ char buffer[256];
+ FILE *fp;
+
+ snprintf(path, sizeof(path), "%s/%s", SYSFS_BASE, attr_name);
+ fp = fopen(path, "r");
+ if (!fp) {
+ perror("Failed to open sysfs attribute");
+ return;
+ }
+
+ if (fgets(buffer, sizeof(buffer), fp)) {
+ printf(" %s: %s", attr_name, buffer);
+ }
+
+ fclose(fp);
+}
+
+static void show_sysfs_info(void)
+{
+ print_separator("Sysfs Attributes");
+ read_sysfs_attr("buffer_size");
+ read_sysfs_attr("data_size");
+ read_sysfs_attr("access_count");
+ printf("\n");
+ read_sysfs_attr("stats");
+}
+
+static void show_proc_info(void)
+{
+ char buffer[1024];
+ FILE *fp;
+
+ print_separator("Procfs Information");
+
+ fp = fopen(PROC_PATH, "r");
+ if (!fp) {
+ perror("Failed to open procfs entry");
+ return;
+ }
+
+ while (fgets(buffer, sizeof(buffer), fp)) {
+ printf("%s", buffer);
+ }
+
+ fclose(fp);
+}
+
+static void test_write(int fd)
+{
+ const char *test_data = "Hello from userspace! This is a test of the mllibdev driver.";
+ ssize_t ret;
+
+ print_separator("Write Test");
+
+ ret = write(fd, test_data, strlen(test_data));
+ if (ret < 0) {
+ perror("Write failed");
+ return;
+ }
+
+ printf("Successfully wrote %zd bytes\n", ret);
+ printf("Data: \"%s\"\n", test_data);
+}
+
+static void test_read(int fd)
+{
+ char buffer[256];
+ ssize_t ret;
+
+ print_separator("Read Test");
+
+ /* Seek to beginning */
+ lseek(fd, 0, SEEK_SET);
+
+ ret = read(fd, buffer, sizeof(buffer) - 1);
+ if (ret < 0) {
+ perror("Read failed");
+ return;
+ }
+
+ buffer[ret] = '\0';
+ printf("Successfully read %zd bytes\n", ret);
+ printf("Data: \"%s\"\n", buffer);
+}
+
+static void test_ioctl(int fd)
+{
+ int size;
+ int ret;
+
+ print_separator("IOCTL Tests");
+
+ /* Get current size */
+ ret = ioctl(fd, ML_LIB_TEST_DEV_IOCGETSIZE, &size);
+ if (ret < 0) {
+ perror("IOCTL GETSIZE failed");
+ return;
+ }
+ printf("Current data size: %d bytes\n", size);
+
+ /* Set new size */
+ size = 50;
+ ret = ioctl(fd, ML_LIB_TEST_DEV_IOCSETSIZE, &size);
+ if (ret < 0) {
+ perror("IOCTL SETSIZE failed");
+ return;
+ }
+ printf("Set data size to: %d bytes\n", size);
+
+ /* Verify new size */
+ ret = ioctl(fd, ML_LIB_TEST_DEV_IOCGETSIZE, &size);
+ if (ret < 0) {
+ perror("IOCTL GETSIZE failed");
+ return;
+ }
+ printf("Verified new size: %d bytes\n", size);
+
+ /* Reset buffer */
+ ret = ioctl(fd, ML_LIB_TEST_DEV_IOCRESET);
+ if (ret < 0) {
+ perror("IOCTL RESET failed");
+ return;
+ }
+ printf("Buffer reset successfully\n");
+
+ /* Verify size after reset */
+ ret = ioctl(fd, ML_LIB_TEST_DEV_IOCGETSIZE, &size);
+ if (ret < 0) {
+ perror("IOCTL GETSIZE failed");
+ return;
+ }
+ printf("Size after reset: %d bytes\n", size);
+}
+
+int main(void)
+{
+ int fd;
+
+ printf("ML Library Testing Device Driver Test Program\n");
+ printf("==================================\n");
+
+ /* Open the device */
+ fd = open(DEVICE_PATH, O_RDWR);
+ if (fd < 0) {
+ perror("Failed to open device");
+ printf("\nMake sure:\n");
+ printf("1. The driver module is loaded (lsmod | grep mllibdev)\n");
+ printf("2. You have proper permissions (run with sudo)\n");
+ printf("3. The device node exists (ls -l /dev/mllibdev)\n");
+ return 1;
+ }
+
+ printf("Device opened successfully: %s\n", DEVICE_PATH);
+
+ /* Run tests */
+ test_write(fd);
+ test_read(fd);
+ test_ioctl(fd);
+
+ /* Show sysfs and proc information */
+ show_sysfs_info();
+ show_proc_info();
+
+ /* Final stats */
+ print_separator("Final Test");
+ printf("All tests completed successfully!\n\n");
+
+ /* Close the device */
+ close(fd);
+
+ return 0;
+}
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel
2026-02-06 19:11 [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Viacheslav Dubeyko
` (3 preceding siblings ...)
2026-02-06 19:11 ` [RFC PATCH v1 4/4] ml-lib: Implement simple user-space testing application Viacheslav Dubeyko
@ 2026-02-06 22:59 ` Jonathan Corbet
2026-02-09 20:33 ` Viacheslav Dubeyko
4 siblings, 1 reply; 14+ messages in thread
From: Jonathan Corbet @ 2026-02-06 22:59 UTC (permalink / raw)
To: Viacheslav Dubeyko, linux-fsdevel, linux-mm, bpf
Cc: Slava.Dubeyko, slava, linux-kernel
Viacheslav Dubeyko <slava@dubeyko.com> writes:
> This patchset introduces initial vision of Machine Learning (ML) library
> in Linux kernel. It is an effort to define the ML library API and
> to elaborate the way of running ML models in Linux kernel.
I went looking for the documentation files ... but then I've always been
known as an optimist. That would be a nice thing to fill in.
Perhaps more important, though, would be a real user for this facility.
You must certainly have one in mind, can we see it to get a sense for
how this library is meant to be used?
Thanks,
jon
^ permalink raw reply [flat|nested] 14+ messages in thread* RE: [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel
2026-02-06 22:59 ` [RFC PATCH v1 0/4] Machine Learning (ML) library in Linux kernel Jonathan Corbet
@ 2026-02-09 20:33 ` Viacheslav Dubeyko
0 siblings, 0 replies; 14+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-09 20:33 UTC (permalink / raw)
To: linux-mm, corbet, slava, linux-fsdevel, bpf; +Cc: linux-kernel
On Fri, 2026-02-06 at 15:59 -0700, Jonathan Corbet wrote:
> Viacheslav Dubeyko <slava@dubeyko.com> writes:
>
> > This patchset introduces initial vision of Machine Learning (ML) library
> > in Linux kernel. It is an effort to define the ML library API and
> > to elaborate the way of running ML models in Linux kernel.
>
> I went looking for the documentation files ... but then I've always been
> known as an optimist. That would be a nice thing to fill in.
Yeah, I can see your pain. :) I totally agree that documentation is necessary.
This patchset is only the first small step to share and discuss with the
community. I am sharing the initial vision of the idea and API with the hope to
have the review and discussion. If the API vision makes sense and it looks good,
then it makes sense to prepare documentation. I am planning to have the
documentation after checking the whole infrastructure with a real-life use-
case(s).
>
> Perhaps more important, though, would be a real user for this facility.
> You must certainly have one in mind, can we see it to get a sense for
> how this library is meant to be used?
I believe there are multiple potential real-life use-cases. Currently, I have
implemented very simple testing driver that generates random numbers and,
potentially, some ML model can be trained on this "mess". :) But it's not very
interesting example. As a next step, I am considering to use this ML library
infrastructure for: (1) GC subsystem in LFS file systems (NILFS2, F2FS, SSDFS),
(2) ML-based DAMON extension with the goal to check the whole idea for real-life
use-cases.
So, let me make the next step and we will be able to discuss this ML library for
real-life use-cases. But the main approach is the collaboration of kernel
subsystem and ML model running in user-space.
Thanks,
Slava.
^ permalink raw reply [flat|nested] 14+ messages in thread