Blame view

fs/super.c 24.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *  linux/fs/super.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
   *  super.c contains code to handle: - mount structures
   *                                   - super-block tables
   *                                   - filesystem drivers list
   *                                   - mount system call
   *                                   - umount system call
   *                                   - ustat system call
   *
   * GK 2/5/95  -  Changed to support mounting the root fs via NFS
   *
   *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
   *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
   *  Added options to /proc/mounts:
96de0e252   Jan Engelhardt   Convert files to ...
18
   *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
   *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
   *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  #include <linux/module.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <linux/acct.h>
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  #include <linux/mount.h>
  #include <linux/security.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  #include <linux/writeback.h>		/* for the emergency remount stuff */
  #include <linux/idr.h>
353ab6e97   Ingo Molnar   [PATCH] sem2mutex...
30
  #include <linux/mutex.h>
5477d0fac   Jens Axboe   fs: fs/super.c ne...
31
  #include <linux/backing-dev.h>
6d59e7f58   Al Viro   [PATCH] move a bu...
32
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
  LIST_HEAD(super_blocks);
  DEFINE_SPINLOCK(sb_lock);
  
  /**
   *	alloc_super	-	create new superblock
fe2bbc483   Henrik Kretzschmar   [PATCH] add missi...
39
   *	@type:	filesystem type superblock should belong to
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
   *
   *	Allocates and initializes a new &struct super_block.  alloc_super()
   *	returns a pointer new superblock or %NULL if allocation had failed.
   */
