diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c new file mode 100644 index 000000000000..06f06f7773d0 --- /dev/null +++ b/fs/gfs2/ops_super.c | |||
@@ -0,0 +1,468 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * This copyrighted material is made available to anyone wishing to use, | ||
6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/completion.h> | ||
14 | #include <linux/buffer_head.h> | ||
15 | #include <linux/statfs.h> | ||
16 | #include <linux/seq_file.h> | ||
17 | #include <linux/mount.h> | ||
18 | #include <linux/kthread.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/gfs2_ondisk.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <linux/lm_interface.h> | ||
23 | |||
24 | #include "gfs2.h" | ||
25 | #include "incore.h" | ||
26 | #include "glock.h" | ||
27 | #include "inode.h" | ||
28 | #include "lm.h" | ||
29 | #include "log.h" | ||
30 | #include "mount.h" | ||
31 | #include "ops_super.h" | ||
32 | #include "quota.h" | ||
33 | #include "recovery.h" | ||
34 | #include "rgrp.h" | ||
35 | #include "super.h" | ||
36 | #include "sys.h" | ||
37 | #include "util.h" | ||
38 | #include "trans.h" | ||
39 | #include "dir.h" | ||
40 | #include "eattr.h" | ||
41 | #include "bmap.h" | ||
42 | |||
43 | /** | ||
44 | * gfs2_write_inode - Make sure the inode is stable on the disk | ||
45 | * @inode: The inode | ||
46 | * @sync: synchronous write flag | ||
47 | * | ||
48 | * Returns: errno | ||
49 | */ | ||
50 | |||
51 | static int gfs2_write_inode(struct inode *inode, int sync) | ||
52 | { | ||
53 | struct gfs2_inode *ip = GFS2_I(inode); | ||
54 | |||
55 | /* Check this is a "normal" inode */ | ||
56 | if (inode->i_private) { | ||
57 | if (current->flags & PF_MEMALLOC) | ||
58 | return 0; | ||
59 | if (sync) | ||
60 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * gfs2_put_super - Unmount the filesystem | ||
68 | * @sb: The VFS superblock | ||
69 | * | ||
70 | */ | ||
71 | |||
72 | static void gfs2_put_super(struct super_block *sb) | ||
73 | { | ||
74 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
75 | int error; | ||
76 | |||
77 | if (!sdp) | ||
78 | return; | ||
79 | |||
80 | if (!strncmp(sb->s_type->name, "gfs2meta", 8)) | ||
81 | return; /* Nothing to do */ | ||
82 | |||
83 | /* Unfreeze the filesystem, if we need to */ | ||
84 | |||
85 | mutex_lock(&sdp->sd_freeze_lock); | ||
86 | if (sdp->sd_freeze_count) | ||
87 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); | ||
88 | mutex_unlock(&sdp->sd_freeze_lock); | ||
89 | |||
90 | kthread_stop(sdp->sd_quotad_process); | ||
91 | kthread_stop(sdp->sd_logd_process); | ||
92 | kthread_stop(sdp->sd_recoverd_process); | ||
93 | while (sdp->sd_glockd_num--) | ||
94 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); | ||
95 | kthread_stop(sdp->sd_scand_process); | ||
96 | |||
97 | if (!(sb->s_flags & MS_RDONLY)) { | ||
98 | error = gfs2_make_fs_ro(sdp); | ||
99 | if (error) | ||
100 | gfs2_io_error(sdp); | ||
101 | } | ||
102 | /* At this point, we're through modifying the disk */ | ||
103 | |||
104 | /* Release stuff */ | ||
105 | |||
106 | iput(sdp->sd_master_dir); | ||
107 | iput(sdp->sd_jindex); | ||
108 | iput(sdp->sd_inum_inode); | ||
109 | iput(sdp->sd_statfs_inode); | ||
110 | iput(sdp->sd_rindex); | ||
111 | iput(sdp->sd_quota_inode); | ||
112 | |||
113 | gfs2_glock_put(sdp->sd_rename_gl); | ||
114 | gfs2_glock_put(sdp->sd_trans_gl); | ||
115 | |||
116 | if (!sdp->sd_args.ar_spectator) { | ||
117 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); | ||
118 | gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); | ||
119 | gfs2_glock_dq_uninit(&sdp->sd_ir_gh); | ||
120 | gfs2_glock_dq_uninit(&sdp->sd_sc_gh); | ||
121 | gfs2_glock_dq_uninit(&sdp->sd_qc_gh); | ||
122 | iput(sdp->sd_ir_inode); | ||
123 | iput(sdp->sd_sc_inode); | ||
124 | iput(sdp->sd_qc_inode); | ||
125 | } | ||
126 | |||
127 | gfs2_glock_dq_uninit(&sdp->sd_live_gh); | ||
128 | gfs2_clear_rgrpd(sdp); | ||
129 | gfs2_jindex_free(sdp); | ||
130 | /* Take apart glock structures and buffer lists */ | ||
131 | gfs2_gl_hash_clear(sdp, WAIT); | ||
132 | /* Unmount the locking protocol */ | ||
133 | gfs2_lm_unmount(sdp); | ||
134 | |||
135 | /* At this point, we're through participating in the lockspace */ | ||
136 | gfs2_sys_fs_del(sdp); | ||
137 | kfree(sdp); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * gfs2_write_super - disk commit all incore transactions | ||
142 | * @sb: the filesystem | ||
143 | * | ||
144 | * This function is called every time sync(2) is called. | ||
145 | * After this exits, all dirty buffers are synced. | ||
146 | */ | ||
147 | |||
148 | static void gfs2_write_super(struct super_block *sb) | ||
149 | { | ||
150 | gfs2_log_flush(sb->s_fs_info, NULL); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * gfs2_write_super_lockfs - prevent further writes to the filesystem | ||
155 | * @sb: the VFS structure for the filesystem | ||
156 | * | ||
157 | */ | ||
158 | |||
159 | static void gfs2_write_super_lockfs(struct super_block *sb) | ||
160 | { | ||
161 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
162 | int error; | ||
163 | |||
164 | for (;;) { | ||
165 | error = gfs2_freeze_fs(sdp); | ||
166 | if (!error) | ||
167 | break; | ||
168 | |||
169 | switch (error) { | ||
170 | case -EBUSY: | ||
171 | fs_err(sdp, "waiting for recovery before freeze\n"); | ||
172 | break; | ||
173 | |||
174 | default: | ||
175 | fs_err(sdp, "error freezing FS: %d\n", error); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | fs_err(sdp, "retrying...\n"); | ||
180 | msleep(1000); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * gfs2_unlockfs - reallow writes to the filesystem | ||
186 | * @sb: the VFS structure for the filesystem | ||
187 | * | ||
188 | */ | ||
189 | |||
190 | static void gfs2_unlockfs(struct super_block *sb) | ||
191 | { | ||
192 | gfs2_unfreeze_fs(sb->s_fs_info); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * gfs2_statfs - Gather and return stats about the filesystem | ||
197 | * @sb: The superblock | ||
198 | * @statfsbuf: The buffer | ||
199 | * | ||
200 | * Returns: 0 on success or error code | ||
201 | */ | ||
202 | |||
203 | static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
204 | { | ||
205 | struct super_block *sb = dentry->d_inode->i_sb; | ||
206 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
207 | struct gfs2_statfs_change sc; | ||
208 | int error; | ||
209 | |||
210 | if (gfs2_tune_get(sdp, gt_statfs_slow)) | ||
211 | error = gfs2_statfs_slow(sdp, &sc); | ||
212 | else | ||
213 | error = gfs2_statfs_i(sdp, &sc); | ||
214 | |||
215 | if (error) | ||
216 | return error; | ||
217 | |||
218 | buf->f_type = GFS2_MAGIC; | ||
219 | buf->f_bsize = sdp->sd_sb.sb_bsize; | ||
220 | buf->f_blocks = sc.sc_total; | ||
221 | buf->f_bfree = sc.sc_free; | ||
222 | buf->f_bavail = sc.sc_free; | ||
223 | buf->f_files = sc.sc_dinodes + sc.sc_free; | ||
224 | buf->f_ffree = sc.sc_free; | ||
225 | buf->f_namelen = GFS2_FNAMESIZE; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * gfs2_remount_fs - called when the FS is remounted | ||
232 | * @sb: the filesystem | ||
233 | * @flags: the remount flags | ||
234 | * @data: extra data passed in (not used right now) | ||
235 | * | ||
236 | * Returns: errno | ||
237 | */ | ||
238 | |||
239 | static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | ||
240 | { | ||
241 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
242 | int error; | ||
243 | |||
244 | error = gfs2_mount_args(sdp, data, 1); | ||
245 | if (error) | ||
246 | return error; | ||
247 | |||
248 | if (sdp->sd_args.ar_spectator) | ||
249 | *flags |= MS_RDONLY; | ||
250 | else { | ||
251 | if (*flags & MS_RDONLY) { | ||
252 | if (!(sb->s_flags & MS_RDONLY)) | ||
253 | error = gfs2_make_fs_ro(sdp); | ||
254 | } else if (!(*flags & MS_RDONLY) && | ||
255 | (sb->s_flags & MS_RDONLY)) { | ||
256 | error = gfs2_make_fs_rw(sdp); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | if (*flags & (MS_NOATIME | MS_NODIRATIME)) | ||
261 | set_bit(SDF_NOATIME, &sdp->sd_flags); | ||
262 | else | ||
263 | clear_bit(SDF_NOATIME, &sdp->sd_flags); | ||
264 | |||
265 | /* Don't let the VFS update atimes. GFS2 handles this itself. */ | ||
266 | *flags |= MS_NOATIME | MS_NODIRATIME; | ||
267 | |||
268 | return error; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * gfs2_clear_inode - Deallocate an inode when VFS is done with it | ||
273 | * @inode: The VFS inode | ||
274 | * | ||
275 | */ | ||
276 | |||
277 | static void gfs2_clear_inode(struct inode *inode) | ||
278 | { | ||
279 | /* This tells us its a "real" inode and not one which only | ||
280 | * serves to contain an address space (see rgrp.c, meta_io.c) | ||
281 | * which therefore doesn't have its own glocks. | ||
282 | */ | ||
283 | if (inode->i_private) { | ||
284 | struct gfs2_inode *ip = GFS2_I(inode); | ||
285 | gfs2_glock_inode_squish(inode); | ||
286 | gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED); | ||
287 | ip->i_gl->gl_object = NULL; | ||
288 | gfs2_glock_schedule_for_reclaim(ip->i_gl); | ||
289 | gfs2_glock_put(ip->i_gl); | ||
290 | ip->i_gl = NULL; | ||
291 | if (ip->i_iopen_gh.gh_gl) | ||
292 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /** | ||
297 | * gfs2_show_options - Show mount options for /proc/mounts | ||
298 | * @s: seq_file structure | ||
299 | * @mnt: vfsmount | ||
300 | * | ||
301 | * Returns: 0 on success or error code | ||
302 | */ | ||
303 | |||
304 | static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | ||
305 | { | ||
306 | struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; | ||
307 | struct gfs2_args *args = &sdp->sd_args; | ||
308 | |||
309 | if (args->ar_lockproto[0]) | ||
310 | seq_printf(s, ",lockproto=%s", args->ar_lockproto); | ||
311 | if (args->ar_locktable[0]) | ||
312 | seq_printf(s, ",locktable=%s", args->ar_locktable); | ||
313 | if (args->ar_hostdata[0]) | ||
314 | seq_printf(s, ",hostdata=%s", args->ar_hostdata); | ||
315 | if (args->ar_spectator) | ||
316 | seq_printf(s, ",spectator"); | ||
317 | if (args->ar_ignore_local_fs) | ||
318 | seq_printf(s, ",ignore_local_fs"); | ||
319 | if (args->ar_localflocks) | ||
320 | seq_printf(s, ",localflocks"); | ||
321 | if (args->ar_localcaching) | ||
322 | seq_printf(s, ",localcaching"); | ||
323 | if (args->ar_debug) | ||
324 | seq_printf(s, ",debug"); | ||
325 | if (args->ar_upgrade) | ||
326 | seq_printf(s, ",upgrade"); | ||
327 | if (args->ar_num_glockd != GFS2_GLOCKD_DEFAULT) | ||
328 | seq_printf(s, ",num_glockd=%u", args->ar_num_glockd); | ||
329 | if (args->ar_posix_acl) | ||
330 | seq_printf(s, ",acl"); | ||
331 | if (args->ar_quota != GFS2_QUOTA_DEFAULT) { | ||
332 | char *state; | ||
333 | switch (args->ar_quota) { | ||
334 | case GFS2_QUOTA_OFF: | ||
335 | state = "off"; | ||
336 | break; | ||
337 | case GFS2_QUOTA_ACCOUNT: | ||
338 | state = "account"; | ||
339 | break; | ||
340 | case GFS2_QUOTA_ON: | ||
341 | state = "on"; | ||
342 | break; | ||
343 | default: | ||
344 | state = "unknown"; | ||
345 | break; | ||
346 | } | ||
347 | seq_printf(s, ",quota=%s", state); | ||
348 | } | ||
349 | if (args->ar_suiddir) | ||
350 | seq_printf(s, ",suiddir"); | ||
351 | if (args->ar_data != GFS2_DATA_DEFAULT) { | ||
352 | char *state; | ||
353 | switch (args->ar_data) { | ||
354 | case GFS2_DATA_WRITEBACK: | ||
355 | state = "writeback"; | ||
356 | break; | ||
357 | case GFS2_DATA_ORDERED: | ||
358 | state = "ordered"; | ||
359 | break; | ||
360 | default: | ||
361 | state = "unknown"; | ||
362 | break; | ||
363 | } | ||
364 | seq_printf(s, ",data=%s", state); | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * We have to (at the moment) hold the inodes main lock to cover | ||
372 | * the gap between unlocking the shared lock on the iopen lock and | ||
373 | * taking the exclusive lock. I'd rather do a shared -> exclusive | ||
374 | * conversion on the iopen lock, but we can change that later. This | ||
375 | * is safe, just less efficient. | ||
376 | */ | ||
377 | static void gfs2_delete_inode(struct inode *inode) | ||
378 | { | ||
379 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
380 | struct gfs2_inode *ip = GFS2_I(inode); | ||
381 | struct gfs2_holder gh; | ||
382 | int error; | ||
383 | |||
384 | if (!inode->i_private) | ||
385 | goto out; | ||
386 | |||
387 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh); | ||
388 | if (unlikely(error)) { | ||
389 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
390 | goto out; | ||
391 | } | ||
392 | |||
393 | gfs2_glock_dq(&ip->i_iopen_gh); | ||
394 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | ||
395 | error = gfs2_glock_nq(&ip->i_iopen_gh); | ||
396 | if (error) | ||
397 | goto out_uninit; | ||
398 | |||
399 | if (S_ISDIR(ip->i_di.di_mode) && | ||
400 | (ip->i_di.di_flags & GFS2_DIF_EXHASH)) { | ||
401 | error = gfs2_dir_exhash_dealloc(ip); | ||
402 | if (error) | ||
403 | goto out_unlock; | ||
404 | } | ||
405 | |||
406 | if (ip->i_di.di_eattr) { | ||
407 | error = gfs2_ea_dealloc(ip); | ||
408 | if (error) | ||
409 | goto out_unlock; | ||
410 | } | ||
411 | |||
412 | if (!gfs2_is_stuffed(ip)) { | ||
413 | error = gfs2_file_dealloc(ip); | ||
414 | if (error) | ||
415 | goto out_unlock; | ||
416 | } | ||
417 | |||
418 | error = gfs2_dinode_dealloc(ip); | ||
419 | |||
420 | out_unlock: | ||
421 | gfs2_glock_dq(&ip->i_iopen_gh); | ||
422 | out_uninit: | ||
423 | gfs2_holder_uninit(&ip->i_iopen_gh); | ||
424 | gfs2_glock_dq_uninit(&gh); | ||
425 | if (error) | ||
426 | fs_warn(sdp, "gfs2_delete_inode: %d\n", error); | ||
427 | out: | ||
428 | truncate_inode_pages(&inode->i_data, 0); | ||
429 | clear_inode(inode); | ||
430 | } | ||
431 | |||
432 | |||
433 | |||
434 | static struct inode *gfs2_alloc_inode(struct super_block *sb) | ||
435 | { | ||
436 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
437 | struct gfs2_inode *ip; | ||
438 | |||
439 | ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL); | ||
440 | if (ip) { | ||
441 | ip->i_flags = 0; | ||
442 | ip->i_gl = NULL; | ||
443 | ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default); | ||
444 | ip->i_last_pfault = jiffies; | ||
445 | } | ||
446 | return &ip->i_inode; | ||
447 | } | ||
448 | |||
449 | static void gfs2_destroy_inode(struct inode *inode) | ||
450 | { | ||
451 | kmem_cache_free(gfs2_inode_cachep, inode); | ||
452 | } | ||
453 | |||
454 | struct super_operations gfs2_super_ops = { | ||
455 | .alloc_inode = gfs2_alloc_inode, | ||
456 | .destroy_inode = gfs2_destroy_inode, | ||
457 | .write_inode = gfs2_write_inode, | ||
458 | .delete_inode = gfs2_delete_inode, | ||
459 | .put_super = gfs2_put_super, | ||
460 | .write_super = gfs2_write_super, | ||
461 | .write_super_lockfs = gfs2_write_super_lockfs, | ||
462 | .unlockfs = gfs2_unlockfs, | ||
463 | .statfs = gfs2_statfs, | ||
464 | .remount_fs = gfs2_remount_fs, | ||
465 | .clear_inode = gfs2_clear_inode, | ||
466 | .show_options = gfs2_show_options, | ||
467 | }; | ||
468 | |||