aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r--fs/gfs2/ops_super.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 29f8a5c0b45b..08837a728635 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -257,6 +257,137 @@ static void gfs2_unlockfs(struct super_block *sb)
257} 257}
258 258
259/** 259/**
260 * statfs_fill - fill in the sg for a given RG
261 * @rgd: the RG
262 * @sc: the sc structure
263 *
264 * Returns: 0 on success, -ESTALE if the LVB is invalid
265 */
266
267static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
268 struct gfs2_statfs_change_host *sc)
269{
270 gfs2_rgrp_verify(rgd);
271 sc->sc_total += rgd->rd_data;
272 sc->sc_free += rgd->rd_free;
273 sc->sc_dinodes += rgd->rd_dinodes;
274 return 0;
275}
276
277/**
278 * gfs2_statfs_slow - Stat a filesystem using asynchronous locking
279 * @sdp: the filesystem
280 * @sc: the sc info that will be returned
281 *
282 * Any error (other than a signal) will cause this routine to fall back
283 * to the synchronous version.
284 *
285 * FIXME: This really shouldn't busy wait like this.
286 *
287 * Returns: errno
288 */
289
290static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
291{
292 struct gfs2_holder ri_gh;
293 struct gfs2_rgrpd *rgd_next;
294 struct gfs2_holder *gha, *gh;
295 unsigned int slots = 64;
296 unsigned int x;
297 int done;
298 int error = 0, err;
299
300 memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
301 gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
302 if (!gha)
303 return -ENOMEM;
304
305 error = gfs2_rindex_hold(sdp, &ri_gh);
306 if (error)
307 goto out;
308
309 rgd_next = gfs2_rgrpd_get_first(sdp);
310
311 for (;;) {
312 done = 1;
313
314 for (x = 0; x < slots; x++) {
315 gh = gha + x;
316
317 if (gh->gh_gl && gfs2_glock_poll(gh)) {
318 err = gfs2_glock_wait(gh);
319 if (err) {
320 gfs2_holder_uninit(gh);
321 error = err;
322 } else {
323 if (!error)
324 error = statfs_slow_fill(
325 gh->gh_gl->gl_object, sc);
326 gfs2_glock_dq_uninit(gh);
327 }
328 }
329
330 if (gh->gh_gl)
331 done = 0;
332 else if (rgd_next && !error) {
333 error = gfs2_glock_nq_init(rgd_next->rd_gl,
334 LM_ST_SHARED,
335 GL_ASYNC,
336 gh);
337 rgd_next = gfs2_rgrpd_get_next(rgd_next);
338 done = 0;
339 }
340
341 if (signal_pending(current))
342 error = -ERESTARTSYS;
343 }
344
345 if (done)
346 break;
347
348 yield();
349 }
350
351 gfs2_glock_dq_uninit(&ri_gh);
352
353out:
354 kfree(gha);
355 return error;
356}
357
358/**
359 * gfs2_statfs_i - Do a statfs
360 * @sdp: the filesystem
361 * @sg: the sg structure
362 *
363 * Returns: errno
364 */
365
366static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
367{
368 struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
369 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
370
371 spin_lock(&sdp->sd_statfs_spin);
372
373 *sc = *m_sc;
374 sc->sc_total += l_sc->sc_total;
375 sc->sc_free += l_sc->sc_free;
376 sc->sc_dinodes += l_sc->sc_dinodes;
377
378 spin_unlock(&sdp->sd_statfs_spin);
379
380 if (sc->sc_free < 0)
381 sc->sc_free = 0;
382 if (sc->sc_free > sc->sc_total)
383 sc->sc_free = sc->sc_total;
384 if (sc->sc_dinodes < 0)
385 sc->sc_dinodes = 0;
386
387 return 0;
388}
389
390/**
260 * gfs2_statfs - Gather and return stats about the filesystem 391 * gfs2_statfs - Gather and return stats about the filesystem
261 * @sb: The superblock 392 * @sb: The superblock
262 * @statfsbuf: The buffer 393 * @statfsbuf: The buffer