cf5162499   Ingo Molnar   [PATCH] lockdep: ...
44
  static struct super_block *alloc_super(struct file_system_type *type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  {
11b0b5abb   Oliver Neukum   [PATCH] use kzall...
46
  	struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
b87221de6   Alexey Dobriyan   const: mark remai...
47
  	static const struct super_operations default_op;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  
  	if (s) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
  		if (security_sb_alloc(s)) {
  			kfree(s);
  			s = NULL;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
  		INIT_LIST_HEAD(&s->s_files);
  		INIT_LIST_HEAD(&s->s_instances);
  		INIT_HLIST_HEAD(&s->s_anon);
  		INIT_LIST_HEAD(&s->s_inodes);
da3bbdd46   Kentaro Makita   fix soft lock up ...
59
  		INIT_LIST_HEAD(&s->s_dentry_lru);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  		init_rwsem(&s->s_umount);
7892f2f48   Ingo Molnar   [PATCH] mutex sub...
61
  		mutex_init(&s->s_lock);
897c6ff95   Arjan van de Ven   [PATCH] lockdep: ...
62
  		lockdep_set_class(&s->s_umount, &type->s_umount_key);
cf5162499   Ingo Molnar   [PATCH] lockdep: ...
63
64
65
66
67
68
  		/*
  		 * The locking rules for s_lock are up to the
  		 * filesystem. For example ext3fs has different
  		 * lock ordering than usbfs:
  		 */
  		lockdep_set_class(&s->s_lock, &type->s_lock_key);
ada723dcd   Peter Zijlstra   fs/super.c: add l...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  		/*
  		 * sget() can have s_umount recursion.
  		 *
  		 * When it cannot find a suitable sb, it allocates a new
  		 * one (this one), and tries again to find a suitable old
  		 * one.
  		 *
  		 * In case that succeeds, it will acquire the s_umount
  		 * lock of the old one. Since these are clearly distrinct
  		 * locks, and this object isn't exposed yet, there's no
  		 * risk of deadlocks.
  		 *
  		 * Annotate this by putting this lock in a different
  		 * subclass.
  		 */
  		down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
b20bd1a5e   Al Viro   get rid of S_BIAS
85
  		s->s_count = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  		atomic_set(&s->s_active, 1);
a11f3a057   Arjan van de Ven   [PATCH] sem2mutex...
87
  		mutex_init(&s->s_vfs_rename_mutex);
51ee049e7   Roland Dreier   vfs: add lockdep ...
88
  		lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
d3be915fc   Ingo Molnar   [PATCH] sem2mutex...
89
90
  		mutex_init(&s->s_dquot.dqio_mutex);
  		mutex_init(&s->s_dquot.dqonoff_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
  		init_rwsem(&s->s_dquot.dqptr_sem);
  		init_waitqueue_head(&s->s_wait_unfrozen);
  		s->s_maxbytes = MAX_NON_LFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  		s->s_op = &default_op;
  		s->s_time_gran = 1000000000;
  	}
  out:
  	return s;
  }
  
  /**
   *	destroy_super	-	frees a superblock
   *	@s: superblock to free
   *
   *	Frees a superblock.
   */
  static inline void destroy_super(struct super_block *s)
  {
  	security_sb_free(s);
79c0b2df7   Miklos Szeredi   add filesystem su...
110
  	kfree(s->s_subtype);
b3b304a23   Miklos Szeredi   mount options: ad...
111
  	kfree(s->s_options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
116
117
  	kfree(s);
  }
  
  /* Superblock refcounting  */
  
  /*
35cf7ba0b   Al Viro   Bury __put_super_...
118
   * Drop a superblock's refcount.  The caller must hold sb_lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
   */
35cf7ba0b   Al Viro   Bury __put_super_...
120
  void __put_super(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  	if (!--sb->s_count) {
551de6f34   Al Viro   Leave superblocks...
123
  		list_del_init(&sb->s_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  		destroy_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
134
  }
  
  /**
   *	put_super	-	drop a temporary reference to superblock
   *	@sb: superblock in question
   *
   *	Drops a temporary reference, frees superblock if there's no
   *	references left.
   */
03ba3782e   Jens Axboe   writeback: switch...
135
  void put_super(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
141
142
143
  {
  	spin_lock(&sb_lock);
  	__put_super(sb);
  	spin_unlock(&sb_lock);
  }
  
  
  /**
1712ac8fd   Al Viro   Saner locking aro...
144
   *	deactivate_locked_super	-	drop an active reference to superblock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
   *	@s: superblock to deactivate
   *
1712ac8fd   Al Viro   Saner locking aro...
147
148
   *	Drops an active reference to superblock, converting it into a temprory
   *	one if there is no other active references left.  In that case we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
   *	tell fs driver to shut it down and drop the temporary reference we
   *	had just acquired.
1712ac8fd   Al Viro   Saner locking aro...
151
152
   *
   *	Caller holds exclusive lock on superblock; that lock is released.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
   */
1712ac8fd   Al Viro   Saner locking aro...
154
  void deactivate_locked_super(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
  {
  	struct file_system_type *fs = s->s_type;
b20bd1a5e   Al Viro   get rid of S_BIAS
157
  	if (atomic_dec_and_test(&s->s_active)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
  		fs->kill_sb(s);
  		put_filesystem(fs);
  		put_super(s);
1712ac8fd   Al Viro   Saner locking aro...
161
162
  	} else {
  		up_write(&s->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  	}
  }
1712ac8fd   Al Viro   Saner locking aro...
165
  EXPORT_SYMBOL(deactivate_locked_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  
  /**
1712ac8fd   Al Viro   Saner locking aro...
168
   *	deactivate_super	-	drop an active reference to superblock
74dbbdd7f   Al Viro   New helper: deact...
169
170
   *	@s: superblock to deactivate
   *
1712ac8fd   Al Viro   Saner locking aro...
171
172
173
   *	Variant of deactivate_locked_super(), except that superblock is *not*
   *	locked by caller.  If we are going to drop the final active reference,
   *	lock will be acquired prior to that.
74dbbdd7f   Al Viro   New helper: deact...
174
   */
1712ac8fd   Al Viro   Saner locking aro...
175
  void deactivate_super(struct super_block *s)
74dbbdd7f   Al Viro   New helper: deact...
176
  {
1712ac8fd   Al Viro   Saner locking aro...
177
178
179
          if (!atomic_add_unless(&s->s_active, -1, 1)) {
  		down_write(&s->s_umount);
  		deactivate_locked_super(s);
74dbbdd7f   Al Viro   New helper: deact...
180
181
  	}
  }
1712ac8fd   Al Viro   Saner locking aro...
182
  EXPORT_SYMBOL(deactivate_super);
74dbbdd7f   Al Viro   New helper: deact...
183
184
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
191
192
193
194
   *	grab_super - acquire an active reference
   *	@s: reference we are trying to make active
   *
   *	Tries to acquire an active reference.  grab_super() is used when we
   * 	had just found a superblock in super_blocks or fs_type->fs_supers
   *	and want to turn it into a full-blown active reference.  grab_super()
   *	is called with sb_lock held and drops it.  Returns 1 in case of
   *	success, 0 if we had failed (superblock contents was already dead or
   *	dying when grab_super() had been called).
   */
9c4dbee79   Josh Triplett   [PATCH] fs: add l...
195
  static int grab_super(struct super_block *s) __releases(sb_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  {
b20bd1a5e   Al Viro   get rid of S_BIAS
197
198
  	if (atomic_inc_not_zero(&s->s_active)) {
  		spin_unlock(&sb_lock);
b20bd1a5e   Al Viro   get rid of S_BIAS
199
200
201
  		return 1;
  	}
  	/* it's going away */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
  	s->s_count++;
  	spin_unlock(&sb_lock);
1712ac8fd   Al Viro   Saner locking aro...
204
  	/* wait for it to die */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  	down_write(&s->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
  	up_write(&s->s_umount);
  	put_super(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  	return 0;
  }
cf9a2ae8d   David Howells   [PATCH] BLOCK: Mo...
210
  /*
914e26379   Al Viro   [PATCH] severing ...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
   * Superblock locking.  We really ought to get rid of these two.
   */
  void lock_super(struct super_block * sb)
  {
  	get_fs_excl();
  	mutex_lock(&sb->s_lock);
  }
  
  void unlock_super(struct super_block * sb)
  {
  	put_fs_excl();
  	mutex_unlock(&sb->s_lock);
  }
  
  EXPORT_SYMBOL(lock_super);
  EXPORT_SYMBOL(unlock_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
234
235
  /**
   *	generic_shutdown_super	-	common helper for ->kill_sb()
   *	@sb: superblock to kill
   *
   *	generic_shutdown_super() does all fs-independent work on superblock
   *	shutdown.  Typical ->kill_sb() should pick all fs-specific objects
   *	that need destruction out of superblock, call generic_shutdown_super()
   *	and release aforementioned objects.  Note: dentries and inodes _are_
   *	taken care of and do not need specific handling.
c636ebdb1   David Howells   [PATCH] VFS: Dest...
236
237
238
239
   *
   *	Upon calling this function, the filesystem may no longer alter or
   *	rearrange the set of dentries belonging to this super_block, nor may it
   *	change the attachments of dentries to inodes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
   */
  void generic_shutdown_super(struct super_block *sb)
  {
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
243
  	const struct super_operations *sop = sb->s_op;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

efaee1920   Arjan van de Ven   async: make the f...
245

c636ebdb1   David Howells   [PATCH] VFS: Dest...
246
247
  	if (sb->s_root) {
  		shrink_dcache_for_umount(sb);
60b0680fa   Jan Kara   vfs: Rename fsync...
248
  		sync_filesystem(sb);
a9e220f83   Al Viro   No need to do loc...
249
  		get_fs_excl();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  		sb->s_flags &= ~MS_ACTIVE;
efaee1920   Arjan van de Ven   async: make the f...
251

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
  		/* bad name - it should be evict_inodes() */
  		invalidate_inodes(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
  		if (sop->put_super)
  			sop->put_super(sb);
  
  		/* Forget any remaining inodes */
  		if (invalidate_inodes(sb)) {
7b4fe29e0   Dave Jones   [PATCH] More info...
260
261
262
263
  			printk("VFS: Busy inodes after unmount of %s. "
  			   "Self-destruct in 5 seconds.  Have a nice day...
  ",
  			   sb->s_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  		}
a9e220f83   Al Viro   No need to do loc...
265
  		put_fs_excl();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
  	}
  	spin_lock(&sb_lock);
  	/* should be initialized for __put_super_and_need_restart() */
551de6f34   Al Viro   Leave superblocks...
269
  	list_del_init(&sb->s_instances);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  	spin_unlock(&sb_lock);
  	up_write(&sb->s_umount);
  }
  
  EXPORT_SYMBOL(generic_shutdown_super);
  
  /**
   *	sget	-	find or create a superblock
   *	@type:	filesystem type superblock should belong to
   *	@test:	comparison callback
   *	@set:	setup callback
   *	@data:	argument to each of them
   */
  struct super_block *sget(struct file_system_type *type,
  			int (*test)(struct super_block *,void *),
  			int (*set)(struct super_block *,void *),
  			void *data)
  {
  	struct super_block *s = NULL;
d47301271   Matthias Kaehlcke   fs/super.c: use l...
289
  	struct super_block *old;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
  	int err;
  
  retry:
  	spin_lock(&sb_lock);
d47301271   Matthias Kaehlcke   fs/super.c: use l...
294
295
296
297
298
299
  	if (test) {
  		list_for_each_entry(old, &type->fs_supers, s_instances) {
  			if (!test(old, data))
  				continue;
  			if (!grab_super(old))
  				goto retry;
a3cfbb53b   Li Zefan   vfs: add missing ...
300
301
  			if (s) {
  				up_write(&s->s_umount);
d47301271   Matthias Kaehlcke   fs/super.c: use l...
302
  				destroy_super(s);
a3cfbb53b   Li Zefan   vfs: add missing ...
303
  			}
d3f214730   Al Viro   Move grabbing s_u...
304
  			down_write(&old->s_umount);
d47301271   Matthias Kaehlcke   fs/super.c: use l...
305
306
  			return old;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
  	}
  	if (!s) {
  		spin_unlock(&sb_lock);
cf5162499   Ingo Molnar   [PATCH] lockdep: ...
310
  		s = alloc_super(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
314
315
316
317
318
  		if (!s)
  			return ERR_PTR(-ENOMEM);
  		goto retry;
  	}
  		
  	err = set(s, data);
  	if (err) {
  		spin_unlock(&sb_lock);
a3cfbb53b   Li Zefan   vfs: add missing ...
319
  		up_write(&s->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  		destroy_super(s);
  		return ERR_PTR(err);
  	}
  	s->s_type = type;
  	strlcpy(s->s_id, type->name, sizeof(s->s_id));
  	list_add_tail(&s->s_list, &super_blocks);
  	list_add(&s->s_instances, &type->fs_supers);
  	spin_unlock(&sb_lock);
  	get_filesystem(type);
  	return s;
  }
  
  EXPORT_SYMBOL(sget);
  
  void drop_super(struct super_block *sb)
  {
  	up_read(&sb->s_umount);
  	put_super(sb);
  }
  
  EXPORT_SYMBOL(drop_super);
e50047533   Christoph Hellwig   cleanup sync_supers
341
342
343
344
345
346
347
348
  /**
   * sync_supers - helper for periodic superblock writeback
   *
   * Call the write_super method if present on all dirty superblocks in
   * the system.  This is for the periodic writeback used by most older
   * filesystems.  For data integrity superblock writeback use
   * sync_filesystems() instead.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
353
354
   * Note: check the dirty flag before waiting, so we don't
   * hold up the sync while mounting a device. (The newly
   * mounted device won't need syncing.)
   */
  void sync_supers(void)
  {
6754af646   Al Viro   Convert simple lo...
355
  	struct super_block *sb, *n;
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
356

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	spin_lock(&sb_lock);
6754af646   Al Viro   Convert simple lo...
358
  	list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
551de6f34   Al Viro   Leave superblocks...
359
360
  		if (list_empty(&sb->s_instances))
  			continue;
e50047533   Christoph Hellwig   cleanup sync_supers
361
  		if (sb->s_op->write_super && sb->s_dirt) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
  			sb->s_count++;
  			spin_unlock(&sb_lock);
e50047533   Christoph Hellwig   cleanup sync_supers
364

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  			down_read(&sb->s_umount);
e50047533   Christoph Hellwig   cleanup sync_supers
366
367
  			if (sb->s_root && sb->s_dirt)
  				sb->s_op->write_super(sb);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
368
  			up_read(&sb->s_umount);
e50047533   Christoph Hellwig   cleanup sync_supers
369

618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
370
  			spin_lock(&sb_lock);
57439f878   npiggin@suse.de   fs: fix superbloc...
371
372
  			/* lock was dropped, must reset next */
  			list_safe_reset_next(sb, n, s_list);
6754af646   Al Viro   Convert simple lo...
373
  			__put_super(sb);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
374
375
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  	spin_unlock(&sb_lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  /**
01a05b337   Al Viro   new helper: itera...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
   *	iterate_supers - call function for all active superblocks
   *	@f: function to call
   *	@arg: argument to pass to it
   *
   *	Scans the superblock list and calls given function, passing it
   *	locked superblock and given argument.
   */
  void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
  {
  	struct super_block *sb, *n;
  
  	spin_lock(&sb_lock);
  	list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
  		if (list_empty(&sb->s_instances))
  			continue;
  		sb->s_count++;
  		spin_unlock(&sb_lock);
  
  		down_read(&sb->s_umount);
  		if (sb->s_root)
  			f(sb, arg);
  		up_read(&sb->s_umount);
  
  		spin_lock(&sb_lock);
57439f878   npiggin@suse.de   fs: fix superbloc...
403
404
  		/* lock was dropped, must reset next */
  		list_safe_reset_next(sb, n, s_list);
01a05b337   Al Viro   new helper: itera...
405
406
407
408
409
410
  		__put_super(sb);
  	}
  	spin_unlock(&sb_lock);
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
416
   *	get_super - get the superblock of a device
   *	@bdev: device to get the superblock for
   *	
   *	Scans the superblock list and finds the superblock of the file system
   *	mounted on the device given. %NULL is returned if no match is found.
   */
df40c01a9   Al Viro   In get_super() an...
417
  struct super_block *get_super(struct block_device *bdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  {
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
419
  	struct super_block *sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
  	if (!bdev)
  		return NULL;
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
422

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  	spin_lock(&sb_lock);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
424
425
  rescan:
  	list_for_each_entry(sb, &super_blocks, s_list) {
551de6f34   Al Viro   Leave superblocks...
426
427
  		if (list_empty(&sb->s_instances))
  			continue;
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
428
429
  		if (sb->s_bdev == bdev) {
  			sb->s_count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  			spin_unlock(&sb_lock);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
431
  			down_read(&sb->s_umount);
df40c01a9   Al Viro   In get_super() an...
432
  			/* still alive? */
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
433
434
435
  			if (sb->s_root)
  				return sb;
  			up_read(&sb->s_umount);
df40c01a9   Al Viro   In get_super() an...
436
  			/* nope, got unmounted */
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
437
  			spin_lock(&sb_lock);
df40c01a9   Al Viro   In get_super() an...
438
439
  			__put_super(sb);
  			goto rescan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
444
445
446
  		}
  	}
  	spin_unlock(&sb_lock);
  	return NULL;
  }
  
  EXPORT_SYMBOL(get_super);
4504230a7   Christoph Hellwig   freeze_bdev: grab...
447
448
449
450
451
452
453
  
  /**
   * get_active_super - get an active reference to the superblock of a device
   * @bdev: device to get the superblock for
   *
   * Scans the superblock list and finds the superblock of the file system
   * mounted on the device given.  Returns the superblock with an active
d3f214730   Al Viro   Move grabbing s_u...
454
   * reference or %NULL if none was found.
4504230a7   Christoph Hellwig   freeze_bdev: grab...
455
456
457
458
459
460
461
   */
  struct super_block *get_active_super(struct block_device *bdev)
  {
  	struct super_block *sb;
  
  	if (!bdev)
  		return NULL;
1494583de   Al Viro   fix get_active_su...
462
  restart:
4504230a7   Christoph Hellwig   freeze_bdev: grab...
463
464
  	spin_lock(&sb_lock);
  	list_for_each_entry(sb, &super_blocks, s_list) {
551de6f34   Al Viro   Leave superblocks...
465
466
  		if (list_empty(&sb->s_instances))
  			continue;
1494583de   Al Viro   fix get_active_su...
467
468
469
470
471
472
  		if (sb->s_bdev == bdev) {
  			if (grab_super(sb)) /* drops sb_lock */
  				return sb;
  			else
  				goto restart;
  		}
4504230a7   Christoph Hellwig   freeze_bdev: grab...
473
474
475
476
  	}
  	spin_unlock(&sb_lock);
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
   
df40c01a9   Al Viro   In get_super() an...
478
  struct super_block *user_get_super(dev_t dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  {
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
480
  	struct super_block *sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  	spin_lock(&sb_lock);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
483
484
  rescan:
  	list_for_each_entry(sb, &super_blocks, s_list) {
551de6f34   Al Viro   Leave superblocks...
485
486
  		if (list_empty(&sb->s_instances))
  			continue;
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
487
488
  		if (sb->s_dev ==  dev) {
  			sb->s_count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  			spin_unlock(&sb_lock);
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
490
  			down_read(&sb->s_umount);
df40c01a9   Al Viro   In get_super() an...
491
  			/* still alive? */
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
492
493
494
  			if (sb->s_root)
  				return sb;
  			up_read(&sb->s_umount);
df40c01a9   Al Viro   In get_super() an...
495
  			/* nope, got unmounted */
618f06362   Kirill Korotaev   [PATCH] O(1) sb l...
496
  			spin_lock(&sb_lock);
df40c01a9   Al Viro   In get_super() an...
497
498
  			__put_super(sb);
  			goto rescan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
502
503
  		}
  	}
  	spin_unlock(&sb_lock);
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
508
509
510
511
512
513
514
515
   *	do_remount_sb - asks filesystem to change mount options.
   *	@sb:	superblock in question
   *	@flags:	numeric part of options
   *	@data:	the rest of options
   *      @force: whether or not to force the change
   *
   *	Alters the mount options of a mounted file system.
   */
  int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
  {
  	int retval;
c79d967de   Christoph Hellwig   quota: move remou...
516
  	int remount_ro;
4504230a7   Christoph Hellwig   freeze_bdev: grab...
517
518
519
  
  	if (sb->s_frozen != SB_UNFROZEN)
  		return -EBUSY;
9361401eb   David Howells   [PATCH] BLOCK: Ma...
520
  #ifdef CONFIG_BLOCK
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
  	if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
  		return -EACCES;
9361401eb   David Howells   [PATCH] BLOCK: Ma...
523
  #endif
4504230a7   Christoph Hellwig   freeze_bdev: grab...
524

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
  	if (flags & MS_RDONLY)
  		acct_auto_close(sb);
  	shrink_dcache_sb(sb);
60b0680fa   Jan Kara   vfs: Rename fsync...
528
  	sync_filesystem(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

d208bbdda   Nick Piggin   fs: improve remou...
530
  	remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY);
d208bbdda   Nick Piggin   fs: improve remou...
531

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
  	/* If we are remounting RDONLY and current sb is read/write,
  	   make sure there are no rw files opened */
d208bbdda   Nick Piggin   fs: improve remou...
534
  	if (remount_ro) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
  		if (force)
  			mark_files_ro(sb);
b0895513f   J. R. Okajima   remove unlock_ker...
537
  		else if (!fs_may_remount_ro(sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
540
541
  			return -EBUSY;
  	}
  
  	if (sb->s_op->remount_fs) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  		retval = sb->s_op->remount_fs(sb, &flags, data);
b0895513f   J. R. Okajima   remove unlock_ker...
543
  		if (retval)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
546
  			return retval;
  	}
  	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
c79d967de   Christoph Hellwig   quota: move remou...
547

d208bbdda   Nick Piggin   fs: improve remou...
548
549
550
551
552
553
554
555
556
557
  	/*
  	 * Some filesystems modify their metadata via some other path than the
  	 * bdev buffer cache (eg. use a private mapping, or directories in
  	 * pagecache, etc). Also file data modifications go via their own
  	 * mappings. So If we try to mount readonly then copy the filesystem
  	 * from bdev, we could get stale data, so invalidate it to give a best
  	 * effort at coherency.
  	 */
  	if (remount_ro && sb->s_bdev)
  		invalidate_bdev(sb->s_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
  	return 0;
  }
a2a9537ac   Jens Axboe   Get rid of pdflus...
560
  static void do_emergency_remount(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  {
e7fe0585c   Al Viro   fix do_emergency_...
562
  	struct super_block *sb, *n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
  
  	spin_lock(&sb_lock);
e7fe0585c   Al Viro   fix do_emergency_...
565
  	list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
551de6f34   Al Viro   Leave superblocks...
566
567
  		if (list_empty(&sb->s_instances))
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
  		sb->s_count++;
  		spin_unlock(&sb_lock);
443b94baa   Al Viro   Make sure that al...
570
  		down_write(&sb->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
  		if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) {
  			/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
  			 * What lock protects sb->s_flags??
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  			do_remount_sb(sb, MS_RDONLY, NULL, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  		}
443b94baa   Al Viro   Make sure that al...
577
  		up_write(&sb->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  		spin_lock(&sb_lock);
57439f878   npiggin@suse.de   fs: fix superbloc...
579
580
  		/* lock was dropped, must reset next */
  		list_safe_reset_next(sb, n, s_list);
e7fe0585c   Al Viro   fix do_emergency_...
581
  		__put_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
  	}
  	spin_unlock(&sb_lock);
a2a9537ac   Jens Axboe   Get rid of pdflus...
584
  	kfree(work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
  	printk("Emergency Remount complete
  ");
  }
  
  void emergency_remount(void)
  {
a2a9537ac   Jens Axboe   Get rid of pdflus...
591
592
593
594
595
596
597
  	struct work_struct *work;
  
  	work = kmalloc(sizeof(*work), GFP_ATOMIC);
  	if (work) {
  		INIT_WORK(work, do_emergency_remount);
  		schedule_work(work);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
602
603
  }
  
  /*
   * Unnamed block devices are dummy devices used by virtual
   * filesystems which don't use real block-devices.  -- jrs
   */
ad76cbc63   Alexey Dobriyan   [PATCH 2/2] anond...
604
  static DEFINE_IDA(unnamed_dev_ida);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
c63e09ecc   Al Viro   Make allocation o...
606
  static int unnamed_dev_start = 0; /* don't bother trying below it */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
609
610
611
612
613
  
  int set_anon_super(struct super_block *s, void *data)
  {
  	int dev;
  	int error;
  
   retry:
ad76cbc63   Alexey Dobriyan   [PATCH 2/2] anond...
614
  	if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
  		return -ENOMEM;
  	spin_lock(&unnamed_dev_lock);
c63e09ecc   Al Viro   Make allocation o...
617
  	error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev);
f21f62208   Al Viro   ... and the same ...
618
619
  	if (!error)
  		unnamed_dev_start = dev + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
623
624
625
626
627
628
  	spin_unlock(&unnamed_dev_lock);
  	if (error == -EAGAIN)
  		/* We raced and lost with another CPU. */
  		goto retry;
  	else if (error)
  		return -EAGAIN;
  
  	if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
  		spin_lock(&unnamed_dev_lock);
ad76cbc63   Alexey Dobriyan   [PATCH 2/2] anond...
629
  		ida_remove(&unnamed_dev_ida, dev);
f21f62208   Al Viro   ... and the same ...
630
631
  		if (unnamed_dev_start > dev)
  			unnamed_dev_start = dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
  		spin_unlock(&unnamed_dev_lock);
  		return -EMFILE;
  	}
  	s->s_dev = MKDEV(0, dev & MINORMASK);
5129a469a   Jörn Engel   Catch filesystems...
636
  	s->s_bdi = &noop_backing_dev_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
639
640
641
642
643
644
645
646
647
  	return 0;
  }
  
  EXPORT_SYMBOL(set_anon_super);
  
  void kill_anon_super(struct super_block *sb)
  {
  	int slot = MINOR(sb->s_dev);
  
  	generic_shutdown_super(sb);
  	spin_lock(&unnamed_dev_lock);
ad76cbc63   Alexey Dobriyan   [PATCH 2/2] anond...
648
  	ida_remove(&unnamed_dev_ida, slot);
c63e09ecc   Al Viro   Make allocation o...
649
650
  	if (slot < unnamed_dev_start)
  		unnamed_dev_start = slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
  	spin_unlock(&unnamed_dev_lock);
  }
  
  EXPORT_SYMBOL(kill_anon_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
659
660
661
662
  void kill_litter_super(struct super_block *sb)
  {
  	if (sb->s_root)
  		d_genocide(sb->s_root);
  	kill_anon_super(sb);
  }
  
  EXPORT_SYMBOL(kill_litter_super);
909e6d947   Serge E. Hallyn   namespaces: move ...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  static int ns_test_super(struct super_block *sb, void *data)
  {
  	return sb->s_fs_info == data;
  }
  
  static int ns_set_super(struct super_block *sb, void *data)
  {
  	sb->s_fs_info = data;
  	return set_anon_super(sb, NULL);
  }
  
  int get_sb_ns(struct file_system_type *fs_type, int flags, void *data,
  	int (*fill_super)(struct super_block *, void *, int),
  	struct vfsmount *mnt)
  {
  	struct super_block *sb;
  
  	sb = sget(fs_type, ns_test_super, ns_set_super, data);
  	if (IS_ERR(sb))
  		return PTR_ERR(sb);
  
  	if (!sb->s_root) {
  		int err;
  		sb->s_flags = flags;
  		err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
  		if (err) {
74dbbdd7f   Al Viro   New helper: deact...
689
  			deactivate_locked_super(sb);
909e6d947   Serge E. Hallyn   namespaces: move ...
690
691
692
693
694
695
696
697
698
699
700
  			return err;
  		}
  
  		sb->s_flags |= MS_ACTIVE;
  	}
  
  	simple_set_mnt(mnt, sb);
  	return 0;
  }
  
  EXPORT_SYMBOL(get_sb_ns);
9361401eb   David Howells   [PATCH] BLOCK: Ma...
701
  #ifdef CONFIG_BLOCK
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
705
  static int set_bdev_super(struct super_block *s, void *data)
  {
  	s->s_bdev = data;
  	s->s_dev = s->s_bdev->bd_dev;
32a88aa1b   Jens Axboe   fs: Assign bdi in...
706
707
708
709
710
711
  
  	/*
  	 * We set the bdi here to the queue backing, file systems can
  	 * overwrite this in ->fill_super()
  	 */
  	s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
713
714
715
716
717
718
  	return 0;
  }
  
  static int test_bdev_super(struct super_block *s, void *data)
  {
  	return (void *)s->s_bdev == data;
  }
454e2398b   David Howells   [PATCH] VFS: Perm...
719
  int get_sb_bdev(struct file_system_type *fs_type,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  	int flags, const char *dev_name, void *data,
454e2398b   David Howells   [PATCH] VFS: Perm...
721
722
  	int (*fill_super)(struct super_block *, void *, int),
  	struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
  {
  	struct block_device *bdev;
  	struct super_block *s;
30c40d2c0   Al Viro   [PATCH] propagate...
726
  	fmode_t mode = FMODE_READ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
  	int error = 0;
30c40d2c0   Al Viro   [PATCH] propagate...
728
729
730
731
  	if (!(flags & MS_RDONLY))
  		mode |= FMODE_WRITE;
  
  	bdev = open_bdev_exclusive(dev_name, mode, fs_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  	if (IS_ERR(bdev))
454e2398b   David Howells   [PATCH] VFS: Perm...
733
  		return PTR_ERR(bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
  
  	/*
  	 * once the super is inserted into the list by sget, s_umount
  	 * will protect the lockfs code from trying to start a snapshot
  	 * while we are mounting
  	 */
4fadd7bb2   Christoph Hellwig   freeze_bdev: kill...
740
741
742
743
744
745
  	mutex_lock(&bdev->bd_fsfreeze_mutex);
  	if (bdev->bd_fsfreeze_count > 0) {
  		mutex_unlock(&bdev->bd_fsfreeze_mutex);
  		error = -EBUSY;
  		goto error_bdev;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  	s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
4fadd7bb2   Christoph Hellwig   freeze_bdev: kill...
747
  	mutex_unlock(&bdev->bd_fsfreeze_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  	if (IS_ERR(s))
454e2398b   David Howells   [PATCH] VFS: Perm...
749
  		goto error_s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
751
752
  
  	if (s->s_root) {
  		if ((flags ^ s->s_flags) & MS_RDONLY) {
74dbbdd7f   Al Viro   New helper: deact...
753
  			deactivate_locked_super(s);
454e2398b   David Howells   [PATCH] VFS: Perm...
754
755
  			error = -EBUSY;
  			goto error_bdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  		}
454e2398b   David Howells   [PATCH] VFS: Perm...
757

30c40d2c0   Al Viro   [PATCH] propagate...
758
  		close_bdev_exclusive(bdev, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
762
  	} else {
  		char b[BDEVNAME_SIZE];
  
  		s->s_flags = flags;
30c40d2c0   Al Viro   [PATCH] propagate...
763
  		s->s_mode = mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
e78c9a004   Pekka Enberg   [PATCH] fs: remov...
765
  		sb_set_blocksize(s, block_size(bdev));
9b04c997b   Theodore Ts'o   [PATCH] vfs: MS_V...
766
  		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  		if (error) {
74dbbdd7f   Al Viro   New helper: deact...
768
  			deactivate_locked_super(s);
454e2398b   David Howells   [PATCH] VFS: Perm...
769
  			goto error;
fa675765a   Greg Kroah-Hartman   Revert mount/umou...
770
  		}
454e2398b   David Howells   [PATCH] VFS: Perm...
771
772
  
  		s->s_flags |= MS_ACTIVE;
87d8fe1ee   Theodore Ts'o   add releasepage h...
773
  		bdev->bd_super = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  	}
a3ec947c8   Sukadev Bhattiprolu   vfs: simple_set_m...
775
776
  	simple_set_mnt(mnt, s);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777

454e2398b   David Howells   [PATCH] VFS: Perm...
778
779
780
  error_s:
  	error = PTR_ERR(s);
  error_bdev:
30c40d2c0   Al Viro   [PATCH] propagate...
781
  	close_bdev_exclusive(bdev, mode);
454e2398b   David Howells   [PATCH] VFS: Perm...
782
783
  error:
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
786
787
788
789
790
  }
  
  EXPORT_SYMBOL(get_sb_bdev);
  
  void kill_block_super(struct super_block *sb)
  {
  	struct block_device *bdev = sb->s_bdev;
30c40d2c0   Al Viro   [PATCH] propagate...
791
  	fmode_t mode = sb->s_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792

ddbaaf302   H Hartley Sweeten   NULL noise in fs/...
793
  	bdev->bd_super = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
  	generic_shutdown_super(sb);
  	sync_blockdev(bdev);
30c40d2c0   Al Viro   [PATCH] propagate...
796
  	close_bdev_exclusive(bdev, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
799
  }
  
  EXPORT_SYMBOL(kill_block_super);
9361401eb   David Howells   [PATCH] BLOCK: Ma...
800
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801

454e2398b   David Howells   [PATCH] VFS: Perm...
802
  int get_sb_nodev(struct file_system_type *fs_type,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  	int flags, void *data,
454e2398b   David Howells   [PATCH] VFS: Perm...
804
805
  	int (*fill_super)(struct super_block *, void *, int),
  	struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
  {
  	int error;
  	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
  
  	if (IS_ERR(s))
454e2398b   David Howells   [PATCH] VFS: Perm...
811
  		return PTR_ERR(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
  
  	s->s_flags = flags;
9b04c997b   Theodore Ts'o   [PATCH] vfs: MS_V...
814
  	error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  	if (error) {
74dbbdd7f   Al Viro   New helper: deact...
816
  		deactivate_locked_super(s);
454e2398b   David Howells   [PATCH] VFS: Perm...
817
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
  	}
  	s->s_flags |= MS_ACTIVE;
a3ec947c8   Sukadev Bhattiprolu   vfs: simple_set_m...
820
821
  	simple_set_mnt(mnt, s);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
824
825
826
827
828
829
  }
  
  EXPORT_SYMBOL(get_sb_nodev);
  
  static int compare_single(struct super_block *s, void *p)
  {
  	return 1;
  }
454e2398b   David Howells   [PATCH] VFS: Perm...
830
  int get_sb_single(struct file_system_type *fs_type,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  	int flags, void *data,
454e2398b   David Howells   [PATCH] VFS: Perm...
832
833
  	int (*fill_super)(struct super_block *, void *, int),
  	struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
835
836
837
838
839
  {
  	struct super_block *s;
  	int error;
  
  	s = sget(fs_type, compare_single, set_anon_super, NULL);
  	if (IS_ERR(s))
454e2398b   David Howells   [PATCH] VFS: Perm...
840
  		return PTR_ERR(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
842
  	if (!s->s_root) {
  		s->s_flags = flags;
9b04c997b   Theodore Ts'o   [PATCH] vfs: MS_V...
843
  		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  		if (error) {
74dbbdd7f   Al Viro   New helper: deact...
845
  			deactivate_locked_super(s);
454e2398b   David Howells   [PATCH] VFS: Perm...
846
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
848
  		}
  		s->s_flags |= MS_ACTIVE;
9329d1bea   Kay Sievers   vfs: get_sb_singl...
849
850
  	} else {
  		do_remount_sb(s, flags, data, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
  	}
a3ec947c8   Sukadev Bhattiprolu   vfs: simple_set_m...
852
853
  	simple_set_mnt(mnt, s);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
856
857
858
  }
  
  EXPORT_SYMBOL(get_sb_single);
  
  struct vfsmount *
bb4a58bf4   Trond Myklebust   VFS: Add GPL_EXPO...
859
  vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  	struct vfsmount *mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
  	char *secdata = NULL;
454e2398b   David Howells   [PATCH] VFS: Perm...
863
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
  
  	if (!type)
  		return ERR_PTR(-ENODEV);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867

454e2398b   David Howells   [PATCH] VFS: Perm...
868
  	error = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
871
  	mnt = alloc_vfsmnt(name);
  	if (!mnt)
  		goto out;
8089352a1   Al Viro   Mirror MS_KERNMOU...
872
873
  	if (flags & MS_KERNMOUNT)
  		mnt->mnt_flags = MNT_INTERNAL;
e00075298   Eric Paris   LSM/SELinux: Inte...
874
  	if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  		secdata = alloc_secdata();
454e2398b   David Howells   [PATCH] VFS: Perm...
876
  		if (!secdata)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  			goto out_mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878

e00075298   Eric Paris   LSM/SELinux: Inte...
879
  		error = security_sb_copy_data(data, secdata);
454e2398b   David Howells   [PATCH] VFS: Perm...
880
  		if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
  			goto out_free_secdata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  	}
454e2398b   David Howells   [PATCH] VFS: Perm...
883
884
  	error = type->get_sb(type, flags, name, data, mnt);
  	if (error < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
  		goto out_free_secdata;
b4c07bce7   Lee Schermerhorn   hugetlbfs: handle...
886
  	BUG_ON(!mnt->mnt_sb);
5129a469a   Jörn Engel   Catch filesystems...
887
  	WARN_ON(!mnt->mnt_sb->s_bdi);
454e2398b   David Howells   [PATCH] VFS: Perm...
888

5129a469a   Jörn Engel   Catch filesystems...
889
890
891
  	error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
  	if (error)
  		goto out_sb;
454e2398b   David Howells   [PATCH] VFS: Perm...
892

42cb56ae2   Jeff Layton   vfs: change sb->s...
893
894
895
896
897
898
899
900
901
902
  	/*
  	 * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
  	 * but s_maxbytes was an unsigned long long for many releases. Throw
  	 * this warning for a little while to try and catch filesystems that
  	 * violate this rule. This warning should be either removed or
  	 * converted to a BUG() in 2.6.34.
  	 */
  	WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
  		"negative value (%lld)
  ", type->name, mnt->mnt_sb->s_maxbytes);
454e2398b   David Howells   [PATCH] VFS: Perm...
903
  	mnt->mnt_mountpoint = mnt->mnt_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
  	mnt->mnt_parent = mnt;
454e2398b   David Howells   [PATCH] VFS: Perm...
905
  	up_write(&mnt->mnt_sb->s_umount);
8680e22f2   Gerald Schaefer   [PATCH] VFS: memo...
906
  	free_secdata(secdata);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
908
  	return mnt;
  out_sb:
454e2398b   David Howells   [PATCH] VFS: Perm...
909
  	dput(mnt->mnt_root);
74dbbdd7f   Al Viro   New helper: deact...
910
  	deactivate_locked_super(mnt->mnt_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
914
915
  out_free_secdata:
  	free_secdata(secdata);
  out_mnt:
  	free_vfsmnt(mnt);
  out:
454e2398b   David Howells   [PATCH] VFS: Perm...
916
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  }
bb4a58bf4   Trond Myklebust   VFS: Add GPL_EXPO...
918
  EXPORT_SYMBOL_GPL(vfs_kern_mount);
18e9e5104   Josef Bacik   Introduce freeze_...
919
  /**
7000d3c42   Randy Dunlap   fs/super: fix ker...
920
921
   * freeze_super - lock the filesystem and force it into a consistent state
   * @sb: the super to lock
18e9e5104   Josef Bacik   Introduce freeze_...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
   *
   * Syncs the super to make sure the filesystem is consistent and calls the fs's
   * freeze_fs.  Subsequent calls to this without first thawing the fs will return
   * -EBUSY.
   */
  int freeze_super(struct super_block *sb)
  {
  	int ret;
  
  	atomic_inc(&sb->s_active);
  	down_write(&sb->s_umount);
  	if (sb->s_frozen) {
  		deactivate_locked_super(sb);
  		return -EBUSY;
  	}
  
  	if (sb->s_flags & MS_RDONLY) {
  		sb->s_frozen = SB_FREEZE_TRANS;
  		smp_wmb();
  		up_write(&sb->s_umount);
  		return 0;
  	}
  
  	sb->s_frozen = SB_FREEZE_WRITE;
  	smp_wmb();
  
  	sync_filesystem(sb);
  
  	sb->s_frozen = SB_FREEZE_TRANS;
  	smp_wmb();
  
  	sync_blockdev(sb->s_bdev);
  	if (sb->s_op->freeze_fs) {
  		ret = sb->s_op->freeze_fs(sb);
  		if (ret) {
  			printk(KERN_ERR
  				"VFS:Filesystem freeze failed
  ");
  			sb->s_frozen = SB_UNFROZEN;
  			deactivate_locked_super(sb);
  			return ret;
  		}
  	}
  	up_write(&sb->s_umount);
  	return 0;
  }
  EXPORT_SYMBOL(freeze_super);
  
  /**
   * thaw_super -- unlock filesystem
   * @sb: the super to thaw
   *
   * Unlocks the filesystem and marks it writeable again after freeze_super().
   */
  int thaw_super(struct super_block *sb)
  {
  	int error;
  
  	down_write(&sb->s_umount);
  	if (sb->s_frozen == SB_UNFROZEN) {
  		up_write(&sb->s_umount);
  		return -EINVAL;
  	}
  
  	if (sb->s_flags & MS_RDONLY)
  		goto out;
  
  	if (sb->s_op->unfreeze_fs) {
  		error = sb->s_op->unfreeze_fs(sb);
  		if (error) {
  			printk(KERN_ERR
  				"VFS:Filesystem thaw failed
  ");
  			sb->s_frozen = SB_FREEZE_TRANS;
  			up_write(&sb->s_umount);
  			return error;
  		}
  	}
  
  out:
  	sb->s_frozen = SB_UNFROZEN;
  	smp_wmb();
  	wake_up(&sb->s_wait_unfrozen);
  	deactivate_locked_super(sb);
  
  	return 0;
  }
  EXPORT_SYMBOL(thaw_super);
79c0b2df7   Miklos Szeredi   add filesystem su...
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
  static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
  {
  	int err;
  	const char *subtype = strchr(fstype, '.');
  	if (subtype) {
  		subtype++;
  		err = -EINVAL;
  		if (!subtype[0])
  			goto err;
  	} else
  		subtype = "";
  
  	mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
  	err = -ENOMEM;
  	if (!mnt->mnt_sb->s_subtype)
  		goto err;
  	return mnt;
  
   err:
  	mntput(mnt);
  	return ERR_PTR(err);
  }
bb4a58bf4   Trond Myklebust   VFS: Add GPL_EXPO...
1032
1033
1034
1035
1036
1037
1038
1039
  struct vfsmount *
  do_kern_mount(const char *fstype, int flags, const char *name, void *data)
  {
  	struct file_system_type *type = get_fs_type(fstype);
  	struct vfsmount *mnt;
  	if (!type)
  		return ERR_PTR(-ENODEV);
  	mnt = vfs_kern_mount(type, flags, name, data);
79c0b2df7   Miklos Szeredi   add filesystem su...
1040
1041
1042
  	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
  	    !mnt->mnt_sb->s_subtype)
  		mnt = fs_set_subtype(mnt, fstype);
bb4a58bf4   Trond Myklebust   VFS: Add GPL_EXPO...
1043
1044
1045
  	put_filesystem(type);
  	return mnt;
  }
8a4e98d9d   Al Viro   [PATCH] restore e...
1046
  EXPORT_SYMBOL_GPL(do_kern_mount);
bb4a58bf4   Trond Myklebust   VFS: Add GPL_EXPO...
1047

8bf9725c2   Pavel Emelyanov   pid namespaces: i...
1048
  struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
  {
8bf9725c2   Pavel Emelyanov   pid namespaces: i...
1050
  	return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
  }
8bf9725c2   Pavel Emelyanov   pid namespaces: i...
1052
  EXPORT_SYMBOL_GPL(kern_mount_data);