OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [gfs2/] [meta_io.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3
 * Copyright (C) 2004-2006 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
 */
9
 
10
#include <linux/sched.h>
11
#include <linux/slab.h>
12
#include <linux/spinlock.h>
13
#include <linux/completion.h>
14
#include <linux/buffer_head.h>
15
#include <linux/mm.h>
16
#include <linux/pagemap.h>
17
#include <linux/writeback.h>
18
#include <linux/swap.h>
19
#include <linux/delay.h>
20
#include <linux/bio.h>
21
#include <linux/gfs2_ondisk.h>
22
#include <linux/lm_interface.h>
23
 
24
#include "gfs2.h"
25
#include "incore.h"
26
#include "glock.h"
27
#include "glops.h"
28
#include "inode.h"
29
#include "log.h"
30
#include "lops.h"
31
#include "meta_io.h"
32
#include "rgrp.h"
33
#include "trans.h"
34
#include "util.h"
35
#include "ops_address.h"
36
 
37
static int aspace_get_block(struct inode *inode, sector_t lblock,
38
                            struct buffer_head *bh_result, int create)
39
{
40
        gfs2_assert_warn(inode->i_sb->s_fs_info, 0);
41
        return -EOPNOTSUPP;
42
}
43
 
44
static int gfs2_aspace_writepage(struct page *page,
45
                                 struct writeback_control *wbc)
46
{
47
        return block_write_full_page(page, aspace_get_block, wbc);
48
}
49
 
50
static const struct address_space_operations aspace_aops = {
51
        .writepage = gfs2_aspace_writepage,
52
        .releasepage = gfs2_releasepage,
53
};
54
 
55
/**
56
 * gfs2_aspace_get - Create and initialize a struct inode structure
57
 * @sdp: the filesystem the aspace is in
58
 *
59
 * Right now a struct inode is just a struct inode.  Maybe Linux
60
 * will supply a more lightweight address space construct (that works)
61
 * in the future.
62
 *
63
 * Make sure pages/buffers in this aspace aren't in high memory.
64
 *
65
 * Returns: the aspace
66
 */
67
 
68
struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp)
69
{
70
        struct inode *aspace;
71
 
72
        aspace = new_inode(sdp->sd_vfs);
73
        if (aspace) {
74
                mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS);
75
                aspace->i_mapping->a_ops = &aspace_aops;
76
                aspace->i_size = ~0ULL;
77
                aspace->i_private = NULL;
78
                insert_inode_hash(aspace);
79
        }
80
        return aspace;
81
}
82
 
83
void gfs2_aspace_put(struct inode *aspace)
84
{
85
        remove_inode_hash(aspace);
86
        iput(aspace);
87
}
88
 
89
/**
90
 * gfs2_meta_inval - Invalidate all buffers associated with a glock
91
 * @gl: the glock
92
 *
93
 */
94
 
95
void gfs2_meta_inval(struct gfs2_glock *gl)
96
{
97
        struct gfs2_sbd *sdp = gl->gl_sbd;
98
        struct inode *aspace = gl->gl_aspace;
99
        struct address_space *mapping = gl->gl_aspace->i_mapping;
100
 
101
        gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count));
102
 
103
        atomic_inc(&aspace->i_writecount);
104
        truncate_inode_pages(mapping, 0);
105
        atomic_dec(&aspace->i_writecount);
106
 
107
        gfs2_assert_withdraw(sdp, !mapping->nrpages);
108
}
109
 
110
/**
111
 * gfs2_meta_sync - Sync all buffers associated with a glock
112
 * @gl: The glock
113
 *
114
 */
115
 
116
void gfs2_meta_sync(struct gfs2_glock *gl)
117
{
118
        struct address_space *mapping = gl->gl_aspace->i_mapping;
119
        int error;
120
 
121
        filemap_fdatawrite(mapping);
122
        error = filemap_fdatawait(mapping);
123
 
124
        if (error)
125
                gfs2_io_error(gl->gl_sbd);
126
}
127
 
