^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) .. SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) Asynchronous Operations Handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) By: David Howells <dhowells@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) .. Contents:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) (*) Overview.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) (*) Operation record initialisation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) (*) Parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) (*) Procedure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) (*) Asynchronous callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) Overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) FS-Cache has an asynchronous operations handling facility that it uses for its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) data storage and retrieval routines. Its operations are represented by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) fscache_operation structs, though these are usually embedded into some other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) This facility is available to and expected to be used by the cache backends,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) and FS-Cache will create operations and pass them off to the appropriate cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) backend for completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) To make use of this facility, <linux/fscache-cache.h> should be #included.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) Operation Record Initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ===============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) An operation is recorded in an fscache_operation struct::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct fscache_operation {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct work_struct fast_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct slow_work slow_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) fscache_operation_processor_t processor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) Someone wanting to issue an operation should allocate something with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct embedded in it. They should initialise it by calling::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void fscache_operation_init(struct fscache_operation *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) fscache_operation_release_t release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) with the operation to be initialised and the release function to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) The op->flags parameter should be set to indicate the CPU time provision and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) the exclusivity (see the Parameters section).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) The op->fast_work, op->slow_work and op->processor flags should be set as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) appropriate for the CPU time provision (see the Parameters section).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) FSCACHE_OP_WAITING may be set in op->flags prior to each submission of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) operation and waited for afterwards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) Parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ==========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) There are a number of parameters that can be set in the operation record's flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) parameter. There are three options for the provision of CPU time in these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) operations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) (1) The operation may be done synchronously (FSCACHE_OP_MYTHREAD). A thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) may decide it wants to handle an operation itself without deferring it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) another thread.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) This is, for example, used in read operations for calling readpages() on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) the backing filesystem in CacheFiles. Although readpages() does an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) asynchronous data fetch, the determination of whether pages exist is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) synchronously - and the netfs does not proceed until this has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) determined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) If this option is to be used, FSCACHE_OP_WAITING must be set in op->flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) before submitting the operation, and the operating thread must wait for it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) to be cleared before proceeding::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) (2) The operation may be fast asynchronous (FSCACHE_OP_FAST), in which case it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) will be given to keventd to process. Such an operation is not permitted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) to sleep on I/O.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) This is, for example, used by CacheFiles to copy data from a backing fs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) page to a netfs page after the backing fs has read the page in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) If this option is used, op->fast_work and op->processor must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) initialised before submitting the operation::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) INIT_WORK(&op->fast_work, do_some_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) (3) The operation may be slow asynchronous (FSCACHE_OP_SLOW), in which case it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) will be given to the slow work facility to process. Such an operation is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) permitted to sleep on I/O.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) This is, for example, used by FS-Cache to handle background writes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pages that have just been fetched from a remote server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) If this option is used, op->slow_work and op->processor must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) initialised before submitting the operation::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) fscache_operation_init_slow(op, processor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) Furthermore, operations may be one of two types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) (1) Exclusive (FSCACHE_OP_EXCLUSIVE). Operations of this type may not run in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) conjunction with any other operation on the object being operated upon.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) An example of this is the attribute change operation, in which the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) being written to may need truncation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (2) Shareable. Operations of this type may be running simultaneously. It's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) up to the operation implementation to prevent interference between other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) operations running at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) Procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) =========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) Operations are used through the following procedure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) (1) The submitting thread must allocate the operation and initialise it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) itself. Normally this would be part of a more specific structure with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) generic op embedded within.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) (2) The submitting thread must then submit the operation for processing using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) one of the following two functions::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int fscache_submit_op(struct fscache_object *object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct fscache_operation *op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int fscache_submit_exclusive_op(struct fscache_object *object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct fscache_operation *op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) The first function should be used to submit non-exclusive ops and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) second to submit exclusive ones. The caller must still set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) FSCACHE_OP_EXCLUSIVE flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) If successful, both functions will assign the operation to the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) object and return 0. -ENOBUFS will be returned if the object specified is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) permanently unavailable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) The operation manager will defer operations on an object that is still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) undergoing lookup or creation. The operation will also be deferred if an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) operation of conflicting exclusivity is in progress on the object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) If the operation is asynchronous, the manager will retain a reference to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) it, so the caller should put their reference to it by passing it to::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) void fscache_put_operation(struct fscache_operation *op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (3) If the submitting thread wants to do the work itself, and has marked the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) operation with FSCACHE_OP_MYTHREAD, then it should monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) FSCACHE_OP_WAITING as described above and check the state of the object if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) necessary (the object might have died while the thread was waiting).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) When it has finished doing its processing, it should call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) fscache_op_complete() and fscache_put_operation() on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) (4) The operation holds an effective lock upon the object, preventing other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) exclusive ops conflicting until it is released. The operation can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) enqueued for further immediate asynchronous processing by adjusting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) CPU time provisioning option if necessary, eg::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) op->flags &= ~FSCACHE_OP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) op->flags |= ~FSCACHE_OP_FAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) and calling::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) void fscache_enqueue_operation(struct fscache_operation *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) This can be used to allow other things to have use of the worker thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) pools.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) Asynchronous Callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) =====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) When used in asynchronous mode, the worker thread pool will invoke the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) processor method with a pointer to the operation. This should then get at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) container struct by using container_of()::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void fscache_write_op(struct fscache_operation *_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct fscache_storage *op =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) container_of(_op, struct fscache_storage, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) The caller holds a reference on the operation, and will invoke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) fscache_put_operation() when the processor function returns. The processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) function is at liberty to call fscache_enqueue_operation() or to take extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) references.