Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

cachefiles: notify the user daemon when looking up cookie

Fscache/CacheFiles used to serve as a local cache for a remote
networking fs. A new on-demand read mode will be introduced for
CacheFiles, which can boost the scenario where on-demand read semantics
are needed, e.g. container image distribution.

The essential difference between these two modes is seen when a cache
miss occurs: In the original mode, the netfs will fetch the data from
the remote server and then write it to the cache file; in on-demand
read mode, fetching the data and writing it into the cache is delegated
to a user daemon.

As the first step, notify the user daemon when looking up cookie. In
this case, an anonymous fd is sent to the user daemon, through which the
user daemon can write the fetched data to the cache file. Since the user
daemon may move the anonymous fd around, e.g. through dup(), an object
ID uniquely identifying the cache file is also attached.

Also add one advisory flag (FSCACHE_ADV_WANT_CACHE_SIZE) suggesting that
the cache file size shall be retrieved at runtime. This helps the
scenario where one cache file contains multiple netfs files, e.g. for
the purpose of deduplication. In this case, netfs itself has no idea the
size of the cache file, whilst the user daemon should give the hint on
it.

Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
Link: https://lore.kernel.org/r/20220509074028.74954-3-jefflexu@linux.alibaba.com
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>

authored by

Jeffle Xu and committed by
Gao Xiang
c8383054 a06fac15

