xref: /linux/include/linux/fs/super.h (revision 978d337c2ed6e5313ee426871a410eddc796ccfd)
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  */
__sb_end_write(struct super_block * sb,int level)12 static 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 
__sb_start_write(struct super_block * sb,int level)17 static 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 
__sb_start_write_trylock(struct super_block * sb,int level)22 static 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  */
__sb_write_started(const struct super_block * sb,int level)41 static 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  */
sb_write_started(const struct super_block * sb)52 static 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  */
sb_write_not_started(const struct super_block * sb)63 static 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  */
sb_end_write(struct super_block * sb)75 static 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  */
sb_end_pagefault(struct super_block * sb)87 static 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  */
sb_end_intwrite(struct super_block * sb)99 static 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  */
sb_start_write(struct super_block * sb)123 static inline void sb_start_write(struct super_block *sb)
124 {
125 	__sb_start_write(sb, SB_FREEZE_WRITE);
126 }
127 
DEFINE_GUARD(super_write,struct super_block *,sb_start_write (_T),sb_end_write (_T))128 DEFINE_GUARD(super_write,
129 	     struct super_block *,
130 	     sb_start_write(_T),
131 	     sb_end_write(_T))
132 
133 static 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  */
sb_start_pagefault(struct super_block * sb)157 static 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  */
sb_start_intwrite(struct super_block * sb)175 static inline void sb_start_intwrite(struct super_block *sb)
176 {
177 	__sb_start_write(sb, SB_FREEZE_FS);
178 }
179 
sb_start_intwrite_trylock(struct super_block * sb)180 static inline bool sb_start_intwrite_trylock(struct super_block *sb)
181 {
182 	return __sb_start_write_trylock(sb, SB_FREEZE_FS);
183 }
184 
sb_rdonly(const struct super_block * sb)185 static inline bool sb_rdonly(const struct super_block *sb)
186 {
187 	return sb->s_flags & SB_RDONLY;
188 }
189 
sb_is_blkdev_sb(struct super_block * sb)190 static 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)
sb_encoding(const struct super_block * sb)196 static 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 */
sb_same_encoding(const struct super_block * sb1,const struct super_block * sb2)202 static 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
sb_encoding(const struct super_block * sb)213 static inline struct unicode_map *sb_encoding(const struct super_block *sb)
214 {
215 	return NULL;
216 }
217 
sb_same_encoding(const struct super_block * sb1,const struct super_block * sb2)218 static inline bool sb_same_encoding(const struct super_block *sb1,
219 				    const struct super_block *sb2)
220 {
221 	return true;
222 }
223 #endif
224 
sb_has_encoding(const struct super_block * sb)225 static inline bool sb_has_encoding(const struct super_block *sb)
226 {
227 	return !!sb_encoding(sb);
228 }
229 
230 int sb_set_blocksize(struct super_block *sb, int size);
231 int __must_check sb_min_blocksize(struct super_block *sb, int size);
232 
233 int freeze_super(struct super_block *super, enum freeze_holder who,
234 		 const void *freeze_owner);
235 int thaw_super(struct super_block *super, enum freeze_holder who,
236 	       const void *freeze_owner);
237 
238 #endif /* _LINUX_FS_SUPER_H */
239