128
/**
129
 * getbuf - Get a buffer with a given address space
130
 * @gl: the glock
131
 * @blkno: the block number (filesystem scope)
132
 * @create: 1 if the buffer should be created
133
 *
134
 * Returns: the buffer
135
 */
136
 
137
static struct buffer_head *getbuf(struct gfs2_glock *gl, u64 blkno, int create)
138
{
139
        struct address_space *mapping = gl->gl_aspace->i_mapping;
140
        struct gfs2_sbd *sdp = gl->gl_sbd;
141
        struct page *page;
142
        struct buffer_head *bh;
143
        unsigned int shift;
144
        unsigned long index;
145
        unsigned int bufnum;
146
 
147
        shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift;
148
        index = blkno >> shift;             /* convert block to page */
149
        bufnum = blkno - (index << shift);  /* block buf index within page */
150
 
151
        if (create) {
152
                for (;;) {
153
                        page = grab_cache_page(mapping, index);
154
                        if (page)
155
                                break;
156
                        yield();
157
                }
158
        } else {
159
                page = find_lock_page(mapping, index);
160
                if (!page)
161
                        return NULL;
162
        }
163
 
164
        if (!page_has_buffers(page))
165
                create_empty_buffers(page, sdp->sd_sb.sb_bsize, 0);
166
 
167
        /* Locate header for our buffer within our page */
168
        for (bh = page_buffers(page); bufnum--; bh = bh->b_this_page)
169
                /* Do nothing */;
170
        get_bh(bh);
171
 
172
        if (!buffer_mapped(bh))
173
                map_bh(bh, sdp->sd_vfs, blkno);
174
 
175
        unlock_page(page);
176
        mark_page_accessed(page);
177
        page_cache_release(page);
178
 
179
        return bh;
180
}
181
 
182
static void meta_prep_new(struct buffer_head *bh)
183
{
184
        struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data;
185
 
186
        lock_buffer(bh);
187
        clear_buffer_dirty(bh);
188
        set_buffer_uptodate(bh);
189
        unlock_buffer(bh);
190
 
191
        mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
192
}
193
 
194
/**
195
 * gfs2_meta_new - Get a block
196
 * @gl: The glock associated with this block
197
 * @blkno: The block number
198
 *
199
 * Returns: The buffer
200
 */
201
 
202
struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
203
{
204
        struct buffer_head *bh;
205
        bh = getbuf(gl, blkno, CREATE);
206
        meta_prep_new(bh);
207
        return bh;
208
}
209
 
210
/**
211
 * gfs2_meta_read - Read a block from disk
212
 * @gl: The glock covering the block
213
 * @blkno: The block number
214
 * @flags: flags
215
 * @bhp: the place where the buffer is returned (NULL on failure)
216
 *
217
 * Returns: errno
218
 */
219
 
220
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
221
                   struct buffer_head **bhp)
222
{
223
        *bhp = getbuf(gl, blkno, CREATE);
224
        if (!buffer_uptodate(*bhp))
225
                ll_rw_block(READ_META, 1, bhp);
226
        if (flags & DIO_WAIT) {
227
                int error = gfs2_meta_wait(gl->gl_sbd, *bhp);
228
                if (error) {
229
                        brelse(*bhp);
230
                        return error;
231
                }
232
        }
233
 
234
        return 0;
235
}
236
 
237
/**
238
 * gfs2_meta_wait - Reread a block from disk
239
 * @sdp: the filesystem
240
 * @bh: The block to wait for
241
 *
242
 * Returns: errno
243
 */
244
 
245
int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
246
{
247
        if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
248
                return -EIO;
249
 
250
        wait_on_buffer(bh);
251
 
252
        if (!buffer_uptodate(bh)) {
253
                struct gfs2_trans *tr = current->journal_info;
254
                if (tr && tr->tr_touched)
255
                        gfs2_io_error_bh(sdp, bh);
256
                return -EIO;
257
        }
258
        if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
259
                return -EIO;
260
 
261
        return 0;
262
}
263
 
