diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 165 |
1 files changed, 146 insertions, 19 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index d5355d9b5926..320323d03479 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "inode.h" | 28 | #include "inode.h" |
29 | #include "log.h" | 29 | #include "log.h" |
30 | #include "mount.h" | 30 | #include "mount.h" |
31 | #include "ops_super.h" | ||
32 | #include "quota.h" | 31 | #include "quota.h" |
33 | #include "recovery.h" | 32 | #include "recovery.h" |
34 | #include "rgrp.h" | 33 | #include "rgrp.h" |
@@ -143,8 +142,6 @@ static void gfs2_put_super(struct super_block *sb) | |||
143 | kthread_stop(sdp->sd_quotad_process); | 142 | kthread_stop(sdp->sd_quotad_process); |
144 | kthread_stop(sdp->sd_logd_process); | 143 | kthread_stop(sdp->sd_logd_process); |
145 | kthread_stop(sdp->sd_recoverd_process); | 144 | kthread_stop(sdp->sd_recoverd_process); |
146 | while (sdp->sd_glockd_num--) | ||
147 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); | ||
148 | 145 | ||
149 | if (!(sb->s_flags & MS_RDONLY)) { | 146 | if (!(sb->s_flags & MS_RDONLY)) { |
150 | error = gfs2_make_fs_ro(sdp); | 147 | error = gfs2_make_fs_ro(sdp); |
@@ -185,7 +182,6 @@ static void gfs2_put_super(struct super_block *sb) | |||
185 | 182 | ||
186 | /* At this point, we're through participating in the lockspace */ | 183 | /* At this point, we're through participating in the lockspace */ |
187 | gfs2_sys_fs_del(sdp); | 184 | gfs2_sys_fs_del(sdp); |
188 | kfree(sdp); | ||
189 | } | 185 | } |
190 | 186 | ||
191 | /** | 187 | /** |
@@ -215,18 +211,18 @@ static int gfs2_sync_fs(struct super_block *sb, int wait) | |||
215 | } | 211 | } |
216 | 212 | ||
217 | /** | 213 | /** |
218 | * gfs2_write_super_lockfs - prevent further writes to the filesystem | 214 | * gfs2_freeze - prevent further writes to the filesystem |
219 | * @sb: the VFS structure for the filesystem | 215 | * @sb: the VFS structure for the filesystem |
220 | * | 216 | * |
221 | */ | 217 | */ |
222 | 218 | ||
223 | static void gfs2_write_super_lockfs(struct super_block *sb) | 219 | static int gfs2_freeze(struct super_block *sb) |
224 | { | 220 | { |
225 | struct gfs2_sbd *sdp = sb->s_fs_info; | 221 | struct gfs2_sbd *sdp = sb->s_fs_info; |
226 | int error; | 222 | int error; |
227 | 223 | ||
228 | if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | 224 | if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) |
229 | return; | 225 | return -EINVAL; |
230 | 226 | ||
231 | for (;;) { | 227 | for (;;) { |
232 | error = gfs2_freeze_fs(sdp); | 228 | error = gfs2_freeze_fs(sdp); |
@@ -246,17 +242,150 @@ static void gfs2_write_super_lockfs(struct super_block *sb) | |||
246 | fs_err(sdp, "retrying...\n"); | 242 | fs_err(sdp, "retrying...\n"); |
247 | msleep(1000); | 243 | msleep(1000); |
248 | } | 244 | } |
245 | return 0; | ||
249 | } | 246 | } |
250 | 247 | ||
251 | /** | 248 | /** |
252 | * gfs2_unlockfs - reallow writes to the filesystem | 249 | * gfs2_unfreeze - reallow writes to the filesystem |
253 | * @sb: the VFS structure for the filesystem | 250 | * @sb: the VFS structure for the filesystem |
254 | * | 251 | * |
255 | */ | 252 | */ |
256 | 253 | ||
257 | static void gfs2_unlockfs(struct super_block *sb) | 254 | static int gfs2_unfreeze(struct super_block *sb) |
258 | { | 255 | { |
259 | gfs2_unfreeze_fs(sb->s_fs_info); | 256 | gfs2_unfreeze_fs(sb->s_fs_info); |
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * statfs_fill - fill in the sg for a given RG | ||
262 | * @rgd: the RG | ||
263 | * @sc: the sc structure | ||
264 | * | ||
265 | * Returns: 0 on success, -ESTALE if the LVB is invalid | ||
266 | */ | ||
267 | |||
268 | static int statfs_slow_fill(struct gfs2_rgrpd *rgd, | ||
269 | struct gfs2_statfs_change_host *sc) | ||
270 | { | ||
271 | gfs2_rgrp_verify(rgd); | ||
272 | sc->sc_total += rgd->rd_data; | ||
273 | sc->sc_free += rgd->rd_free; | ||
274 | sc->sc_dinodes += rgd->rd_dinodes; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * gfs2_statfs_slow - Stat a filesystem using asynchronous locking | ||
280 | * @sdp: the filesystem | ||
281 | * @sc: the sc info that will be returned | ||
282 | * | ||
283 | * Any error (other than a signal) will cause this routine to fall back | ||
284 | * to the synchronous version. | ||
285 | * | ||
286 | * FIXME: This really shouldn't busy wait like this. | ||
287 | * | ||
288 | * Returns: errno | ||
289 | */ | ||
290 | |||
291 | static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
292 | { | ||
293 | struct gfs2_holder ri_gh; | ||
294 | struct gfs2_rgrpd *rgd_next; | ||
295 | struct gfs2_holder *gha, *gh; | ||
296 | unsigned int slots = 64; | ||
297 | unsigned int x; | ||
298 | int done; | ||
299 | int error = 0, err; | ||
300 | |||
301 | memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); | ||
302 | gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL); | ||
303 | if (!gha) | ||
304 | return -ENOMEM; | ||
305 | |||
306 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
307 | if (error) | ||
308 | goto out; | ||
309 | |||
310 | rgd_next = gfs2_rgrpd_get_first(sdp); | ||
311 | |||
312 | for (;;) { | ||
313 | done = 1; | ||
314 | |||
315 | for (x = 0; x < slots; x++) { | ||
316 | gh = gha + x; | ||
317 | |||
318 | if (gh->gh_gl && gfs2_glock_poll(gh)) { | ||
319 | err = gfs2_glock_wait(gh); | ||
320 | if (err) { | ||
321 | gfs2_holder_uninit(gh); | ||
322 | error = err; | ||
323 | } else { | ||
324 | if (!error) | ||
325 | error = statfs_slow_fill( | ||
326 | gh->gh_gl->gl_object, sc); | ||
327 | gfs2_glock_dq_uninit(gh); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | if (gh->gh_gl) | ||
332 | done = 0; | ||
333 | else if (rgd_next && !error) { | ||
334 | error = gfs2_glock_nq_init(rgd_next->rd_gl, | ||
335 | LM_ST_SHARED, | ||
336 | GL_ASYNC, | ||
337 | gh); | ||
338 | rgd_next = gfs2_rgrpd_get_next(rgd_next); | ||
339 | done = 0; | ||
340 | } | ||
341 | |||
342 | if (signal_pending(current)) | ||
343 | error = -ERESTARTSYS; | ||
344 | } | ||
345 | |||
346 | if (done) | ||
347 | break; | ||
348 | |||
349 | yield(); | ||
350 | } | ||
351 | |||
352 | gfs2_glock_dq_uninit(&ri_gh); | ||
353 | |||
354 | out: | ||
355 | kfree(gha); | ||
356 | return error; | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * gfs2_statfs_i - Do a statfs | ||
361 | * @sdp: the filesystem | ||
362 | * @sg: the sg structure | ||
363 | * | ||
364 | * Returns: errno | ||
365 | */ | ||
366 | |||
367 | static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
368 | { | ||
369 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
370 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
371 | |||
372 | spin_lock(&sdp->sd_statfs_spin); | ||
373 | |||
374 | *sc = *m_sc; | ||
375 | sc->sc_total += l_sc->sc_total; | ||
376 | sc->sc_free += l_sc->sc_free; | ||
377 | sc->sc_dinodes += l_sc->sc_dinodes; | ||
378 | |||
379 | spin_unlock(&sdp->sd_statfs_spin); | ||
380 | |||
381 | if (sc->sc_free < 0) | ||
382 | sc->sc_free = 0; | ||
383 | if (sc->sc_free > sc->sc_total) | ||
384 | sc->sc_free = sc->sc_total; | ||
385 | if (sc->sc_dinodes < 0) | ||
386 | sc->sc_dinodes = 0; | ||
387 | |||
388 | return 0; | ||
260 | } | 389 | } |
261 | 390 | ||
262 | /** | 391 | /** |
@@ -370,7 +499,6 @@ static void gfs2_clear_inode(struct inode *inode) | |||
370 | */ | 499 | */ |
371 | if (test_bit(GIF_USER, &ip->i_flags)) { | 500 | if (test_bit(GIF_USER, &ip->i_flags)) { |
372 | ip->i_gl->gl_object = NULL; | 501 | ip->i_gl->gl_object = NULL; |
373 | gfs2_glock_schedule_for_reclaim(ip->i_gl); | ||
374 | gfs2_glock_put(ip->i_gl); | 502 | gfs2_glock_put(ip->i_gl); |
375 | ip->i_gl = NULL; | 503 | ip->i_gl = NULL; |
376 | if (ip->i_iopen_gh.gh_gl) { | 504 | if (ip->i_iopen_gh.gh_gl) { |
@@ -423,8 +551,6 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
423 | seq_printf(s, ",debug"); | 551 | seq_printf(s, ",debug"); |
424 | if (args->ar_upgrade) | 552 | if (args->ar_upgrade) |
425 | seq_printf(s, ",upgrade"); | 553 | seq_printf(s, ",upgrade"); |
426 | if (args->ar_num_glockd != GFS2_GLOCKD_DEFAULT) | ||
427 | seq_printf(s, ",num_glockd=%u", args->ar_num_glockd); | ||
428 | if (args->ar_posix_acl) | 554 | if (args->ar_posix_acl) |
429 | seq_printf(s, ",acl"); | 555 | seq_printf(s, ",acl"); |
430 | if (args->ar_quota != GFS2_QUOTA_DEFAULT) { | 556 | if (args->ar_quota != GFS2_QUOTA_DEFAULT) { |
@@ -494,16 +620,16 @@ static void gfs2_delete_inode(struct inode *inode) | |||
494 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 620 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
495 | error = gfs2_glock_nq(&ip->i_iopen_gh); | 621 | error = gfs2_glock_nq(&ip->i_iopen_gh); |
496 | if (error) | 622 | if (error) |
497 | goto out_uninit; | 623 | goto out_truncate; |
498 | 624 | ||
499 | if (S_ISDIR(inode->i_mode) && | 625 | if (S_ISDIR(inode->i_mode) && |
500 | (ip->i_di.di_flags & GFS2_DIF_EXHASH)) { | 626 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { |
501 | error = gfs2_dir_exhash_dealloc(ip); | 627 | error = gfs2_dir_exhash_dealloc(ip); |
502 | if (error) | 628 | if (error) |
503 | goto out_unlock; | 629 | goto out_unlock; |
504 | } | 630 | } |
505 | 631 | ||
506 | if (ip->i_di.di_eattr) { | 632 | if (ip->i_eattr) { |
507 | error = gfs2_ea_dealloc(ip); | 633 | error = gfs2_ea_dealloc(ip); |
508 | if (error) | 634 | if (error) |
509 | goto out_unlock; | 635 | goto out_unlock; |
@@ -519,6 +645,7 @@ static void gfs2_delete_inode(struct inode *inode) | |||
519 | if (error) | 645 | if (error) |
520 | goto out_unlock; | 646 | goto out_unlock; |
521 | 647 | ||
648 | out_truncate: | ||
522 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 649 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
523 | if (error) | 650 | if (error) |
524 | goto out_unlock; | 651 | goto out_unlock; |
@@ -527,8 +654,8 @@ static void gfs2_delete_inode(struct inode *inode) | |||
527 | gfs2_trans_end(sdp); | 654 | gfs2_trans_end(sdp); |
528 | 655 | ||
529 | out_unlock: | 656 | out_unlock: |
530 | gfs2_glock_dq(&ip->i_iopen_gh); | 657 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) |
531 | out_uninit: | 658 | gfs2_glock_dq(&ip->i_iopen_gh); |
532 | gfs2_holder_uninit(&ip->i_iopen_gh); | 659 | gfs2_holder_uninit(&ip->i_iopen_gh); |
533 | gfs2_glock_dq_uninit(&gh); | 660 | gfs2_glock_dq_uninit(&gh); |
534 | if (error && error != GLR_TRYFAILED) | 661 | if (error && error != GLR_TRYFAILED) |
@@ -563,8 +690,8 @@ const struct super_operations gfs2_super_ops = { | |||
563 | .put_super = gfs2_put_super, | 690 | .put_super = gfs2_put_super, |
564 | .write_super = gfs2_write_super, | 691 | .write_super = gfs2_write_super, |
565 | .sync_fs = gfs2_sync_fs, | 692 | .sync_fs = gfs2_sync_fs, |
566 | .write_super_lockfs = gfs2_write_super_lockfs, | 693 | .freeze_fs = gfs2_freeze, |
567 | .unlockfs = gfs2_unlockfs, | 694 | .unfreeze_fs = gfs2_unfreeze, |
568 | .statfs = gfs2_statfs, | 695 | .statfs = gfs2_statfs, |
569 | .remount_fs = gfs2_remount_fs, | 696 | .remount_fs = gfs2_remount_fs, |
570 | .clear_inode = gfs2_clear_inode, | 697 | .clear_inode = gfs2_clear_inode, |