diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 131 |
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 | |||
267 | static 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 | |||
290 | static 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 | |||
353 | out: | ||
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 | |||
366 | static 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 |