264
/**
265
 * gfs2_attach_bufdata - attach a struct gfs2_bufdata structure to a buffer
266
 * @gl: the glock the buffer belongs to
267
 * @bh: The buffer to be attached to
268
 * @meta: Flag to indicate whether its metadata or not
269
 */
270
 
271
void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
272
                         int meta)
273
{
274
        struct gfs2_bufdata *bd;
275
 
276
        if (meta)
277
                lock_page(bh->b_page);
278
 
279
        if (bh->b_private) {
280
                if (meta)
281
                        unlock_page(bh->b_page);
282
                return;
283
        }
284
 
285
        bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL),
286
        bd->bd_bh = bh;
287
        bd->bd_gl = gl;
288
 
289
        INIT_LIST_HEAD(&bd->bd_list_tr);
290
        if (meta)
291
                lops_init_le(&bd->bd_le, &gfs2_buf_lops);
292
        else
293
                lops_init_le(&bd->bd_le, &gfs2_databuf_lops);
294
        bh->b_private = bd;
295
 
296
        if (meta)
297
                unlock_page(bh->b_page);
298
}
299
 
300
void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta)
301
{
302
        struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host);
303
        struct gfs2_bufdata *bd = bh->b_private;
304
        if (test_clear_buffer_pinned(bh)) {
305
                list_del_init(&bd->bd_le.le_list);
306
                if (meta) {
307
                        gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
308
                        sdp->sd_log_num_buf--;
309
                        tr->tr_num_buf_rm++;
310
                } else {
311
                        gfs2_assert_warn(sdp, sdp->sd_log_num_databuf);
312
                        sdp->sd_log_num_databuf--;
313
                        tr->tr_num_databuf_rm++;
314
                }
315
                tr->tr_touched = 1;
316
                brelse(bh);
317
        }
318
        if (bd) {
319
                if (bd->bd_ail) {
320
                        gfs2_remove_from_ail(NULL, bd);
321
                        bh->b_private = NULL;
322
                        bd->bd_bh = NULL;
323
                        bd->bd_blkno = bh->b_blocknr;
324
                        gfs2_trans_add_revoke(sdp, bd);
325
                }
326
        }
327
        clear_buffer_dirty(bh);
328
        clear_buffer_uptodate(bh);
329
}
330
 
331
/**
332
 * gfs2_meta_wipe - make inode's buffers so they aren't dirty/pinned anymore
333
 * @ip: the inode who owns the buffers
334
 * @bstart: the first buffer in the run
335
 * @blen: the number of buffers in the run
336
 *
337
 */
338
 
339
void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
340
{
341
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
342
        struct buffer_head *bh;
343
 
344
        while (blen) {
345
                bh = getbuf(ip->i_gl, bstart, NO_CREATE);
346
                if (bh) {
347
                        lock_buffer(bh);
348
                        gfs2_log_lock(sdp);
349
                        gfs2_remove_from_journal(bh, current->journal_info, 1);
350
                        gfs2_log_unlock(sdp);
351
                        unlock_buffer(bh);
352
                        brelse(bh);
353
                }
354
 
355
                bstart++;
356
                blen--;
357
        }
358
}
359
 
360
/**
361
 * gfs2_meta_cache_flush - get rid of any references on buffers for this inode
362
 * @ip: The GFS2 inode
363
 *
364
 * This releases buffers that are in the most-recently-used array of
365
 * blocks used for indirect block addressing for this inode.
366
 */
367
 
368
void gfs2_meta_cache_flush(struct gfs2_inode *ip)
369
{
370
        struct buffer_head **bh_slot;
371
        unsigned int x;
372
 
373
        spin_lock(&ip->i_spin);
374
 
375
        for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) {
376
                bh_slot = &ip->i_cache[x];
377
                if (*bh_slot) {
378
                        brelse(*bh_slot);
379
                        *bh_slot = NULL;
380
                }
381
        }
382
 
