diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 149 |
1 files changed, 137 insertions, 12 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index d5355d9b5926..777783deddcb 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 | /** |
@@ -260,6 +256,137 @@ static void gfs2_unlockfs(struct super_block *sb) | |||
260 | } | 256 | } |
261 | 257 | ||
262 | /** | 258 | /** |
259 | * statfs_fill - fill in the sg for a given RG | ||
260 | * @rgd: the RG | ||
261 | * @sc: the sc structure | ||
262 | * | ||
263 | * Returns: 0 on success, -ESTALE if the LVB is invalid | ||
264 | */ | ||
265 | |||
266 | static int statfs_slow_fill(struct gfs2_rgrpd *rgd, | ||
267 | struct gfs2_statfs_change_host *sc) | ||
268 | { | ||
269 | gfs2_rgrp_verify(rgd); | ||
270 | sc->sc_total += rgd->rd_data; | ||
271 | sc->sc_free += rgd->rd_free; | ||
272 | sc->sc_dinodes += rgd->rd_dinodes; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * gfs2_statfs_slow - Stat a filesystem using asynchronous locking | ||
278 | * @sdp: the filesystem | ||
279 | * @sc: the sc info that will be returned | ||
280 | * | ||
281 | * Any error (other than a signal) will cause this routine to fall back | ||
282 | * to the synchronous version. | ||
283 | * | ||
284 | * FIXME: This really shouldn't busy wait like this. | ||
285 | * | ||
286 | * Returns: errno | ||
287 | */ | ||
288 | |||
289 | static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
290 | { | ||
291 | struct gfs2_holder ri_gh; | ||
292 | struct gfs2_rgrpd *rgd_next; | ||
293 | struct gfs2_holder *gha, *gh; | ||
294 | unsigned int slots = 64; | ||
295 | unsigned int x; | ||
296 | int done; | ||
297 | int error = 0, err; | ||
298 | |||
299 | memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); | ||
300 | gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL); | ||
301 | if (!gha) | ||
302 | return -ENOMEM; | ||
303 | |||
304 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
305 | if (error) | ||
306 | goto out; | ||
307 | |||
308 | rgd_next = gfs2_rgrpd_get_first(sdp); | ||
309 | |||
310 | for (;;) { | ||
311 | done = 1; | ||
312 | |||
313 | for (x = 0; x < slots; x++) { | ||
314 | gh = gha + x; | ||
315 | |||
316 | if (gh->gh_gl && gfs2_glock_poll(gh)) { | ||
317 | err = gfs2_glock_wait(gh); | ||
318 | if (err) { | ||
319 | gfs2_holder_uninit(gh); | ||
320 | error = err; | ||
321 | } else { | ||
322 | if (!error) | ||
323 | error = statfs_slow_fill( | ||
324 | gh->gh_gl->gl_object, sc); | ||
325 | gfs2_glock_dq_uninit(gh); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | if (gh->gh_gl) | ||
330 | done = 0; | ||
331 | else if (rgd_next && !error) { | ||
332 | error = gfs2_glock_nq_init(rgd_next->rd_gl, | ||
333 | LM_ST_SHARED, | ||
334 | GL_ASYNC, | ||
335 | gh); | ||
336 | rgd_next = gfs2_rgrpd_get_next(rgd_next); | ||
337 | done = 0; | ||
338 | } | ||
339 | |||
340 | if (signal_pending(current)) | ||
341 | error = -ERESTARTSYS; | ||
342 | } | ||
343 | |||
344 | if (done) | ||
345 | break; | ||
346 | |||
347 | yield(); | ||
348 | } | ||
349 | |||
350 | gfs2_glock_dq_uninit(&ri_gh); | ||
351 | |||
352 | out: | ||
353 | kfree(gha); | ||
354 | return error; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * gfs2_statfs_i - Do a statfs | ||
359 | * @sdp: the filesystem | ||
360 | * @sg: the sg structure | ||
361 | * | ||
362 | * Returns: errno | ||
363 | */ | ||
364 | |||
365 | static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
366 | { | ||
367 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
368 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
369 | |||
370 | spin_lock(&sdp->sd_statfs_spin); | ||
371 | |||
372 | *sc = *m_sc; | ||
373 | sc->sc_total += l_sc->sc_total; | ||
374 | sc->sc_free += l_sc->sc_free; | ||
375 | sc->sc_dinodes += l_sc->sc_dinodes; | ||
376 | |||
377 | spin_unlock(&sdp->sd_statfs_spin); | ||
378 | |||
379 | if (sc->sc_free < 0) | ||
380 | sc->sc_free = 0; | ||
381 | if (sc->sc_free > sc->sc_total) | ||
382 | sc->sc_free = sc->sc_total; | ||
383 | if (sc->sc_dinodes < 0) | ||
384 | sc->sc_dinodes = 0; | ||
385 | |||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | /** | ||
263 | * gfs2_statfs - Gather and return stats about the filesystem | 390 | * gfs2_statfs - Gather and return stats about the filesystem |
264 | * @sb: The superblock | 391 | * @sb: The superblock |
265 | * @statfsbuf: The buffer | 392 | * @statfsbuf: The buffer |
@@ -370,7 +497,6 @@ static void gfs2_clear_inode(struct inode *inode) | |||
370 | */ | 497 | */ |
371 | if (test_bit(GIF_USER, &ip->i_flags)) { | 498 | if (test_bit(GIF_USER, &ip->i_flags)) { |
372 | ip->i_gl->gl_object = NULL; | 499 | ip->i_gl->gl_object = NULL; |
373 | gfs2_glock_schedule_for_reclaim(ip->i_gl); | ||
374 | gfs2_glock_put(ip->i_gl); | 500 | gfs2_glock_put(ip->i_gl); |
375 | ip->i_gl = NULL; | 501 | ip->i_gl = NULL; |
376 | if (ip->i_iopen_gh.gh_gl) { | 502 | if (ip->i_iopen_gh.gh_gl) { |
@@ -423,8 +549,6 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
423 | seq_printf(s, ",debug"); | 549 | seq_printf(s, ",debug"); |
424 | if (args->ar_upgrade) | 550 | if (args->ar_upgrade) |
425 | seq_printf(s, ",upgrade"); | 551 | 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) | 552 | if (args->ar_posix_acl) |
429 | seq_printf(s, ",acl"); | 553 | seq_printf(s, ",acl"); |
430 | if (args->ar_quota != GFS2_QUOTA_DEFAULT) { | 554 | if (args->ar_quota != GFS2_QUOTA_DEFAULT) { |
@@ -494,16 +618,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); | 618 | 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); | 619 | error = gfs2_glock_nq(&ip->i_iopen_gh); |
496 | if (error) | 620 | if (error) |
497 | goto out_uninit; | 621 | goto out_truncate; |
498 | 622 | ||
499 | if (S_ISDIR(inode->i_mode) && | 623 | if (S_ISDIR(inode->i_mode) && |
500 | (ip->i_di.di_flags & GFS2_DIF_EXHASH)) { | 624 | (ip->i_diskflags & GFS2_DIF_EXHASH)) { |
501 | error = gfs2_dir_exhash_dealloc(ip); | 625 | error = gfs2_dir_exhash_dealloc(ip); |
502 | if (error) | 626 | if (error) |
503 | goto out_unlock; | 627 | goto out_unlock; |
504 | } | 628 | } |
505 | 629 | ||
506 | if (ip->i_di.di_eattr) { | 630 | if (ip->i_eattr) { |
507 | error = gfs2_ea_dealloc(ip); | 631 | error = gfs2_ea_dealloc(ip); |
508 | if (error) | 632 | if (error) |
509 | goto out_unlock; | 633 | goto out_unlock; |
@@ -519,6 +643,7 @@ static void gfs2_delete_inode(struct inode *inode) | |||
519 | if (error) | 643 | if (error) |
520 | goto out_unlock; | 644 | goto out_unlock; |
521 | 645 | ||
646 | out_truncate: | ||
522 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 647 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
523 | if (error) | 648 | if (error) |
524 | goto out_unlock; | 649 | goto out_unlock; |
@@ -527,8 +652,8 @@ static void gfs2_delete_inode(struct inode *inode) | |||
527 | gfs2_trans_end(sdp); | 652 | gfs2_trans_end(sdp); |
528 | 653 | ||
529 | out_unlock: | 654 | out_unlock: |
530 | gfs2_glock_dq(&ip->i_iopen_gh); | 655 | if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) |
531 | out_uninit: | 656 | gfs2_glock_dq(&ip->i_iopen_gh); |
532 | gfs2_holder_uninit(&ip->i_iopen_gh); | 657 | gfs2_holder_uninit(&ip->i_iopen_gh); |
533 | gfs2_glock_dq_uninit(&gh); | 658 | gfs2_glock_dq_uninit(&gh); |
534 | if (error && error != GLR_TRYFAILED) | 659 | if (error && error != GLR_TRYFAILED) |