| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * kernfs.h - pseudo filesystem decoupled from vfs locking |
|---|
| 3 | | - * |
|---|
| 4 | | - * This file is released under the GPLv2. |
|---|
| 5 | 4 | */ |
|---|
| 6 | 5 | |
|---|
| 7 | 6 | #ifndef __LINUX_KERNFS_H |
|---|
| .. | .. |
|---|
| 27 | 26 | struct super_block; |
|---|
| 28 | 27 | struct file_system_type; |
|---|
| 29 | 28 | struct poll_table_struct; |
|---|
| 29 | +struct fs_context; |
|---|
| 30 | 30 | |
|---|
| 31 | +struct kernfs_fs_context; |
|---|
| 31 | 32 | struct kernfs_open_node; |
|---|
| 32 | 33 | struct kernfs_iattrs; |
|---|
| 33 | 34 | |
|---|
| .. | .. |
|---|
| 37 | 38 | KERNFS_LINK = 0x0004, |
|---|
| 38 | 39 | }; |
|---|
| 39 | 40 | |
|---|
| 40 | | -#define KERNFS_TYPE_MASK 0x000f |
|---|
| 41 | | -#define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK |
|---|
| 41 | +#define KERNFS_TYPE_MASK 0x000f |
|---|
| 42 | +#define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK |
|---|
| 43 | +#define KERNFS_MAX_USER_XATTRS 128 |
|---|
| 44 | +#define KERNFS_USER_XATTR_SIZE_LIMIT (128 << 10) |
|---|
| 42 | 45 | |
|---|
| 43 | 46 | enum kernfs_node_flag { |
|---|
| 44 | 47 | KERNFS_ACTIVATED = 0x0010, |
|---|
| .. | .. |
|---|
| 63 | 66 | KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001, |
|---|
| 64 | 67 | |
|---|
| 65 | 68 | /* |
|---|
| 66 | | - * For regular flies, if the opener has CAP_DAC_OVERRIDE, open(2) |
|---|
| 69 | + * For regular files, if the opener has CAP_DAC_OVERRIDE, open(2) |
|---|
| 67 | 70 | * succeeds regardless of the RW permissions. sysfs had an extra |
|---|
| 68 | 71 | * layer of enforcement where open(2) fails with -EACCES regardless |
|---|
| 69 | 72 | * of CAP_DAC_OVERRIDE if the permission doesn't have the |
|---|
| .. | .. |
|---|
| 78 | 81 | * fhandle to access nodes of the fs. |
|---|
| 79 | 82 | */ |
|---|
| 80 | 83 | KERNFS_ROOT_SUPPORT_EXPORTOP = 0x0004, |
|---|
| 84 | + |
|---|
| 85 | + /* |
|---|
| 86 | + * Support user xattrs to be written to nodes rooted at this root. |
|---|
| 87 | + */ |
|---|
| 88 | + KERNFS_ROOT_SUPPORT_USER_XATTR = 0x0008, |
|---|
| 81 | 89 | }; |
|---|
| 82 | 90 | |
|---|
| 83 | 91 | /* type-specific structures for kernfs_node union members */ |
|---|
| .. | .. |
|---|
| 102 | 110 | struct kernfs_open_node *open; |
|---|
| 103 | 111 | loff_t size; |
|---|
| 104 | 112 | struct kernfs_node *notify_next; /* for kernfs_notify() */ |
|---|
| 105 | | -}; |
|---|
| 106 | | - |
|---|
| 107 | | -/* represent a kernfs node */ |
|---|
| 108 | | -union kernfs_node_id { |
|---|
| 109 | | - struct { |
|---|
| 110 | | - /* |
|---|
| 111 | | - * blktrace will export this struct as a simplified 'struct |
|---|
| 112 | | - * fid' (which is a big data struction), so userspace can use |
|---|
| 113 | | - * it to find kernfs node. The layout must match the first two |
|---|
| 114 | | - * fields of 'struct fid' exactly. |
|---|
| 115 | | - */ |
|---|
| 116 | | - u32 ino; |
|---|
| 117 | | - u32 generation; |
|---|
| 118 | | - }; |
|---|
| 119 | | - u64 id; |
|---|
| 120 | 113 | }; |
|---|
| 121 | 114 | |
|---|
| 122 | 115 | /* |
|---|
| .. | .. |
|---|
| 155 | 148 | |
|---|
| 156 | 149 | void *priv; |
|---|
| 157 | 150 | |
|---|
| 158 | | - union kernfs_node_id id; |
|---|
| 151 | + /* |
|---|
| 152 | + * 64bit unique ID. On 64bit ino setups, id is the ino. On 32bit, |
|---|
| 153 | + * the low 32bits are ino and upper generation. |
|---|
| 154 | + */ |
|---|
| 155 | + u64 id; |
|---|
| 156 | + |
|---|
| 159 | 157 | unsigned short flags; |
|---|
| 160 | 158 | umode_t mode; |
|---|
| 161 | 159 | struct kernfs_iattrs *iattr; |
|---|
| 160 | + |
|---|
| 161 | + ANDROID_KABI_RESERVE(1); |
|---|
| 162 | 162 | }; |
|---|
| 163 | 163 | |
|---|
| 164 | 164 | /* |
|---|
| .. | .. |
|---|
| 169 | 169 | * kernfs_node parameter. |
|---|
| 170 | 170 | */ |
|---|
| 171 | 171 | struct kernfs_syscall_ops { |
|---|
| 172 | | - int (*remount_fs)(struct kernfs_root *root, int *flags, char *data); |
|---|
| 173 | 172 | int (*show_options)(struct seq_file *sf, struct kernfs_root *root); |
|---|
| 174 | 173 | |
|---|
| 175 | 174 | int (*mkdir)(struct kernfs_node *parent, const char *name, |
|---|
| .. | .. |
|---|
| 193 | 192 | |
|---|
| 194 | 193 | /* private fields, do not use outside kernfs proper */ |
|---|
| 195 | 194 | struct idr ino_idr; |
|---|
| 196 | | - u32 last_ino; |
|---|
| 197 | | - u32 next_generation; |
|---|
| 195 | + u32 last_id_lowbits; |
|---|
| 196 | + u32 id_highbits; |
|---|
| 198 | 197 | struct kernfs_syscall_ops *syscall_ops; |
|---|
| 199 | 198 | |
|---|
| 200 | 199 | /* list of kernfs_super_info of this root, protected by kernfs_mutex */ |
|---|
| 201 | 200 | struct list_head supers; |
|---|
| 202 | 201 | |
|---|
| 203 | 202 | wait_queue_head_t deactivate_waitq; |
|---|
| 203 | + |
|---|
| 204 | + ANDROID_KABI_RESERVE(1); |
|---|
| 204 | 205 | }; |
|---|
| 205 | 206 | |
|---|
| 206 | 207 | struct kernfs_open_file { |
|---|
| .. | .. |
|---|
| 221 | 222 | bool mmapped:1; |
|---|
| 222 | 223 | bool released:1; |
|---|
| 223 | 224 | const struct vm_operations_struct *vm_ops; |
|---|
| 225 | + |
|---|
| 226 | + ANDROID_KABI_RESERVE(1); |
|---|
| 224 | 227 | }; |
|---|
| 225 | 228 | |
|---|
| 226 | 229 | struct kernfs_ops { |
|---|
| .. | .. |
|---|
| 282 | 285 | ANDROID_KABI_RESERVE(2); |
|---|
| 283 | 286 | }; |
|---|
| 284 | 287 | |
|---|
| 288 | +/* |
|---|
| 289 | + * The kernfs superblock creation/mount parameter context. |
|---|
| 290 | + */ |
|---|
| 291 | +struct kernfs_fs_context { |
|---|
| 292 | + struct kernfs_root *root; /* Root of the hierarchy being mounted */ |
|---|
| 293 | + void *ns_tag; /* Namespace tag of the mount (or NULL) */ |
|---|
| 294 | + unsigned long magic; /* File system specific magic number */ |
|---|
| 295 | + |
|---|
| 296 | + /* The following are set/used by kernfs_mount() */ |
|---|
| 297 | + bool new_sb_created; /* Set to T if we allocated a new sb */ |
|---|
| 298 | +}; |
|---|
| 299 | + |
|---|
| 285 | 300 | #ifdef CONFIG_KERNFS |
|---|
| 286 | 301 | |
|---|
| 287 | 302 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) |
|---|
| 288 | 303 | { |
|---|
| 289 | 304 | return kn->flags & KERNFS_TYPE_MASK; |
|---|
| 305 | +} |
|---|
| 306 | + |
|---|
| 307 | +static inline ino_t kernfs_id_ino(u64 id) |
|---|
| 308 | +{ |
|---|
| 309 | + /* id is ino if ino_t is 64bit; otherwise, low 32bits */ |
|---|
| 310 | + if (sizeof(ino_t) >= sizeof(u64)) |
|---|
| 311 | + return id; |
|---|
| 312 | + else |
|---|
| 313 | + return (u32)id; |
|---|
| 314 | +} |
|---|
| 315 | + |
|---|
| 316 | +static inline u32 kernfs_id_gen(u64 id) |
|---|
| 317 | +{ |
|---|
| 318 | + /* gen is fixed at 1 if ino_t is 64bit; otherwise, high 32bits */ |
|---|
| 319 | + if (sizeof(ino_t) >= sizeof(u64)) |
|---|
| 320 | + return 1; |
|---|
| 321 | + else |
|---|
| 322 | + return id >> 32; |
|---|
| 323 | +} |
|---|
| 324 | + |
|---|
| 325 | +static inline ino_t kernfs_ino(struct kernfs_node *kn) |
|---|
| 326 | +{ |
|---|
| 327 | + return kernfs_id_ino(kn->id); |
|---|
| 328 | +} |
|---|
| 329 | + |
|---|
| 330 | +static inline ino_t kernfs_gen(struct kernfs_node *kn) |
|---|
| 331 | +{ |
|---|
| 332 | + return kernfs_id_gen(kn->id); |
|---|
| 290 | 333 | } |
|---|
| 291 | 334 | |
|---|
| 292 | 335 | /** |
|---|
| .. | .. |
|---|
| 368 | 411 | struct poll_table_struct *pt); |
|---|
| 369 | 412 | void kernfs_notify(struct kernfs_node *kn); |
|---|
| 370 | 413 | |
|---|
| 414 | +int kernfs_xattr_get(struct kernfs_node *kn, const char *name, |
|---|
| 415 | + void *value, size_t size); |
|---|
| 416 | +int kernfs_xattr_set(struct kernfs_node *kn, const char *name, |
|---|
| 417 | + const void *value, size_t size, int flags); |
|---|
| 418 | + |
|---|
| 371 | 419 | const void *kernfs_super_ns(struct super_block *sb); |
|---|
| 372 | | -struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, |
|---|
| 373 | | - struct kernfs_root *root, unsigned long magic, |
|---|
| 374 | | - bool *new_sb_created, const void *ns); |
|---|
| 420 | +int kernfs_get_tree(struct fs_context *fc); |
|---|
| 421 | +void kernfs_free_fs_context(struct fs_context *fc); |
|---|
| 375 | 422 | void kernfs_kill_sb(struct super_block *sb); |
|---|
| 376 | | -struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns); |
|---|
| 377 | 423 | |
|---|
| 378 | 424 | void kernfs_init(void); |
|---|
| 379 | 425 | |
|---|
| 380 | | -struct kernfs_node *kernfs_get_node_by_id(struct kernfs_root *root, |
|---|
| 381 | | - const union kernfs_node_id *id); |
|---|
| 426 | +struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root, |
|---|
| 427 | + u64 id); |
|---|
| 382 | 428 | #else /* CONFIG_KERNFS */ |
|---|
| 383 | 429 | |
|---|
| 384 | 430 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) |
|---|
| .. | .. |
|---|
| 472 | 518 | |
|---|
| 473 | 519 | static inline void kernfs_notify(struct kernfs_node *kn) { } |
|---|
| 474 | 520 | |
|---|
| 521 | +static inline int kernfs_xattr_get(struct kernfs_node *kn, const char *name, |
|---|
| 522 | + void *value, size_t size) |
|---|
| 523 | +{ return -ENOSYS; } |
|---|
| 524 | + |
|---|
| 525 | +static inline int kernfs_xattr_set(struct kernfs_node *kn, const char *name, |
|---|
| 526 | + const void *value, size_t size, int flags) |
|---|
| 527 | +{ return -ENOSYS; } |
|---|
| 528 | + |
|---|
| 475 | 529 | static inline const void *kernfs_super_ns(struct super_block *sb) |
|---|
| 476 | 530 | { return NULL; } |
|---|
| 477 | 531 | |
|---|
| 478 | | -static inline struct dentry * |
|---|
| 479 | | -kernfs_mount_ns(struct file_system_type *fs_type, int flags, |
|---|
| 480 | | - struct kernfs_root *root, unsigned long magic, |
|---|
| 481 | | - bool *new_sb_created, const void *ns) |
|---|
| 482 | | -{ return ERR_PTR(-ENOSYS); } |
|---|
| 532 | +static inline int kernfs_get_tree(struct fs_context *fc) |
|---|
| 533 | +{ return -ENOSYS; } |
|---|
| 534 | + |
|---|
| 535 | +static inline void kernfs_free_fs_context(struct fs_context *fc) { } |
|---|
| 483 | 536 | |
|---|
| 484 | 537 | static inline void kernfs_kill_sb(struct super_block *sb) { } |
|---|
| 485 | 538 | |
|---|
| .. | .. |
|---|
| 493 | 546 | * @buf: buffer to copy @kn's name into |
|---|
| 494 | 547 | * @buflen: size of @buf |
|---|
| 495 | 548 | * |
|---|
| 496 | | - * Builds and returns the full path of @kn in @buf of @buflen bytes. The |
|---|
| 497 | | - * path is built from the end of @buf so the returned pointer usually |
|---|
| 498 | | - * doesn't match @buf. If @buf isn't long enough, @buf is nul terminated |
|---|
| 499 | | - * and %NULL is returned. |
|---|
| 549 | + * If @kn is NULL result will be "(null)". |
|---|
| 550 | + * |
|---|
| 551 | + * Returns the length of the full path. If the full length is equal to or |
|---|
| 552 | + * greater than @buflen, @buf contains the truncated path with the trailing |
|---|
| 553 | + * '\0'. On error, -errno is returned. |
|---|
| 500 | 554 | */ |
|---|
| 501 | 555 | static inline int kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen) |
|---|
| 502 | 556 | { |
|---|
| .. | .. |
|---|
| 559 | 613 | const char *new_name) |
|---|
| 560 | 614 | { |
|---|
| 561 | 615 | return kernfs_rename_ns(kn, new_parent, new_name, NULL); |
|---|
| 562 | | -} |
|---|
| 563 | | - |
|---|
| 564 | | -static inline struct dentry * |
|---|
| 565 | | -kernfs_mount(struct file_system_type *fs_type, int flags, |
|---|
| 566 | | - struct kernfs_root *root, unsigned long magic, |
|---|
| 567 | | - bool *new_sb_created) |
|---|
| 568 | | -{ |
|---|
| 569 | | - return kernfs_mount_ns(fs_type, flags, root, |
|---|
| 570 | | - magic, new_sb_created, NULL); |
|---|
| 571 | 616 | } |
|---|
| 572 | 617 | |
|---|
| 573 | 618 | #endif /* __LINUX_KERNFS_H */ |
|---|