383
        spin_unlock(&ip->i_spin);
384
}
385
 
386
/**
387
 * gfs2_meta_indirect_buffer - Get a metadata buffer
388
 * @ip: The GFS2 inode
389
 * @height: The level of this buf in the metadata (indir addr) tree (if any)
390
 * @num: The block number (device relative) of the buffer
391
 * @new: Non-zero if we may create a new buffer
392
 * @bhp: the buffer is returned here
393
 *
394
 * Try to use the gfs2_inode's MRU metadata tree cache.
395
 *
396
 * Returns: errno
397
 */
398
 
399
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
400
                              int new, struct buffer_head **bhp)
401
{
402
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
403
        struct gfs2_glock *gl = ip->i_gl;
404
        struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height;
405
        int in_cache = 0;
406
 
407
        BUG_ON(!gl);
408
        BUG_ON(!sdp);
409
 
410
        spin_lock(&ip->i_spin);
411
        if (*bh_slot && (*bh_slot)->b_blocknr == num) {
412
                bh = *bh_slot;
413
                get_bh(bh);
414
                in_cache = 1;
415
        }
416
        spin_unlock(&ip->i_spin);
417
 
418
        if (!bh)
419
                bh = getbuf(gl, num, CREATE);
420
 
421
        if (!bh)
422
                return -ENOBUFS;
423
 
424
        if (new) {
425
                if (gfs2_assert_warn(sdp, height))
426
                        goto err;
427
                meta_prep_new(bh);
428
                gfs2_trans_add_bh(ip->i_gl, bh, 1);
429
                gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
430
                gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
431
        } else {
432
                u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
433
                if (!buffer_uptodate(bh)) {
434
                        ll_rw_block(READ_META, 1, &bh);
435
                        if (gfs2_meta_wait(sdp, bh))
436
                                goto err;
437
                }
438
                if (gfs2_metatype_check(sdp, bh, mtype))
439
                        goto err;
440
        }
441
 
442
        if (!in_cache) {
443
                spin_lock(&ip->i_spin);
444
                if (*bh_slot)
445
                        brelse(*bh_slot);
446
                *bh_slot = bh;
447
                get_bh(bh);
448
                spin_unlock(&ip->i_spin);
449
        }
450
 
451
        *bhp = bh;
452
        return 0;
453
err:
454
        brelse(bh);
455
        return -EIO;
456
}
457
 
458
/**
459
 * gfs2_meta_ra - start readahead on an extent of a file
460
 * @gl: the glock the blocks belong to
461
 * @dblock: the starting disk block
462
 * @extlen: the number of blocks in the extent
463
 *
464
 * returns: the first buffer in the extent
465
 */
466
 
467
struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
468
{
469
        struct gfs2_sbd *sdp = gl->gl_sbd;
470
        struct buffer_head *first_bh, *bh;
471
        u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
472
                          sdp->sd_sb.sb_bsize_shift;
473
 
474
        BUG_ON(!extlen);
475
 
476
        if (max_ra < 1)
477
                max_ra = 1;
478
        if (extlen > max_ra)
479
                extlen = max_ra;
480
 
481
        first_bh = getbuf(gl, dblock, CREATE);
482
 
483
        if (buffer_uptodate(first_bh))
484
                goto out;
485
        if (!buffer_locked(first_bh))
486
                ll_rw_block(READ_META, 1, &first_bh);
487
 
488
        dblock++;
489
        extlen--;
490
 
491
        while (extlen) {
492
                bh = getbuf(gl, dblock, CREATE);
493
 
494
                if (!buffer_uptodate(bh) && !buffer_locked(bh))
495
                        ll_rw_block(READA, 1, &bh);
496
                brelse(bh);
497
                dblock++;
498
                extlen--;
499
                if (!buffer_locked(first_bh) && buffer_uptodate(first_bh))
500
                        goto out;
501
        }
502
 
503
        wait_on_buffer(first_bh);
504
out:
505
        return first_bh;
506
}
507
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.