.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
---|
3 | 4 | * Copyright (C) 2004-2008 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 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | #include <linux/sched.h> |
---|
.. | .. |
---|
189 | 186 | static void gfs2_meta_read_endio(struct bio *bio) |
---|
190 | 187 | { |
---|
191 | 188 | struct bio_vec *bvec; |
---|
192 | | - int i; |
---|
| 189 | + struct bvec_iter_all iter_all; |
---|
193 | 190 | |
---|
194 | | - bio_for_each_segment_all(bvec, bio, i) { |
---|
| 191 | + bio_for_each_segment_all(bvec, bio, iter_all) { |
---|
195 | 192 | struct page *page = bvec->bv_page; |
---|
196 | 193 | struct buffer_head *bh = page_buffers(page); |
---|
197 | 194 | unsigned int len = bvec->bv_len; |
---|
.. | .. |
---|
254 | 251 | struct buffer_head *bh, *bhs[2]; |
---|
255 | 252 | int num = 0; |
---|
256 | 253 | |
---|
257 | | - if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { |
---|
| 254 | + if (unlikely(gfs2_withdrawn(sdp)) && |
---|
| 255 | + (!sdp->sd_jdesc || gl != sdp->sd_jinode_gl)) { |
---|
258 | 256 | *bhp = NULL; |
---|
259 | 257 | return -EIO; |
---|
260 | 258 | } |
---|
.. | .. |
---|
312 | 310 | |
---|
313 | 311 | int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh) |
---|
314 | 312 | { |
---|
315 | | - if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
---|
| 313 | + if (unlikely(gfs2_withdrawn(sdp))) |
---|
316 | 314 | return -EIO; |
---|
317 | 315 | |
---|
318 | 316 | wait_on_buffer(bh); |
---|
.. | .. |
---|
323 | 321 | gfs2_io_error_bh_wd(sdp, bh); |
---|
324 | 322 | return -EIO; |
---|
325 | 323 | } |
---|
326 | | - if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
---|
| 324 | + if (unlikely(gfs2_withdrawn(sdp))) |
---|
327 | 325 | return -EIO; |
---|
328 | 326 | |
---|
329 | 327 | return 0; |
---|
.. | .. |
---|
350 | 348 | brelse(bh); |
---|
351 | 349 | } |
---|
352 | 350 | if (bd) { |
---|
353 | | - spin_lock(&sdp->sd_ail_lock); |
---|
354 | 351 | if (bd->bd_tr) { |
---|
355 | 352 | gfs2_trans_add_revoke(sdp, bd); |
---|
356 | 353 | } else if (was_pinned) { |
---|
357 | 354 | bh->b_private = NULL; |
---|
358 | 355 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
---|
| 356 | + } else if (!list_empty(&bd->bd_ail_st_list) && |
---|
| 357 | + !list_empty(&bd->bd_ail_gl_list)) { |
---|
| 358 | + gfs2_remove_from_ail(bd); |
---|
359 | 359 | } |
---|
360 | | - spin_unlock(&sdp->sd_ail_lock); |
---|
361 | 360 | } |
---|
362 | 361 | clear_buffer_dirty(bh); |
---|
363 | 362 | clear_buffer_uptodate(bh); |
---|
364 | 363 | } |
---|
365 | 364 | |
---|
366 | 365 | /** |
---|
367 | | - * gfs2_meta_wipe - make inode's buffers so they aren't dirty/pinned anymore |
---|
| 366 | + * gfs2_ail1_wipe - remove deleted/freed buffers from the ail1 list |
---|
| 367 | + * @sdp: superblock |
---|
| 368 | + * @bstart: starting block address of buffers to remove |
---|
| 369 | + * @blen: length of buffers to be removed |
---|
| 370 | + * |
---|
| 371 | + * This function is called from gfs2_journal wipe, whose job is to remove |
---|
| 372 | + * buffers, corresponding to deleted blocks, from the journal. If we find any |
---|
| 373 | + * bufdata elements on the system ail1 list, they haven't been written to |
---|
| 374 | + * the journal yet. So we remove them. |
---|
| 375 | + */ |
---|
| 376 | +static void gfs2_ail1_wipe(struct gfs2_sbd *sdp, u64 bstart, u32 blen) |
---|
| 377 | +{ |
---|
| 378 | + struct gfs2_trans *tr, *s; |
---|
| 379 | + struct gfs2_bufdata *bd, *bs; |
---|
| 380 | + struct buffer_head *bh; |
---|
| 381 | + u64 end = bstart + blen; |
---|
| 382 | + |
---|
| 383 | + gfs2_log_lock(sdp); |
---|
| 384 | + spin_lock(&sdp->sd_ail_lock); |
---|
| 385 | + list_for_each_entry_safe(tr, s, &sdp->sd_ail1_list, tr_list) { |
---|
| 386 | + list_for_each_entry_safe(bd, bs, &tr->tr_ail1_list, |
---|
| 387 | + bd_ail_st_list) { |
---|
| 388 | + bh = bd->bd_bh; |
---|
| 389 | + if (bh->b_blocknr < bstart || bh->b_blocknr >= end) |
---|
| 390 | + continue; |
---|
| 391 | + |
---|
| 392 | + gfs2_remove_from_journal(bh, REMOVE_JDATA); |
---|
| 393 | + } |
---|
| 394 | + } |
---|
| 395 | + spin_unlock(&sdp->sd_ail_lock); |
---|
| 396 | + gfs2_log_unlock(sdp); |
---|
| 397 | +} |
---|
| 398 | + |
---|
| 399 | +static struct buffer_head *gfs2_getjdatabuf(struct gfs2_inode *ip, u64 blkno) |
---|
| 400 | +{ |
---|
| 401 | + struct address_space *mapping = ip->i_inode.i_mapping; |
---|
| 402 | + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
---|
| 403 | + struct page *page; |
---|
| 404 | + struct buffer_head *bh; |
---|
| 405 | + unsigned int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift; |
---|
| 406 | + unsigned long index = blkno >> shift; /* convert block to page */ |
---|
| 407 | + unsigned int bufnum = blkno - (index << shift); |
---|
| 408 | + |
---|
| 409 | + page = find_get_page_flags(mapping, index, FGP_LOCK|FGP_ACCESSED); |
---|
| 410 | + if (!page) |
---|
| 411 | + return NULL; |
---|
| 412 | + if (!page_has_buffers(page)) { |
---|
| 413 | + unlock_page(page); |
---|
| 414 | + put_page(page); |
---|
| 415 | + return NULL; |
---|
| 416 | + } |
---|
| 417 | + /* Locate header for our buffer within our page */ |
---|
| 418 | + for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page) |
---|
| 419 | + /* Do nothing */; |
---|
| 420 | + get_bh(bh); |
---|
| 421 | + unlock_page(page); |
---|
| 422 | + put_page(page); |
---|
| 423 | + return bh; |
---|
| 424 | +} |
---|
| 425 | + |
---|
| 426 | +/** |
---|
| 427 | + * gfs2_journal_wipe - make inode's buffers so they aren't dirty/pinned anymore |
---|
368 | 428 | * @ip: the inode who owns the buffers |
---|
369 | 429 | * @bstart: the first buffer in the run |
---|
370 | 430 | * @blen: the number of buffers in the run |
---|
371 | 431 | * |
---|
372 | 432 | */ |
---|
373 | 433 | |
---|
374 | | -void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) |
---|
| 434 | +void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) |
---|
375 | 435 | { |
---|
376 | 436 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
---|
377 | 437 | struct buffer_head *bh; |
---|
| 438 | + int ty; |
---|
378 | 439 | |
---|
| 440 | + gfs2_ail1_wipe(sdp, bstart, blen); |
---|
379 | 441 | while (blen) { |
---|
| 442 | + ty = REMOVE_META; |
---|
380 | 443 | bh = gfs2_getbuf(ip->i_gl, bstart, NO_CREATE); |
---|
| 444 | + if (!bh && gfs2_is_jdata(ip)) { |
---|
| 445 | + bh = gfs2_getjdatabuf(ip, bstart); |
---|
| 446 | + ty = REMOVE_JDATA; |
---|
| 447 | + } |
---|
381 | 448 | if (bh) { |
---|
382 | 449 | lock_buffer(bh); |
---|
383 | 450 | gfs2_log_lock(sdp); |
---|
384 | | - gfs2_remove_from_journal(bh, REMOVE_META); |
---|
| 451 | + spin_lock(&sdp->sd_ail_lock); |
---|
| 452 | + gfs2_remove_from_journal(bh, ty); |
---|
| 453 | + spin_unlock(&sdp->sd_ail_lock); |
---|
385 | 454 | gfs2_log_unlock(sdp); |
---|
386 | 455 | unlock_buffer(bh); |
---|
387 | 456 | brelse(bh); |
---|