Release 4.10 fs/nilfs2/segment.c
/*
* segment.c - NILFS segment constructor.
*
* Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Written by Ryusuke Konishi.
*
*/
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/bitops.h>
#include <linux/bio.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/crc32.h>
#include <linux/pagevec.h>
#include <linux/slab.h>
#include "nilfs.h"
#include "btnode.h"
#include "page.h"
#include "segment.h"
#include "sufile.h"
#include "cpfile.h"
#include "ifile.h"
#include "segbuf.h"
/*
* Segment constructor
*/
#define SC_N_INODEVEC 16
/* Size of locally allocated inode vector */
#define SC_MAX_SEGDELTA 64
/*
* Upper limit of the number of segments
* appended in collection retry loop
*/
/* Construction mode */
enum {
SC_LSEG_SR = 1, /* Make a logical segment having a super root */
SC_LSEG_DSYNC, /*
* Flush data blocks of a given file and make
* a logical segment without a super root.
*/
SC_FLUSH_FILE, /*
* Flush data files, leads to segment writes without
* creating a checkpoint.
*/
SC_FLUSH_DAT, /*
* Flush DAT file. This also creates segments
* without a checkpoint.
*/
};
/* Stage numbers of dirty block collection */
enum {
NILFS_ST_INIT = 0,
NILFS_ST_GC, /* Collecting dirty blocks for GC */
NILFS_ST_FILE,
NILFS_ST_IFILE,
NILFS_ST_CPFILE,
NILFS_ST_SUFILE,
NILFS_ST_DAT,
NILFS_ST_SR, /* Super root */
NILFS_ST_DSYNC, /* Data sync blocks */
NILFS_ST_DONE,
};
#define CREATE_TRACE_POINTS
#include <trace/events/nilfs2.h>
/*
* nilfs_sc_cstage_inc(), nilfs_sc_cstage_set(), nilfs_sc_cstage_get() are
* wrapper functions of stage count (nilfs_sc_info->sc_stage.scnt). Users of
* the variable must use them because transition of stage count must involve
* trace events (trace_nilfs2_collection_stage_transition).
*
* nilfs_sc_cstage_get() isn't required for the above purpose because it doesn't
* produce tracepoint events. It is provided just for making the intention
* clear.
*/
static inline void nilfs_sc_cstage_inc(struct nilfs_sc_info *sci)
{
sci->sc_stage.scnt++;
trace_nilfs2_collection_stage_transition(sci);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hitoshi mitake | hitoshi mitake | 24 | 100.00% | 1 | 100.00% |
| Total | 24 | 100.00% | 1 | 100.00% |
static inline void nilfs_sc_cstage_set(struct nilfs_sc_info *sci, int next_scnt)
{
sci->sc_stage.scnt = next_scnt;
trace_nilfs2_collection_stage_transition(sci);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hitoshi mitake | hitoshi mitake | 28 | 100.00% | 1 | 100.00% |
| Total | 28 | 100.00% | 1 | 100.00% |
static inline int nilfs_sc_cstage_get(struct nilfs_sc_info *sci)
{
return sci->sc_stage.scnt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hitoshi mitake | hitoshi mitake | 19 | 100.00% | 1 | 100.00% |
| Total | 19 | 100.00% | 1 | 100.00% |
/* State flags of collection */
#define NILFS_CF_NODE 0x0001
/* Collecting node blocks */
#define NILFS_CF_IFILE_STARTED 0x0002
/* IFILE stage has started */
#define NILFS_CF_SUFREED 0x0004
/* segment usages has been freed */
#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED | NILFS_CF_SUFREED)
/* Operations depending on the construction mode and file type */
struct nilfs_sc_operations {
int (*collect_data)(struct nilfs_sc_info *, struct buffer_head *,
struct inode *);
int (*collect_node)(struct nilfs_sc_info *, struct buffer_head *,
struct inode *);
int (*collect_bmap)(struct nilfs_sc_info *, struct buffer_head *,
struct inode *);
void (*write_data_binfo)(struct nilfs_sc_info *,
struct nilfs_segsum_pointer *,
union nilfs_binfo *);
void (*write_node_binfo)(struct nilfs_sc_info *,
struct nilfs_segsum_pointer *,
union nilfs_binfo *);
};
/*
* Other definitions
*/
static void nilfs_segctor_start_timer(struct nilfs_sc_info *);
static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);
static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *);
static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
#define nilfs_cnt32_gt(a, b) \
(typecheck(__u32, a) && typecheck(__u32, b) && \
((__s32)(b) - (__s32)(a) < 0))
#define nilfs_cnt32_ge(a, b) \
(typecheck(__u32, a) && typecheck(__u32, b) && \
((__s32)(a) - (__s32)(b) >= 0))
#define nilfs_cnt32_lt(a, b) nilfs_cnt32_gt(b, a)
#define nilfs_cnt32_le(a, b) nilfs_cnt32_ge(b, a)
static int nilfs_prepare_segment_lock(struct super_block *sb,
struct nilfs_transaction_info *ti)
{
struct nilfs_transaction_info *cur_ti = current->journal_info;
void *save = NULL;
if (cur_ti) {
if (cur_ti->ti_magic == NILFS_TI_MAGIC)
return ++cur_ti->ti_count;
/*
* If journal_info field is occupied by other FS,
* it is saved and will be restored on
* nilfs_transaction_commit().
*/
nilfs_msg(sb, KERN_WARNING, "journal info from a different FS");
save = current->journal_info;
}
if (!ti) {
ti = kmem_cache_alloc(nilfs_transaction_cachep, GFP_NOFS);
if (!ti)
return -ENOMEM;
ti->ti_flags = NILFS_TI_DYNAMIC_ALLOC;
} else {
ti->ti_flags = 0;
}
ti->ti_count = 0;
ti->ti_save = save;
ti->ti_magic = NILFS_TI_MAGIC;
current->journal_info = ti;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 134 | 100.00% | 3 | 100.00% |
| Total | 134 | 100.00% | 3 | 100.00% |
/**
* nilfs_transaction_begin - start indivisible file operations.
* @sb: super block
* @ti: nilfs_transaction_info
* @vacancy_check: flags for vacancy rate checks
*
* nilfs_transaction_begin() acquires a reader/writer semaphore, called
* the segment semaphore, to make a segment construction and write tasks
* exclusive. The function is used with nilfs_transaction_commit() in pairs.
* The region enclosed by these two functions can be nested. To avoid a
* deadlock, the semaphore is only acquired or released in the outermost call.
*
* This function allocates a nilfs_transaction_info struct to keep context
* information on it. It is initialized and hooked onto the current task in
* the outermost call. If a pre-allocated struct is given to @ti, it is used
* instead; otherwise a new struct is assigned from a slab.
*
* When @vacancy_check flag is set, this function will check the amount of
* free space, and will wait for the GC to reclaim disk space if low capacity.
*
* Return Value: On success, 0 is returned. On error, one of the following
* negative error code is returned.
*
* %-ENOMEM - Insufficient memory available.
*
* %-ENOSPC - No space left on device
*/
int nilfs_transaction_begin(struct super_block *sb,
struct nilfs_transaction_info *ti,
int vacancy_check)
{
struct the_nilfs *nilfs;
int ret = nilfs_prepare_segment_lock(sb, ti);
struct nilfs_transaction_info *trace_ti;
if (unlikely(ret < 0))
return ret;
if (ret > 0) {
trace_ti = current->journal_info;
trace_nilfs2_transaction_transition(sb, trace_ti,
trace_ti->ti_count, trace_ti->ti_flags,
TRACE_NILFS2_TRANSACTION_BEGIN);
return 0;
}
sb_start_intwrite(sb);
nilfs = sb->s_fs_info;
down_read(&nilfs->ns_segctor_sem);
if (vacancy_check && nilfs_near_disk_full(nilfs)) {
up_read(&nilfs->ns_segctor_sem);
ret = -ENOSPC;
goto failed;
}
trace_ti = current->journal_info;
trace_nilfs2_transaction_transition(sb, trace_ti, trace_ti->ti_count,
trace_ti->ti_flags,
TRACE_NILFS2_TRANSACTION_BEGIN);
return 0;
failed:
ti = current->journal_info;
current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
kmem_cache_free(nilfs_transaction_cachep, ti);
sb_end_intwrite(sb);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 136 | 69.74% | 5 | 71.43% |
hitoshi mitake | hitoshi mitake | 53 | 27.18% | 1 | 14.29% |
jan kara | jan kara | 6 | 3.08% | 1 | 14.29% |
| Total | 195 | 100.00% | 7 | 100.00% |
/**
* nilfs_transaction_commit - commit indivisible file operations.
* @sb: super block
*
* nilfs_transaction_commit() releases the read semaphore which is
* acquired by nilfs_transaction_begin(). This is only performed
* in outermost call of this function. If a commit flag is set,
* nilfs_transaction_commit() sets a timer to start the segment
* constructor. If a sync flag is set, it starts construction
* directly.
*/
int nilfs_transaction_commit(struct super_block *sb)
{
struct nilfs_transaction_info *ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
int err = 0;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
ti->ti_flags |= NILFS_TI_COMMIT;
if (ti->ti_count > 0) {
ti->ti_count--;
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_COMMIT);
return 0;
}
if (nilfs->ns_writer) {
struct nilfs_sc_info *sci = nilfs->ns_writer;
if (ti->ti_flags & NILFS_TI_COMMIT)
nilfs_segctor_start_timer(sci);
if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)
nilfs_segctor_do_flush(sci, 0);
}
up_read(&nilfs->ns_segctor_sem);
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_COMMIT);
current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_SYNC)
err = nilfs_construct_segment(sb);
if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
kmem_cache_free(nilfs_transaction_cachep, ti);
sb_end_intwrite(sb);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 170 | 81.34% | 4 | 66.67% |
hitoshi mitake | hitoshi mitake | 34 | 16.27% | 1 | 16.67% |
jan kara | jan kara | 5 | 2.39% | 1 | 16.67% |
| Total | 209 | 100.00% | 6 | 100.00% |
void nilfs_transaction_abort(struct super_block *sb)
{
struct nilfs_transaction_info *ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
if (ti->ti_count > 0) {
ti->ti_count--;
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_ABORT);
return;
}
up_read(&nilfs->ns_segctor_sem);
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_ABORT);
current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
kmem_cache_free(nilfs_transaction_cachep, ti);
sb_end_intwrite(sb);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 88 | 69.29% | 2 | 50.00% |
hitoshi mitake | hitoshi mitake | 34 | 26.77% | 1 | 25.00% |
jan kara | jan kara | 5 | 3.94% | 1 | 25.00% |
| Total | 127 | 100.00% | 4 | 100.00% |
void nilfs_relax_pressure_in_lock(struct super_block *sb)
{
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
if (!sci || !sci->sc_flush_request)
return;
set_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags);
up_read(&nilfs->ns_segctor_sem);
down_write(&nilfs->ns_segctor_sem);
if (sci->sc_flush_request &&
test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags)) {
struct nilfs_transaction_info *ti = current->journal_info;
ti->ti_flags |= NILFS_TI_WRITER;
nilfs_segctor_do_immediate_flush(sci);
ti->ti_flags &= ~NILFS_TI_WRITER;
}
downgrade_write(&nilfs->ns_segctor_sem);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 118 | 100.00% | 3 | 100.00% |
| Total | 118 | 100.00% | 3 | 100.00% |
static void nilfs_transaction_lock(struct super_block *sb,
struct nilfs_transaction_info *ti,
int gcflag)
{
struct nilfs_transaction_info *cur_ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
WARN_ON(cur_ti);
ti->ti_flags = NILFS_TI_WRITER;
ti->ti_count = 0;
ti->ti_save = cur_ti;
ti->ti_magic = NILFS_TI_MAGIC;
current->journal_info = ti;
for (;;) {
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_TRYLOCK);
down_write(&nilfs->ns_segctor_sem);
if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))
break;
nilfs_segctor_do_immediate_flush(sci);
up_write(&nilfs->ns_segctor_sem);
cond_resched();
}
if (gcflag)
ti->ti_flags |= NILFS_TI_GC;
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_LOCK);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 136 | 80.00% | 6 | 85.71% |
hitoshi mitake | hitoshi mitake | 34 | 20.00% | 1 | 14.29% |
| Total | 170 | 100.00% | 7 | 100.00% |
static void nilfs_transaction_unlock(struct super_block *sb)
{
struct nilfs_transaction_info *ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
BUG_ON(ti->ti_count > 0);
up_write(&nilfs->ns_segctor_sem);
current->journal_info = ti->ti_save;
trace_nilfs2_transaction_transition(sb, ti, ti->ti_count,
ti->ti_flags, TRACE_NILFS2_TRANSACTION_UNLOCK);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 67 | 79.76% | 4 | 80.00% |
hitoshi mitake | hitoshi mitake | 17 | 20.24% | 1 | 20.00% |
| Total | 84 | 100.00% | 5 | 100.00% |
static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
struct nilfs_segsum_pointer *ssp,
unsigned int bytes)
{
struct nilfs_segment_buffer *segbuf = sci->sc_curseg;
unsigned int blocksize = sci->sc_super->s_blocksize;
void *p;
if (unlikely(ssp->offset + bytes > blocksize)) {
ssp->offset = 0;
BUG_ON(NILFS_SEGBUF_BH_IS_LAST(ssp->bh,
&segbuf->sb_segsum_buffers));
ssp->bh = NILFS_SEGBUF_NEXT_BH(ssp->bh);
}
p = ssp->bh->b_data + ssp->offset;
ssp->offset += bytes;
return p;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 112 | 100.00% | 2 | 100.00% |
| Total | 112 | 100.00% | 2 | 100.00% |
/**
* nilfs_segctor_reset_segment_buffer - reset the current segment buffer
* @sci: nilfs_sc_info
*/
static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci)
{
struct nilfs_segment_buffer *segbuf = sci->sc_curseg;
struct buffer_head *sumbh;
unsigned int sumbytes;
unsigned int flags = 0;
int err;
if (nilfs_doing_gc())
flags = NILFS_SS_GC;
err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, sci->sc_cno);
if (unlikely(err))
return err;
sumbh = NILFS_SEGBUF_FIRST_BH(&segbuf->sb_segsum_buffers);
sumbytes = segbuf->sb_sum.sumbytes;
sci->sc_finfo_ptr.bh = sumbh; sci->sc_finfo_ptr.offset = sumbytes;
sci->sc_binfo_ptr.bh = sumbh; sci->sc_binfo_ptr.offset = sumbytes;
sci->sc_blk_cnt = sci->sc_datablk_cnt = 0;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 137 | 100.00% | 4 | 100.00% |
| Total | 137 | 100.00% | 4 | 100.00% |
static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci)
{
sci->sc_nblk_this_inc += sci->sc_curseg->sb_sum.nblocks;
if (NILFS_SEGBUF_IS_LAST(sci->sc_curseg, &sci->sc_segbufs))
return -E2BIG; /*
* The current segment is filled up
* (internal code)
*/
sci->sc_curseg = NILFS_NEXT_SEGBUF(sci->sc_curseg);
return nilfs_segctor_reset_segment_buffer(sci);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 59 | 100.00% | 2 | 100.00% |
| Total | 59 | 100.00% | 2 | 100.00% |
static int nilfs_segctor_add_super_root(struct nilfs_sc_info *sci)
{
struct nilfs_segment_buffer *segbuf = sci->sc_curseg;
int err;
if (segbuf->sb_sum.nblocks >= segbuf->sb_rest_blocks) {
err = nilfs_segctor_feed_segment(sci);
if (err)
return err;
segbuf = sci->sc_curseg;
}
err = nilfs_segbuf_extend_payload(segbuf, &segbuf->sb_super_root);
if (likely(!err))
segbuf->sb_sum.flags |= NILFS_SS_SR;
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 88 | 100.00% | 2 | 100.00% |
| Total | 88 | 100.00% | 2 | 100.00% |
/*
* Functions for making segment summary and payloads
*/
static int nilfs_segctor_segsum_block_required(
struct nilfs_sc_info *sci, const struct nilfs_segsum_pointer *ssp,
unsigned int binfo_size)
{
unsigned int blocksize = sci->sc_super->s_blocksize;
/* Size of finfo and binfo is enough small against blocksize */
return ssp->offset + binfo_size +
(!sci->sc_blk_cnt ? sizeof(struct nilfs_finfo) : 0) >
blocksize;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 56 | 100.00% | 2 | 100.00% |
| Total | 56 | 100.00% | 2 | 100.00% |
static void nilfs_segctor_begin_finfo(struct nilfs_sc_info *sci,
struct inode *inode)
{
sci->sc_curseg->sb_sum.nfinfo++;
sci->sc_binfo_ptr = sci->sc_finfo_ptr;
nilfs_segctor_map_segsum_entry(
sci, &sci->sc_binfo_ptr, sizeof(struct nilfs_finfo));
if (NILFS_I(inode)->i_root &&
!test_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags))
set_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags);
/* skip finfo */
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 80 | 100.00% | 3 | 100.00% |
| Total | 80 | 100.00% | 3 | 100.00% |
static void nilfs_segctor_end_finfo(struct nilfs_sc_info *sci,
struct inode *inode)
{
struct nilfs_finfo *finfo;
struct nilfs_inode_info *ii;
struct nilfs_segment_buffer *segbuf;
__u64 cno;
if (sci->sc_blk_cnt == 0)
return;
ii = NILFS_I(inode);
if (test_bit(NILFS_I_GCINODE, &ii->i_state))
cno = ii->i_cno;
else if (NILFS_ROOT_METADATA_FILE(inode->i_ino))
cno = 0;
else
cno = sci->sc_cno;
finfo = nilfs_segctor_map_segsum_entry(sci, &sci->sc_finfo_ptr,
sizeof(*finfo));
finfo->fi_ino = cpu_to_le64(inode->i_ino);
finfo->fi_nblocks = cpu_to_le32(sci->sc_blk_cnt);
finfo->fi_ndatablk = cpu_to_le32(sci->sc_datablk_cnt);
finfo->fi_cno = cpu_to_le64(cno);
segbuf = sci->sc_curseg;
segbuf->sb_sum.sumbytes = sci->sc_binfo_ptr.offset +
sci->sc_super->s_blocksize * (segbuf->sb_sum.nsumblk - 1);
sci->sc_finfo_ptr = sci->sc_binfo_ptr;
sci->sc_blk_cnt = sci->sc_datablk_cnt = 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 201 | 100.00% | 2 | 100.00% |
| Total | 201 | 100.00% | 2 | 100.00% |
static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci,
struct buffer_head *bh,
struct inode *inode,
unsigned int binfo_size)
{
struct nilfs_segment_buffer *segbuf;
int required, err = 0;
retry:
segbuf = sci->sc_curseg;
required = nilfs_segctor_segsum_block_required(
sci, &sci->sc_binfo_ptr, binfo_size);
if (segbuf->sb_sum.nblocks + required + 1 > segbuf->sb_rest_blocks) {
nilfs_segctor_end_finfo(sci, inode);
err = nilfs_segctor_feed_segment(sci);
if (err)
return err;
goto retry;
}
if (unlikely(required)) {
err = nilfs_segbuf_extend_segsum(segbuf);
if (unlikely(err))
goto failed;
}
if (sci->sc_blk_cnt == 0)
nilfs_segctor_begin_finfo(sci, inode);
nilfs_segctor_map_segsum_entry(sci, &sci->sc_binfo_ptr, binfo_size);
/* Substitution to vblocknr is delayed until update_blocknr() */
nilfs_segbuf_add_file_buffer(segbuf, bh);
sci->sc_blk_cnt++;
failed:
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 172 | 100.00% | 2 | 100.00% |
| Total | 172 | 100.00% | 2 | 100.00% |
/*
* Callback functions that enumerate, mark, and collect dirty blocks
*/
static int nilfs_collect_file_data(struct nilfs_sc_info *sci,
struct buffer_head *bh, struct inode *inode)
{
int err;
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
if (err < 0)
return err;
err = nilfs_segctor_add_file_block(sci, bh, inode,
sizeof(struct nilfs_binfo_v));
if (!err)
sci->sc_datablk_cnt++;
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 77 | 100.00% | 1 | 100.00% |
| Total | 77 | 100.00% | 1 | 100.00% |
static int nilfs_collect_file_node(struct nilfs_sc_info *sci,
struct buffer_head *bh,
struct inode *inode)
{
return nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 34 | 100.00% | 2 | 100.00% |
| Total | 34 | 100.00% | 2 | 100.00% |
static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci,
struct buffer_head *bh,
struct inode *inode)
{
WARN_ON(!buffer_dirty(bh));
return nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 45 | 100.00% | 2 | 100.00% |
| Total | 45 | 100.00% | 2 | 100.00% |
static void nilfs_write_file_data_binfo(struct nilfs_sc_info *sci,
struct nilfs_segsum_pointer *ssp,
union nilfs_binfo *binfo)
{
struct nilfs_binfo_v *binfo_v = nilfs_segctor_map_segsum_entry(
sci, ssp, sizeof(*binfo_v));
*binfo_v = binfo->bi_v;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 46 | 100.00% | 1 | 100.00% |
| Total | 46 | 100.00% | 1 | 100.00% |
static void nilfs_write_file_node_binfo(struct nilfs_sc_info *sci,
struct nilfs_segsum_pointer *ssp,
union nilfs_binfo *binfo)
{
__le64 *vblocknr = nilfs_segctor_map_segsum_entry(
sci, ssp, sizeof(*vblocknr));
*vblocknr = binfo->bi_v.bi_vblocknr;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 47 | 100.00% | 1 | 100.00% |
| Total | 47 | 100.00% | 1 | 100.00% |
static const struct nilfs_sc_operations nilfs_sc_file_ops = {
.collect_data = nilfs_collect_file_data,
.collect_node = nilfs_collect_file_node,
.collect_bmap = nilfs_collect_file_bmap,
.write_data_binfo = nilfs_write_file_data_binfo,
.write_node_binfo = nilfs_write_file_node_binfo,
};
static int nilfs_collect_dat_data(struct nilfs_sc_info *sci,
struct buffer_head *bh, struct inode *inode)
{
int err;
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
if (err < 0)
return err;
err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64));
if (!err)
sci->sc_datablk_cnt++;
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 76 | 100.00% | 1 | 100.00% |
| Total | 76 | 100.00% | 1 | 100.00% |
static int nilfs_collect_dat_bmap(struct nilfs_sc_info *sci,
struct buffer_head *bh, struct inode *inode)
{
WARN_ON(!buffer_dirty(bh));
return nilfs_segctor_add_file_block(sci, bh, inode,
sizeof(struct nilfs_binfo_dat));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 46 | 100.00% | 2 | 100.00% |
| Total | 46 | 100.00% | 2 | 100.00% |
static void nilfs_write_dat_data_binfo(struct nilfs_sc_info *sci,
struct nilfs_segsum_pointer *ssp,
union nilfs_binfo *binfo)
{
__le64 *blkoff = nilfs_segctor_map_segsum_entry(sci, ssp,
sizeof(*blkoff));
*blkoff = binfo->bi_dat.bi_blkoff;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 47 | 100.00% | 1 | 100.00% |
| Total | 47 | 100.00% | 1 | 100.00% |
static void nilfs_write_dat_node_binfo(struct nilfs_sc_info *sci,
struct nilfs_segsum_pointer *ssp,
union nilfs_binfo *binfo)
{
struct nilfs_binfo_dat *binfo_dat =
nilfs_segctor_map_segsum_entry(sci, ssp, sizeof(*binfo_dat));
*binfo_dat = binfo->bi_dat;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
ryusuke konishi | ryusuke konishi | 46 | 100.00% | 1 | 100.00% |
| Total | 46 | 100.00% | 1 | 100.00% |
static const struct nilfs_sc_operations nilfs_sc_dat_ops = {
.collect_data = nilfs_collect_dat_data,
.collect_node = nilfs_collect_file_node,
.collect_bmap = nilfs_collect_dat_bmap,
.write_data_binfo = nilfs_write_dat_data_binfo,
.write_node_binfo = nilfs_write_dat_node_binfo,
};
static const struct nilfs_sc_operations nilfs_sc_dsync_ops = {
.collect_data = nilfs_collect_file_data,
.collect_node = NULL,
.collect_bmap = NULL,
.write_data_binfo = nilfs_write_file_data_binfo,
.write_node_binfo = NULL,
};
static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
struct list_head *listp,
size_t nlimit,
loff_t start, loff_t end)
{
struct address_space *mapping = inode->i_mapping;
struct pagevec pvec;
pgoff_t index = 0, last = ULONG_MAX;
size_t ndirties = 0;
int i;
if (unlikely(start != 0 || end != LLONG_MAX)) {
/*
* A valid range is given for sync-ing data pages. The
* range is rounded to per-page; extra dirty buffers
* may be included if blocksize < pagesize.
*/
index = start >> PAGE_SHIFT;
last = end >>