at master 7.2 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_FS_SUPER_H 3#define _LINUX_FS_SUPER_H 4 5#include <linux/fs/super_types.h> 6#include <linux/unicode.h> 7 8/* 9 * These are internal functions, please use sb_start_{write,pagefault,intwrite} 10 * instead. 11 */ 12static inline void __sb_end_write(struct super_block *sb, int level) 13{ 14 percpu_up_read(sb->s_writers.rw_sem + level - 1); 15} 16 17static inline void __sb_start_write(struct super_block *sb, int level) 18{ 19 percpu_down_read_freezable(sb->s_writers.rw_sem + level - 1, true); 20} 21 22static inline bool __sb_start_write_trylock(struct super_block *sb, int level) 23{ 24 return percpu_down_read_trylock(sb->s_writers.rw_sem + level - 1); 25} 26 27#define __sb_writers_acquired(sb, lev) \ 28 percpu_rwsem_acquire(&(sb)->s_writers.rw_sem[(lev) - 1], 1, _THIS_IP_) 29#define __sb_writers_release(sb, lev) \ 30 percpu_rwsem_release(&(sb)->s_writers.rw_sem[(lev) - 1], _THIS_IP_) 31 32/** 33 * __sb_write_started - check if sb freeze level is held 34 * @sb: the super we write to 35 * @level: the freeze level 36 * 37 * * > 0 - sb freeze level is held 38 * * 0 - sb freeze level is not held 39 * * < 0 - !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN 40 */ 41static inline int __sb_write_started(const struct super_block *sb, int level) 42{ 43 return lockdep_is_held_type(sb->s_writers.rw_sem + level - 1, 1); 44} 45 46/** 47 * sb_write_started - check if SB_FREEZE_WRITE is held 48 * @sb: the super we write to 49 * 50 * May be false positive with !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN. 51 */ 52static inline bool sb_write_started(const struct super_block *sb) 53{ 54 return __sb_write_started(sb, SB_FREEZE_WRITE); 55} 56 57/** 58 * sb_write_not_started - check if SB_FREEZE_WRITE is not held 59 * @sb: the super we write to 60 * 61 * May be false positive with !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN. 62 */ 63static inline bool sb_write_not_started(const struct super_block *sb) 64{ 65 return __sb_write_started(sb, SB_FREEZE_WRITE) <= 0; 66} 67 68/** 69 * sb_end_write - drop write access to a superblock 70 * @sb: the super we wrote to 71 * 72 * Decrement number of writers to the filesystem. Wake up possible waiters 73 * wanting to freeze the filesystem. 74 */ 75static inline void sb_end_write(struct super_block *sb) 76{ 77 __sb_end_write(sb, SB_FREEZE_WRITE); 78} 79 80/** 81 * sb_end_pagefault - drop write access to a superblock from a page fault 82 * @sb: the super we wrote to 83 * 84 * Decrement number of processes handling write page fault to the filesystem. 85 * Wake up possible waiters wanting to freeze the filesystem. 86 */ 87static inline void sb_end_pagefault(struct super_block *sb) 88{ 89 __sb_end_write(sb, SB_FREEZE_PAGEFAULT); 90} 91 92/** 93 * sb_end_intwrite - drop write access to a superblock for internal fs purposes 94 * @sb: the super we wrote to 95 * 96 * Decrement fs-internal number of writers to the filesystem. Wake up possible 97 * waiters wanting to freeze the filesystem. 98 */ 99static inline void sb_end_intwrite(struct super_block *sb) 100{ 101 __sb_end_write(sb, SB_FREEZE_FS); 102} 103 104/** 105 * sb_start_write - get write access to a superblock 106 * @sb: the super we write to 107 * 108 * When a process wants to write data or metadata to a file system (i.e. dirty 109 * a page or an inode), it should embed the operation in a sb_start_write() - 110 * sb_end_write() pair to get exclusion against file system freezing. This 111 * function increments number of writers preventing freezing. If the file 112 * system is already frozen, the function waits until the file system is 113 * thawed. 114 * 115 * Since freeze protection behaves as a lock, users have to preserve 116 * ordering of freeze protection and other filesystem locks. Generally, 117 * freeze protection should be the outermost lock. In particular, we have: 118 * 119 * sb_start_write 120 * -> i_rwsem (write path, truncate, directory ops, ...) 121 * -> s_umount (freeze_super, thaw_super) 122 */ 123static inline void sb_start_write(struct super_block *sb) 124{ 125 __sb_start_write(sb, SB_FREEZE_WRITE); 126} 127 128DEFINE_GUARD(super_write, 129 struct super_block *, 130 sb_start_write(_T), 131 sb_end_write(_T)) 132 133static inline bool sb_start_write_trylock(struct super_block *sb) 134{ 135 return __sb_start_write_trylock(sb, SB_FREEZE_WRITE); 136} 137 138/** 139 * sb_start_pagefault - get write access to a superblock from a page fault 140 * @sb: the super we write to 141 * 142 * When a process starts handling write page fault, it should embed the 143 * operation into sb_start_pagefault() - sb_end_pagefault() pair to get 144 * exclusion against file system freezing. This is needed since the page fault 145 * is going to dirty a page. This function increments number of running page 146 * faults preventing freezing. If the file system is already frozen, the 147 * function waits until the file system is thawed. 148 * 149 * Since page fault freeze protection behaves as a lock, users have to preserve 150 * ordering of freeze protection and other filesystem locks. It is advised to 151 * put sb_start_pagefault() close to mmap_lock in lock ordering. Page fault 152 * handling code implies lock dependency: 153 * 154 * mmap_lock 155 * -> sb_start_pagefault 156 */ 157static inline void sb_start_pagefault(struct super_block *sb) 158{ 159 __sb_start_write(sb, SB_FREEZE_PAGEFAULT); 160} 161 162/** 163 * sb_start_intwrite - get write access to a superblock for internal fs purposes 164 * @sb: the super we write to 165 * 166 * This is the third level of protection against filesystem freezing. It is 167 * free for use by a filesystem. The only requirement is that it must rank 168 * below sb_start_pagefault. 169 * 170 * For example filesystem can call sb_start_intwrite() when starting a 171 * transaction which somewhat eases handling of freezing for internal sources 172 * of filesystem changes (internal fs threads, discarding preallocation on file 173 * close, etc.). 174 */ 175static inline void sb_start_intwrite(struct super_block *sb) 176{ 177 __sb_start_write(sb, SB_FREEZE_FS); 178} 179 180static inline bool sb_start_intwrite_trylock(struct super_block *sb) 181{ 182 return __sb_start_write_trylock(sb, SB_FREEZE_FS); 183} 184 185static inline bool sb_rdonly(const struct super_block *sb) 186{ 187 return sb->s_flags & SB_RDONLY; 188} 189 190static inline bool sb_is_blkdev_sb(struct super_block *sb) 191{ 192 return IS_ENABLED(CONFIG_BLOCK) && sb == blockdev_superblock; 193} 194 195#if IS_ENABLED(CONFIG_UNICODE) 196static inline struct unicode_map *sb_encoding(const struct super_block *sb) 197{ 198 return sb->s_encoding; 199} 200 201/* Compare if two super blocks have the same encoding and flags */ 202static inline bool sb_same_encoding(const struct super_block *sb1, 203 const struct super_block *sb2) 204{ 205 if (sb1->s_encoding == sb2->s_encoding) 206 return true; 207 208 return (sb1->s_encoding && sb2->s_encoding && 209 (sb1->s_encoding->version == sb2->s_encoding->version) && 210 (sb1->s_encoding_flags == sb2->s_encoding_flags)); 211} 212#else 213static inline struct unicode_map *sb_encoding(const struct super_block *sb) 214{ 215 return NULL; 216} 217 218static inline bool sb_same_encoding(const struct super_block *sb1, 219 const struct super_block *sb2) 220{ 221 return true; 222} 223#endif 224 225static inline bool sb_has_encoding(const struct super_block *sb) 226{ 227 return !!sb_encoding(sb); 228} 229 230int sb_set_blocksize(struct super_block *sb, int size); 231int __must_check sb_min_blocksize(struct super_block *sb, int size); 232 233int freeze_super(struct super_block *super, enum freeze_holder who, 234 const void *freeze_owner); 235int thaw_super(struct super_block *super, enum freeze_holder who, 236 const void *freeze_owner); 237 238#endif /* _LINUX_FS_SUPER_H */