summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bentele2019-08-23 12:36:09 +0200
committerManuel Bentele2019-08-23 13:36:07 +0200
commit5f754cb3ad76360a3db9ed4094077aae1dc0d559 (patch)
treebdb188125e384891be01866e637864b8fd432465
parentdoc: admin-guide: add loop block device documentation (diff)
downloadkernel-qcow2-linux-5f754cb3ad76360a3db9ed4094077aae1dc0d559.tar.gz
kernel-qcow2-linux-5f754cb3ad76360a3db9ed4094077aae1dc0d559.tar.xz
kernel-qcow2-linux-5f754cb3ad76360a3db9ed4094077aae1dc0d559.zip
doc: driver-api: add loop file format subsystem API documentation
The APIs of the file format subsystem for loop devices is documented in the reST kernel documentation format. The documentation deals with the description of the internal API of the file format subsystem to access its functionality and adds a section on how to write own loop file format drivers using the driver API of the subsystem. Signed-off-by: Manuel Bentele <development@manuel-bentele.de>
-rw-r--r--Documentation/driver-api/index.rst3
-rw-r--r--Documentation/driver-api/loop-file-fmt.rst135
-rw-r--r--drivers/block/loop/loop_file_fmt.h231
3 files changed, 365 insertions, 4 deletions
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index 6d9f2f9fe20e..10147d439f62 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -40,7 +40,8 @@ available subsections can be seen below.
mtdnand
miscellaneous
w1
- rapidio
+ loop-file-fmt
+ rapidio/index
s390-drivers
vme
80211/index
diff --git a/Documentation/driver-api/loop-file-fmt.rst b/Documentation/driver-api/loop-file-fmt.rst
new file mode 100644
index 000000000000..335fde30f364
--- /dev/null
+++ b/Documentation/driver-api/loop-file-fmt.rst
@@ -0,0 +1,135 @@
+===========================================
+Loopback block device file format subsystem
+===========================================
+
+This document outlines the file format subsystem used in the loopback block
+device module. This subsystem deals with the abstraction of direct file access
+to allow the implementation of various disk file formats. The subsystem can
+handle ...
+
+ - read
+ - write
+ - discard
+ - flush
+ - sector size
+
+... operations of a loop device.
+
+Therefore, the subsystem provides an internal API for the loop device module to
+access its functionality and exports a file format driver API to implement any
+file format driver for loop devices.
+
+
+Use the file format subsystem
+=============================
+
+At the moment, the file format subsystem is only intended to be used from the
+loopback device module to provide a specific file format implementation per
+configured loop device. Therefore, the loop device module can use the following
+internal file format API functions to set up loop file formats and access the
+file format subsystem.
+
+
+Internal subsystem API
+----------------------
+
+.. kernel-doc:: drivers/block/loop/loop_file_fmt.h
+ :functions: loop_file_fmt_alloc loop_file_fmt_free \
+ loop_file_fmt_set_lo loop_file_fmt_get_lo
+ loop_file_fmt_init loop_file_fmt_exit \
+ loop_file_fmt_read loop_file_fmt_read_aio \
+ loop_file_fmt_write loop_file_fmt_write_aio \
+ loop_file_fmt_discard loop_file_fmt_flush \
+ loop_file_fmt_sector_size loop_file_fmt_change
+
+
+Finite state machine
+--------------------
+
+To prevent a misuse of the internal file format API, the file format subsystem
+implements an finite state machine. The state machine consists of two states
+and a transition for each internal API function. The state
+*file_fmt_uninitialized* of a loop file format denotes that the file format is
+already allocated but not initialized. After the initialization, the file
+format's state is set to *file_fmt_initialized*. In this state, all IO related
+file format operations can be accessed.
+
+.. note:: If an internal API call does not succeed the file format's state \
+ does not change accordingly to its transition and remains in the \
+ original state before the API call.
+
+The entire implemented finite state machine looks like the following:
+
+.. kernel-render:: DOT
+ :alt: loop file format states
+ :caption: File format states and transitions
+
+ digraph file_fmt_states {
+ rankdir = LR;
+ node [ shape = point, label = "" ] ENTRY, EXIT;
+ node [ shape = circle, label = "file_fmt_uninitialized" ] UN;
+ node [ shape = doublecircle, label = "file_fmt_initialized" ] IN;
+ subgraph helper {
+ rank = "same";
+ ENTRY -> UN [ label = "loop_file_fmt_alloc()" ];
+ UN -> EXIT [ label = "loop_file_fmt_free()" ];
+ }
+ UN -> IN [ label = "loop_file_fmt_init()" ];
+ IN -> UN [ label = "loop_file_fmt_exit()" ];
+ IN -> IN [ label = "loop_file_fmt_read()\nloop_file_fmt_read_aio()\nloop_file_fmt_write()\n loop_file_fmt_write_aio()\nloop_file_fmt_discard()\nloop_file_fmt_flush()\nloop_file_fmt_sector_size()\nloop_file_fmt_change()" ];
+ }
+
+
+Write file format drivers
+=========================
+
+A file format driver for the loop file format subsystem is implemented as
+kernel module. In the kernel module's code, the file format driver structure is
+statically allocated and must be initialized. An example definition would look
+like::
+
+ struct loop_file_fmt_driver raw_file_fmt_driver = {
+ .name = "RAW",
+ .file_fmt_type = LO_FILE_FMT_RAW,
+ .ops = &raw_file_fmt_ops,
+ .owner = THIS_MODULE
+ };
+
+The definition assigns a *name* to the file format driver. The *file_fmt_type*
+field is set to the file format type that the driver implements. The *owner*
+specifies the driver's owner and is used to lock the kernel module of the
+driver if the file format driver is in use. The most important field of a loop
+file format driver is the specification of its implementation. Therefore, the
+*ops* field proposes all file format operations that the driver implement by
+link to a statically allocated operations structure.
+
+.. note:: All fields of the **loop_file_fmt_driver** structure must be \
+ initialized and set up accordingly, otherwise the driver does not \
+ work properly.
+
+An example of such an operations structure looks like::
+
+ struct loop_file_fmt_ops raw_file_fmt_ops = {
+ .init = NULL,
+ .exit = NULL,
+ .read = raw_file_fmt_read,
+ .write = raw_file_fmt_write,
+ .read_aio = raw_file_fmt_read_aio,
+ .write_aio = raw_file_fmt_write_aio,
+ .discard = raw_file_fmt_discard,
+ .flush = raw_file_fmt_flush,
+ .sector_size = raw_file_fmt_sector_size
+ };
+
+The operations structure consists of a bunch of functions pointers which are
+set in this example to some functions of the binary raw disk file format
+implemented in the example driver. If a function is not available in the
+driver's implementation the function pointer in the operations structure must
+be set to *NULL*.
+
+If all definitions are available and set up correctly the driver can be
+registered and later on unregistered by using the following functions exported
+by the file format subsystem:
+
+.. kernel-doc:: drivers/block/loop/loop_file_fmt.h
+ :functions: loop_file_fmt_register_driver loop_file_fmt_unregister_driver
diff --git a/drivers/block/loop/loop_file_fmt.h b/drivers/block/loop/loop_file_fmt.h
index 208c8f7cbc31..cd62dee60bf7 100644
--- a/drivers/block/loop/loop_file_fmt.h
+++ b/drivers/block/loop/loop_file_fmt.h
@@ -14,32 +14,88 @@
struct loop_file_fmt;
-/* data structure representing the file format subsystem interface */
+/**
+ * struct loop_file_fmt_ops - File format subsystem operations
+ *
+ * Data structure representing the file format subsystem interface.
+ */
struct loop_file_fmt_ops {
+ /**
+ * @init: Initialization callback function
+ */
int (*init) (struct loop_file_fmt *lo_fmt);
+
+ /**
+ * @exit: Release callback function
+ */
void (*exit) (struct loop_file_fmt *lo_fmt);
+ /**
+ * @read: Read IO callback function
+ */
int (*read) (struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+ /**
+ * @write: Write IO callback function
+ */
int (*write) (struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+ /**
+ * @read_aio: Asynchronous read IO callback function
+ */
int (*read_aio) (struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+ /**
+ * @write_aio: Asynchronous write IO callback function
+ */
int (*write_aio) (struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+ /**
+ * @discard: Discard IO callback function
+ */
int (*discard) (struct loop_file_fmt *lo_fmt,
struct request *rq);
+ /**
+ * @flush: Flush callback function
+ */
int (*flush) (struct loop_file_fmt *lo_fmt);
+ /**
+ * @sector_size: Get sector size callback function
+ */
loff_t (*sector_size) (struct loop_file_fmt *lo_fmt);
};
-/* data structure for implementing file format drivers */
+/**
+ * struct loop_file_fmt_driver - File format subsystem driver
+ *
+ * Data structure to implement file format drivers for the file format
+ * subsystem.
+ */
struct loop_file_fmt_driver {
+ /**
+ * @name: Name of the file format driver
+ */
const char *name;
+
+ /**
+ * @file_fmt_type: Loop file format type of the file format driver
+ */
const u32 file_fmt_type;
+
+ /**
+ * @ops: Driver's implemented file format operations
+ */
struct loop_file_fmt_ops *ops;
+
+ /**
+ * @ops: Owner of the file format driver
+ */
struct module *owner;
};
@@ -77,49 +133,218 @@ enum {
file_fmt_initialized
};
-/* data structure for using with the file format subsystem */
+/**
+ * struct loop_file_fmt - Loop file format
+ *
+ * Data structure to use with the file format the loop file format subsystem.
+ */
struct loop_file_fmt {
+ /**
+ * @file_fmt_type: Current type of the loop file format
+ */
u32 file_fmt_type;
+
+ /**
+ * @file_fmt_state: Current state of the loop file format
+ */
int file_fmt_state;
+
+ /**
+ * @lo: Link to a file format's loop device
+ */
struct loop_device *lo;
+
+ /**
+ * @private_data: Optional link to a file format's driver specific data
+ */
void *private_data;
};
+
/* subsystem functions for the driver implementation */
+
+/**
+ * loop_file_fmt_register_driver - Register a loop file format driver
+ * @drv: File format driver
+ *
+ * Registers the specified loop file format driver @drv by the loop file format
+ * subsystem.
+ */
extern int loop_file_fmt_register_driver(struct loop_file_fmt_driver *drv);
+
+/**
+ * loop_file_fmt_unregister_driver - Unregister a loop file format driver
+ * @drv: File format driver
+ *
+ * Unregisters the specified loop file format driver @drv from the loop file
+ * format subsystem.
+ */
extern void loop_file_fmt_unregister_driver(struct loop_file_fmt_driver *drv);
+
/* subsystem functions for subsystem usage */
+
+/**
+ * loop_file_fmt_alloc - Allocate a loop file format
+ *
+ * Dynamically allocates a loop file format and returns a pointer to the
+ * created loop file format.
+ */
extern struct loop_file_fmt *loop_file_fmt_alloc(void);
+
+/**
+ * loop_file_fmt_free - Free an allocated loop file format
+ * @lo_fmt: Loop file format
+ *
+ * Frees the already allocated loop file format @lo_fmt.
+ */
extern void loop_file_fmt_free(struct loop_file_fmt *lo_fmt);
+/**
+ * loop_file_fmt_set_lo - Set the loop file format's loop device
+ * @lo_fmt: Loop file format
+ * @lo: Loop device
+ *
+ * The link to the loop device @lo is set in the loop file format @lo_fmt.
+ */
extern int loop_file_fmt_set_lo(struct loop_file_fmt *lo_fmt,
struct loop_device *lo);
+
+/**
+ * loop_file_fmt_get_lo - Get the loop file format's loop device
+ * @lo_fmt: Loop file format
+ *
+ * Returns a pointer to the loop device of the loop file format @lo_fmt.
+ */
extern struct loop_device *loop_file_fmt_get_lo(struct loop_file_fmt *lo_fmt);
+/**
+ * loop_file_fmt_init - Initialize a loop file format
+ * @lo_fmt: Loop file format
+ * @file_fmt_type: Type of the file format
+ *
+ * Initializes the specified loop file format @lo_fmt and sets up the correct
+ * file format type @file_fmt_type. Depending on @file_fmt_type, the correct
+ * loop file format driver is loaded in the subsystems backend. If no loop file
+ * format driver for the specified file format is available an error is
+ * returned.
+ */
extern int loop_file_fmt_init(struct loop_file_fmt *lo_fmt,
u32 file_fmt_type);
+
+/**
+ * loop_file_fmt_exit - Release a loop file format
+ * @lo_fmt: Loop file format
+ *
+ * Releases the specified loop file format @lo_fmt and all its resources.
+ */
extern void loop_file_fmt_exit(struct loop_file_fmt *lo_fmt);
+/**
+ * loop_file_fmt_read - Read IO from a loop file format
+ * @lo_fmt: Loop file format
+ * @rq: IO Request
+ *
+ * Reads IO from the file format's loop device by sending the IO read request
+ * @rq to the loop file format subsystem. The subsystem calls the registered
+ * callback function of the suitable loop file format driver.
+ */
extern int loop_file_fmt_read(struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+/**
+ * loop_file_fmt_read_aio - Read IO from a loop file format asynchronously
+ * @lo_fmt: Loop file format
+ * @rq: IO Request
+ *
+ * Reads IO from the file format's loop device asynchronously by sending the
+ * IO read aio request @rq to the loop file format subsystem. The subsystem
+ * calls the registered callback function of the suitable loop file format
+ * driver.
+ */
extern int loop_file_fmt_read_aio(struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+/**
+ * loop_file_fmt_write - Write IO to a loop file format
+ * @lo_fmt: Loop file format
+ * @rq: IO Request
+ *
+ * Write IO to the file format's loop device by sending the IO write request
+ * @rq to the loop file format subsystem. The subsystem calls the registered
+ * callback function of the suitable loop file format driver.
+ */
extern int loop_file_fmt_write(struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+/**
+ * loop_file_fmt_write_aio - Write IO to a loop file format asynchronously
+ * @lo_fmt: Loop file format
+ * @rq: IO Request
+ *
+ * Write IO to the file format's loop device asynchronously by sending the
+ * IO write aio request @rq to the loop file format subsystem. The subsystem
+ * calls the registered callback function of the suitable loop file format
+ * driver.
+ */
extern int loop_file_fmt_write_aio(struct loop_file_fmt *lo_fmt,
struct request *rq);
+
+/**
+ * loop_file_fmt_discard - Discard IO on a loop file format
+ * @lo_fmt: Loop file format
+ * @rq: IO Request
+ *
+ * Discard IO on the file format's loop device by sending the IO discard
+ * request @rq to the loop file format subsystem. The subsystem calls the
+ * registered callback function of the suitable loop file format driver.
+ */
extern int loop_file_fmt_discard(struct loop_file_fmt *lo_fmt,
struct request *rq);
+/**
+ * loop_file_fmt_flush - Flush a loop file format
+ * @lo_fmt: Loop file format
+ *
+ * Flush the file format's loop device by calling the registered callback
+ * function of the suitable loop file format driver.
+ */
extern int loop_file_fmt_flush(struct loop_file_fmt *lo_fmt);
+/**
+ * loop_file_fmt_sector_size - Get sector size of a loop file format
+ * @lo_fmt: Loop file format
+ *
+ * Returns the physical sector size of the loop file format's loop device.
+ * If the loop file format implements a sparse disk image format, then this
+ * function returns the virtual sector size.
+ */
extern loff_t loop_file_fmt_sector_size(struct loop_file_fmt *lo_fmt);
+/**
+ * loop_file_fmt_change - Change the loop file format's type
+ * @lo_fmt: Loop file format
+ * @file_fmt_type_new: Loop file format type
+ *
+ * Changes the file format type of the already initialized loop file format
+ * @lo_fmt. Therefore, the function releases the old file format and frees all
+ * of its resources before the loop file format @lo_fmt is initialized and set
+ * up with the new file format @file_fmt_type_new.
+ */
extern int loop_file_fmt_change(struct loop_file_fmt *lo_fmt,
u32 file_fmt_type_new);
+
/* helper functions of the subsystem */
+
+/**
+ * loop_file_fmt_print_type - Convert file format type to string
+ * @file_fmt_type: Loop file format type
+ * @file_fmt_name: Loop file format type string
+ *
+ * Converts the specified numeric @file_fmt_type value into a human readable
+ * string stating the file format as string in @file_fmt_name.
+ */
extern ssize_t loop_file_fmt_print_type(u32 file_fmt_type,
char *file_fmt_name);