+577 -15
+12
fs/cachefiles/Kconfig
··· 26 26 help 27 27 This permits error injection to be enabled in cachefiles whilst a 28 28 cache is in service. 29 + 30 + config CACHEFILES_ONDEMAND 31 + bool "Support for on-demand read" 32 + depends on CACHEFILES 33 + default n 34 + help 35 + This permits userspace to enable the cachefiles on-demand read mode. 36 + In this mode, when a cache miss occurs, responsibility for fetching 37 + the data lies with the cachefiles backend instead of with the netfs 38 + and is delegated to userspace. 39 + 40 + If unsure, say N.
+1
fs/cachefiles/Makefile
··· 16 16 xattr.o 17 17 18 18 cachefiles-$(CONFIG_CACHEFILES_ERROR_INJECTION) += error_inject.o 19 + cachefiles-$(CONFIG_CACHEFILES_ONDEMAND) += ondemand.o 19 20 20 21 obj-$(CONFIG_CACHEFILES) := cachefiles.o
+68 -13
fs/cachefiles/daemon.c
··· 75 75 { "inuse", cachefiles_daemon_inuse }, 76 76 { "secctx", cachefiles_daemon_secctx }, 77 77 { "tag", cachefiles_daemon_tag }, 78 + #ifdef CONFIG_CACHEFILES_ONDEMAND 79 + { "copen", cachefiles_ondemand_copen }, 80 + #endif 78 81 { "", NULL } 79 82 }; 80 83 ··· 111 108 INIT_LIST_HEAD(&cache->volumes); 112 109 INIT_LIST_HEAD(&cache->object_list); 113 110 spin_lock_init(&cache->object_list_lock); 111 + xa_init_flags(&cache->reqs, XA_FLAGS_ALLOC); 112 + xa_init_flags(&cache->ondemand_ids, XA_FLAGS_ALLOC1); 114 113 115 114 /* set default caching limits 116 115 * - limit at 1% free space and/or free files ··· 131 126 return 0; 132 127 } 133 128 129 + static void cachefiles_flush_reqs(struct cachefiles_cache *cache) 130 + { 131 + struct xarray *xa = &cache->reqs; 132 + struct cachefiles_req *req; 133 + unsigned long index; 134 + 135 + /* 136 + * Make sure the following two operations won't be reordered. 137 + * 1) set CACHEFILES_DEAD bit 138 + * 2) flush requests in the xarray 139 + * Otherwise the request may be enqueued after xarray has been 140 + * flushed, leaving the orphan request never being completed. 141 + * 142 + * CPU 1 CPU 2 143 + * ===== ===== 144 + * flush requests in the xarray 145 + * test CACHEFILES_DEAD bit 146 + * enqueue the request 147 + * set CACHEFILES_DEAD bit 148 + */ 149 + smp_mb(); 150 + 151 + xa_lock(xa); 152 + xa_for_each(xa, index, req) { 153 + req->error = -EIO; 154 + complete(&req->done); 155 + } 156 + xa_unlock(xa); 157 + 158 + xa_destroy(&cache->reqs); 159 + xa_destroy(&cache->ondemand_ids); 160 + } 161 + 134 162 /* 135 163 * Release a cache. 136 164 */ ··· 177 139 178 140 set_bit(CACHEFILES_DEAD, &cache->flags); 179 141 142 + if (cachefiles_in_ondemand_mode(cache)) 143 + cachefiles_flush_reqs(cache); 180 144 cachefiles_daemon_unbind(cache); 181 145 182 146 /* clean up the control file interface */ ··· 192 152 return 0; 193 153 } 194 154 195 - /* 196 - * Read the cache state. 197 - */ 198 - static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, 199 - size_t buflen, loff_t *pos) 155 + static ssize_t cachefiles_do_daemon_read(struct cachefiles_cache *cache, 156 + char __user *_buffer, size_t buflen) 200 157 { 201 - struct cachefiles_cache *cache = file->private_data; 202 158 unsigned long long b_released; 203 159 unsigned f_released; 204 160 char buffer[256]; 205 161 int n; 206 - 207 - //_enter(",,%zu,", buflen); 208 - 209 - if (!test_bit(CACHEFILES_READY, &cache->flags)) 210 - return 0; 211 162 212 163 /* check how much space the cache has */ 213 164 cachefiles_has_space(cache, 0, 0, cachefiles_has_space_check); ··· 235 204 return -EFAULT; 236 205 237 206 return n; 207 + } 208 + 209 + /* 210 + * Read the cache state. 211 + */ 212 + static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, 213 + size_t buflen, loff_t *pos) 214 + { 215 + struct cachefiles_cache *cache = file->private_data; 216 + 217 + //_enter(",,%zu,", buflen); 218 + 219 + if (!test_bit(CACHEFILES_READY, &cache->flags)) 220 + return 0; 221 + 222 + if (cachefiles_in_ondemand_mode(cache)) 223 + return cachefiles_ondemand_daemon_read(cache, _buffer, buflen); 224 + else 225 + return cachefiles_do_daemon_read(cache, _buffer, buflen); 238 226 } 239 227 240 228 /* ··· 347 297 poll_wait(file, &cache->daemon_pollwq, poll); 348 298 mask = 0; 349 299 350 - if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags)) 351 - mask |= EPOLLIN; 300 + if (cachefiles_in_ondemand_mode(cache)) { 301 + if (!xa_empty(&cache->reqs)) 302 + mask |= EPOLLIN; 303 + } else { 304 + if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags)) 305 + mask |= EPOLLIN; 306 + } 352 307 353 308 if (test_bit(CACHEFILES_CULLING, &cache->flags)) 354 309 mask |= EPOLLOUT;
+51
fs/cachefiles/internal.h
··· 15 15 #include <linux/fscache-cache.h> 16 16 #include <linux/cred.h> 17 17 #include <linux/security.h> 18 + #include <linux/xarray.h> 19 + #include <linux/cachefiles.h> 18 20 19 21 #define CACHEFILES_DIO_BLOCK_SIZE 4096 20 22 ··· 60 58 enum cachefiles_content content_info:8; /* Info about content presence */ 61 59 unsigned long flags; 62 60 #define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Have an unlinked tmpfile */ 61 + #ifdef CONFIG_CACHEFILES_ONDEMAND 62 + int ondemand_id; 63 + #endif 63 64 }; 65 + 66 + #define CACHEFILES_ONDEMAND_ID_CLOSED -1 64 67 65 68 /* 66 69 * Cache files cache definition ··· 105 98 #define CACHEFILES_DEAD 1 /* T if cache dead */ 106 99 #define CACHEFILES_CULLING 2 /* T if cull engaged */ 107 100 #define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */ 101 + #define CACHEFILES_ONDEMAND_MODE 4 /* T if in on-demand read mode */ 108 102 char *rootdirname; /* name of cache root directory */ 109 103 char *secctx; /* LSM security context */ 110 104 char *tag; /* cache binding tag */ 105 + struct xarray reqs; /* xarray of pending on-demand requests */ 106 + struct xarray ondemand_ids; /* xarray for ondemand_id allocation */ 107 + u32 ondemand_id_next; 111 108 }; 109 + 110 + static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache) 111 + { 112 + return IS_ENABLED(CONFIG_CACHEFILES_ONDEMAND) && 113 + test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags); 114 + } 115 + 116 + struct cachefiles_req { 117 + struct cachefiles_object *object; 118 + struct completion done; 119 + int error; 120 + struct cachefiles_msg msg; 121 + }; 122 + 123 + #define CACHEFILES_REQ_NEW XA_MARK_1 112 124 113 125 #include <trace/events/cachefiles.h> 114 126 ··· 275 249 extern struct file *cachefiles_create_tmpfile(struct cachefiles_object *object); 276 250 extern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache, 277 251 struct cachefiles_object *object); 252 + 253 + /* 254 + * ondemand.c 255 + */ 256 + #ifdef CONFIG_CACHEFILES_ONDEMAND 257 + extern ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, 258 + char __user *_buffer, size_t buflen); 259 + 260 + extern int cachefiles_ondemand_copen(struct cachefiles_cache *cache, 261 + char *args); 262 + 263 + extern int cachefiles_ondemand_init_object(struct cachefiles_object *object); 264 + 265 + #else 266 + static inline ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, 267 + char __user *_buffer, size_t buflen) 268 + { 269 + return -EOPNOTSUPP; 270 + } 271 + 272 + static inline int cachefiles_ondemand_init_object(struct cachefiles_object *object) 273 + { 274 + return 0; 275 + } 276 + #endif 278 277 279 278 /* 280 279 * security.c
+14 -2
fs/cachefiles/namei.c
··· 452 452 struct dentry *fan = volume->fanout[(u8)object->cookie->key_hash]; 453 453 struct file *file; 454 454 struct path path; 455 - uint64_t ni_size = object->cookie->object_size; 455 + uint64_t ni_size; 456 456 long ret; 457 457 458 - ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); 459 458 460 459 cachefiles_begin_secure(cache, &saved_cred); 461 460 ··· 479 480 file = ERR_PTR(-EBUSY); 480 481 goto out_dput; 481 482 } 483 + 484 + ret = cachefiles_ondemand_init_object(object); 485 + if (ret < 0) { 486 + file = ERR_PTR(ret); 487 + goto out_unuse; 488 + } 489 + 490 + ni_size = object->cookie->object_size; 491 + ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); 482 492 483 493 if (ni_size > 0) { 484 494 trace_cachefiles_trunc(object, d_backing_inode(path.dentry), 0, ni_size, ··· 593 585 goto error_fput; 594 586 } 595 587 _debug("file -> %pd positive", dentry); 588 + 589 + ret = cachefiles_ondemand_init_object(object); 590 + if (ret < 0) 591 + goto error_fput; 596 592 597 593 ret = cachefiles_check_auxdata(object, file); 598 594 if (ret < 0)
+378
fs/cachefiles/ondemand.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + #include <linux/fdtable.h> 3 + #include <linux/anon_inodes.h> 4 + #include <linux/uio.h> 5 + #include "internal.h" 6 + 7 + static int cachefiles_ondemand_fd_release(struct inode *inode, 8 + struct file *file) 9 + { 10 + struct cachefiles_object *object = file->private_data; 11 + struct cachefiles_cache *cache = object->volume->cache; 12 + int object_id = object->ondemand_id; 13 + 14 + object->ondemand_id = CACHEFILES_ONDEMAND_ID_CLOSED; 15 + xa_erase(&cache->ondemand_ids, object_id); 16 + cachefiles_put_object(object, cachefiles_obj_put_ondemand_fd); 17 + return 0; 18 + } 19 + 20 + static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, 21 + struct iov_iter *iter) 22 + { 23 + struct cachefiles_object *object = kiocb->ki_filp->private_data; 24 + struct cachefiles_cache *cache = object->volume->cache; 25 + struct file *file = object->file; 26 + size_t len = iter->count; 27 + loff_t pos = kiocb->ki_pos; 28 + const struct cred *saved_cred; 29 + int ret; 30 + 31 + if (!file) 32 + return -ENOBUFS; 33 + 34 + cachefiles_begin_secure(cache, &saved_cred); 35 + ret = __cachefiles_prepare_write(object, file, &pos, &len, true); 36 + cachefiles_end_secure(cache, saved_cred); 37 + if (ret < 0) 38 + return ret; 39 + 40 + ret = __cachefiles_write(object, file, pos, iter, NULL, NULL); 41 + if (!ret) 42 + ret = len; 43 + 44 + return ret; 45 + } 46 + 47 + static loff_t cachefiles_ondemand_fd_llseek(struct file *filp, loff_t pos, 48 + int whence) 49 + { 50 + struct cachefiles_object *object = filp->private_data; 51 + struct file *file = object->file; 52 + 53 + if (!file) 54 + return -ENOBUFS; 55 + 56 + return vfs_llseek(file, pos, whence); 57 + } 58 + 59 + static const struct file_operations cachefiles_ondemand_fd_fops = { 60 + .owner = THIS_MODULE, 61 + .release = cachefiles_ondemand_fd_release, 62 + .write_iter = cachefiles_ondemand_fd_write_iter, 63 + .llseek = cachefiles_ondemand_fd_llseek, 64 + }; 65 + 66 + /* 67 + * OPEN request Completion (copen) 68 + * - command: "copen <id>,<cache_size>" 69 + * <cache_size> indicates the object size if >=0, error code if negative 70 + */ 71 + int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) 72 + { 73 + struct cachefiles_req *req; 74 + struct fscache_cookie *cookie; 75 + char *pid, *psize; 76 + unsigned long id; 77 + long size; 78 + int ret; 79 + 80 + if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags)) 81 + return -EOPNOTSUPP; 82 + 83 + if (!*args) { 84 + pr_err("Empty id specified\n"); 85 + return -EINVAL; 86 + } 87 + 88 + pid = args; 89 + psize = strchr(args, ','); 90 + if (!psize) { 91 + pr_err("Cache size is not specified\n"); 92 + return -EINVAL; 93 + } 94 + 95 + *psize = 0; 96 + psize++; 97 + 98 + ret = kstrtoul(pid, 0, &id); 99 + if (ret) 100 + return ret; 101 + 102 + req = xa_erase(&cache->reqs, id); 103 + if (!req) 104 + return -EINVAL; 105 + 106 + /* fail OPEN request if copen format is invalid */ 107 + ret = kstrtol(psize, 0, &size); 108 + if (ret) { 109 + req->error = ret; 110 + goto out; 111 + } 112 + 113 + /* fail OPEN request if daemon reports an error */ 114 + if (size < 0) { 115 + if (!IS_ERR_VALUE(size)) 116 + size = -EINVAL; 117 + req->error = size; 118 + goto out; 119 + } 120 + 121 + cookie = req->object->cookie; 122 + cookie->object_size = size; 123 + if (size) 124 + clear_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags); 125 + else 126 + set_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags); 127 + 128 + out: 129 + complete(&req->done); 130 + return ret; 131 + } 132 + 133 + static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) 134 + { 135 + struct cachefiles_object *object; 136 + struct cachefiles_cache *cache; 137 + struct cachefiles_open *load; 138 + struct file *file; 139 + u32 object_id; 140 + int ret, fd; 141 + 142 + object = cachefiles_grab_object(req->object, 143 + cachefiles_obj_get_ondemand_fd); 144 + cache = object->volume->cache; 145 + 146 + ret = xa_alloc_cyclic(&cache->ondemand_ids, &object_id, NULL, 147 + XA_LIMIT(1, INT_MAX), 148 + &cache->ondemand_id_next, GFP_KERNEL); 149 + if (ret < 0) 150 + goto err; 151 + 152 + fd = get_unused_fd_flags(O_WRONLY); 153 + if (fd < 0) { 154 + ret = fd; 155 + goto err_free_id; 156 + } 157 + 158 + file = anon_inode_getfile("[cachefiles]", &cachefiles_ondemand_fd_fops, 159 + object, O_WRONLY); 160 + if (IS_ERR(file)) { 161 + ret = PTR_ERR(file); 162 + goto err_put_fd; 163 + } 164 + 165 + file->f_mode |= FMODE_PWRITE | FMODE_LSEEK; 166 + fd_install(fd, file); 167 + 168 + load = (void *)req->msg.data; 169 + load->fd = fd; 170 + req->msg.object_id = object_id; 171 + object->ondemand_id = object_id; 172 + return 0; 173 + 174 + err_put_fd: 175 + put_unused_fd(fd); 176 + err_free_id: 177 + xa_erase(&cache->ondemand_ids, object_id); 178 + err: 179 + cachefiles_put_object(object, cachefiles_obj_put_ondemand_fd); 180 + return ret; 181 + } 182 + 183 + ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, 184 + char __user *_buffer, size_t buflen) 185 + { 186 + struct cachefiles_req *req; 187 + struct cachefiles_msg *msg; 188 + unsigned long id = 0; 189 + size_t n; 190 + int ret = 0; 191 + XA_STATE(xas, &cache->reqs, 0); 192 + 193 + /* 194 + * Search for a request that has not ever been processed, to prevent 195 + * requests from being processed repeatedly. 196 + */ 197 + xa_lock(&cache->reqs); 198 + req = xas_find_marked(&xas, UINT_MAX, CACHEFILES_REQ_NEW); 199 + if (!req) { 200 + xa_unlock(&cache->reqs); 201 + return 0; 202 + } 203 + 204 + msg = &req->msg; 205 + n = msg->len; 206 + 207 + if (n > buflen) { 208 + xa_unlock(&cache->reqs); 209 + return -EMSGSIZE; 210 + } 211 + 212 + xas_clear_mark(&xas, CACHEFILES_REQ_NEW); 213 + xa_unlock(&cache->reqs); 214 + 215 + id = xas.xa_index; 216 + msg->msg_id = id; 217 + 218 + if (msg->opcode == CACHEFILES_OP_OPEN) { 219 + ret = cachefiles_ondemand_get_fd(req); 220 + if (ret) 221 + goto error; 222 + } 223 + 224 + if (copy_to_user(_buffer, msg, n) != 0) { 225 + ret = -EFAULT; 226 + goto err_put_fd; 227 + } 228 + 229 + return n; 230 + 231 + err_put_fd: 232 + if (msg->opcode == CACHEFILES_OP_OPEN) 233 + close_fd(((struct cachefiles_open *)msg->data)->fd); 234 + error: 235 + xa_erase(&cache->reqs, id); 236 + req->error = ret; 237 + complete(&req->done); 238 + return ret; 239 + } 240 + 241 + typedef int (*init_req_fn)(struct cachefiles_req *req, void *private); 242 + 243 + static int cachefiles_ondemand_send_req(struct cachefiles_object *object, 244 + enum cachefiles_opcode opcode, 245 + size_t data_len, 246 + init_req_fn init_req, 247 + void *private) 248 + { 249 + struct cachefiles_cache *cache = object->volume->cache; 250 + struct cachefiles_req *req; 251 + XA_STATE(xas, &cache->reqs, 0); 252 + int ret; 253 + 254 + if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags)) 255 + return 0; 256 + 257 + if (test_bit(CACHEFILES_DEAD, &cache->flags)) 258 + return -EIO; 259 + 260 + req = kzalloc(sizeof(*req) + data_len, GFP_KERNEL); 261 + if (!req) 262 + return -ENOMEM; 263 + 264 + req->object = object; 265 + init_completion(&req->done); 266 + req->msg.opcode = opcode; 267 + req->msg.len = sizeof(struct cachefiles_msg) + data_len; 268 + 269 + ret = init_req(req, private); 270 + if (ret) 271 + goto out; 272 + 273 + do { 274 + /* 275 + * Stop enqueuing the request when daemon is dying. The 276 + * following two operations need to be atomic as a whole. 277 + * 1) check cache state, and 278 + * 2) enqueue request if cache is alive. 279 + * Otherwise the request may be enqueued after xarray has been 280 + * flushed, leaving the orphan request never being completed. 281 + * 282 + * CPU 1 CPU 2 283 + * ===== ===== 284 + * test CACHEFILES_DEAD bit 285 + * set CACHEFILES_DEAD bit 286 + * flush requests in the xarray 287 + * enqueue the request 288 + */ 289 + xas_lock(&xas); 290 + 291 + if (test_bit(CACHEFILES_DEAD, &cache->flags)) { 292 + xas_unlock(&xas); 293 + ret = -EIO; 294 + goto out; 295 + } 296 + 297 + /* coupled with the barrier in cachefiles_flush_reqs() */ 298 + smp_mb(); 299 + 300 + xas.xa_index = 0; 301 + xas_find_marked(&xas, UINT_MAX, XA_FREE_MARK); 302 + if (xas.xa_node == XAS_RESTART) 303 + xas_set_err(&xas, -EBUSY); 304 + xas_store(&xas, req); 305 + xas_clear_mark(&xas, XA_FREE_MARK); 306 + xas_set_mark(&xas, CACHEFILES_REQ_NEW); 307 + xas_unlock(&xas); 308 + } while (xas_nomem(&xas, GFP_KERNEL)); 309 + 310 + ret = xas_error(&xas); 311 + if (ret) 312 + goto out; 313 + 314 + wake_up_all(&cache->daemon_pollwq); 315 + wait_for_completion(&req->done); 316 + ret = req->error; 317 + out: 318 + kfree(req); 319 + return ret; 320 + } 321 + 322 + static int cachefiles_ondemand_init_open_req(struct cachefiles_req *req, 323 + void *private) 324 + { 325 + struct cachefiles_object *object = req->object; 326 + struct fscache_cookie *cookie = object->cookie; 327 + struct fscache_volume *volume = object->volume->vcookie; 328 + struct cachefiles_open *load = (void *)req->msg.data; 329 + size_t volume_key_size, cookie_key_size; 330 + void *volume_key, *cookie_key; 331 + 332 + /* 333 + * Volume key is a NUL-terminated string. key[0] stores strlen() of the 334 + * string, followed by the content of the string (excluding '\0'). 335 + */ 336 + volume_key_size = volume->key[0] + 1; 337 + volume_key = volume->key + 1; 338 + 339 + /* Cookie key is binary data, which is netfs specific. */ 340 + cookie_key_size = cookie->key_len; 341 + cookie_key = fscache_get_key(cookie); 342 + 343 + if (!(object->cookie->advice & FSCACHE_ADV_WANT_CACHE_SIZE)) { 344 + pr_err("WANT_CACHE_SIZE is needed for on-demand mode\n"); 345 + return -EINVAL; 346 + } 347 + 348 + load->volume_key_size = volume_key_size; 349 + load->cookie_key_size = cookie_key_size; 350 + memcpy(load->data, volume_key, volume_key_size); 351 + memcpy(load->data + volume_key_size, cookie_key, cookie_key_size); 352 + 353 + return 0; 354 + } 355 + 356 + int cachefiles_ondemand_init_object(struct cachefiles_object *object) 357 + { 358 + struct fscache_cookie *cookie = object->cookie; 359 + struct fscache_volume *volume = object->volume->vcookie; 360 + size_t volume_key_size, cookie_key_size, data_len; 361 + 362 + /* 363 + * CacheFiles will firstly check the cache file under the root cache 364 + * directory. If the coherency check failed, it will fallback to 365 + * creating a new tmpfile as the cache file. Reuse the previously 366 + * allocated object ID if any. 367 + */ 368 + if (object->ondemand_id > 0) 369 + return 0; 370 + 371 + volume_key_size = volume->key[0] + 1; 372 + cookie_key_size = cookie->key_len; 373 + data_len = sizeof(struct cachefiles_open) + 374 + volume_key_size + cookie_key_size; 375 + 376 + return cachefiles_ondemand_send_req(object, CACHEFILES_OP_OPEN, 377 + data_len, cachefiles_ondemand_init_open_req, NULL); 378 + }
+1
include/linux/fscache.h
··· 39 39 #define FSCACHE_ADV_SINGLE_CHUNK 0x01 /* The object is a single chunk of data */ 40 40 #define FSCACHE_ADV_WRITE_CACHE 0x00 /* Do cache if written to locally */ 41 41 #define FSCACHE_ADV_WRITE_NOCACHE 0x02 /* Don't cache if written to locally */ 42 + #define FSCACHE_ADV_WANT_CACHE_SIZE 0x04 /* Retrieve cache size at runtime */ 42 43 43 44 #define FSCACHE_INVAL_DIO_WRITE 0x01 /* Invalidate due to DIO write */ 44 45
+2
include/trace/events/cachefiles.h
··· 31 31 cachefiles_obj_see_lookup_failed, 32 32 cachefiles_obj_see_withdraw_cookie, 33 33 cachefiles_obj_see_withdrawal, 34 + cachefiles_obj_get_ondemand_fd, 35 + cachefiles_obj_put_ondemand_fd, 34 36 }; 35 37 36 38 enum fscache_why_object_killed {
+50
include/uapi/linux/cachefiles.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + #ifndef _LINUX_CACHEFILES_H 3 + #define _LINUX_CACHEFILES_H 4 + 5 + #include <linux/types.h> 6 + 7 + /* 8 + * Fscache ensures that the maximum length of cookie key is 255. The volume key 9 + * is controlled by netfs, and generally no bigger than 255. 10 + */ 11 + #define CACHEFILES_MSG_MAX_SIZE 1024 12 + 13 + enum cachefiles_opcode { 14 + CACHEFILES_OP_OPEN, 15 + }; 16 + 17 + /* 18 + * Message Header 19 + * 20 + * @msg_id a unique ID identifying this message 21 + * @opcode message type, CACHEFILE_OP_* 22 + * @len message length, including message header and following data 23 + * @object_id a unique ID identifying a cache file 24 + * @data message type specific payload 25 + */ 26 + struct cachefiles_msg { 27 + __u32 msg_id; 28 + __u32 opcode; 29 + __u32 len; 30 + __u32 object_id; 31 + __u8 data[]; 32 + }; 33 + 34 + /* 35 + * @data contains the volume_key followed directly by the cookie_key. volume_key 36 + * is a NUL-terminated string; @volume_key_size indicates the size of the volume 37 + * key in bytes. cookie_key is binary data, which is netfs specific; 38 + * @cookie_key_size indicates the size of the cookie key in bytes. 39 + * 40 + * @fd identifies an anon_fd referring to the cache file. 41 + */ 42 + struct cachefiles_open { 43 + __u32 volume_key_size; 44 + __u32 cookie_key_size; 45 + __u32 fd; 46 + __u32 flags; 47 + __u8 data[]; 48 + }; 49 + 50 + #endif