the_nilfs.h 10.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * the_nilfs.h - the_nilfs shared structure.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by Ryusuke Konishi <ryusuke@osrg.net>
 *
 */

#ifndef _THE_NILFS_H
#define _THE_NILFS_H

#include <linux/types.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
32
#include <linux/slab.h>
33 34 35 36 37 38 39 40
#include "sb.h"

/* the_nilfs struct */
enum {
	THE_NILFS_INIT = 0,     /* Information from super_block is set */
	THE_NILFS_LOADED,       /* Roll-back/roll-forward has done and
				   the latest checkpoint was loaded */
	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
41
	THE_NILFS_GC_RUNNING,	/* gc process is running */
42
	THE_NILFS_SB_DIRTY,	/* super block is dirty */
43 44 45 46 47 48
};

/**
 * struct the_nilfs - struct to supervise multiple nilfs mount points
 * @ns_flags: flags
 * @ns_count: reference count
49
 * @ns_list: list head for nilfs_list
50 51 52 53
 * @ns_bdev: block device
 * @ns_bdi: backing dev info
 * @ns_writer: back pointer to writable nilfs_sb_info
 * @ns_sem: semaphore for shared states
54
 * @ns_super_sem: semaphore for global operations across super block instances
55
 * @ns_mount_mutex: mutex protecting mount process of nilfs
56
 * @ns_writer_sem: semaphore protecting ns_writer attach/detach
57
 * @ns_current: back pointer to current mount
58 59
 * @ns_sbh: buffer heads of on-disk super blocks
 * @ns_sbp: pointers to super block data
J
Jiro SEKIBA 已提交
60 61
 * @ns_sbwtime: previous write time of super block
 * @ns_sbwcount: write count of super block
62
 * @ns_sbsize: size of valid data in super block
63 64 65 66 67 68 69 70 71 72 73 74 75
 * @ns_supers: list of nilfs super block structs
 * @ns_seg_seq: segment sequence counter
 * @ns_segnum: index number of the latest full segment.
 * @ns_nextnum: index number of the full segment index to be used next
 * @ns_pseg_offset: offset of next partial segment in the current full segment
 * @ns_cno: next checkpoint number
 * @ns_ctime: write time of the last segment
 * @ns_nongc_ctime: write time of the last segment not for cleaner operation
 * @ns_ndirtyblks: Number of dirty data blocks
 * @ns_last_segment_lock: lock protecting fields for the latest segment
 * @ns_last_pseg: start block number of the latest segment
 * @ns_last_seq: sequence value of the latest segment
 * @ns_last_cno: checkpoint number of the latest segment
76
 * @ns_prot_seq: least sequence number of segments which must not be reclaimed
77
 * @ns_prev_seq: base sequence number used to decide if advance log cursor
78 79 80 81 82 83 84
 * @ns_segctor_sem: segment constructor semaphore
 * @ns_dat: DAT file inode
 * @ns_cpfile: checkpoint file inode
 * @ns_sufile: segusage file inode
 * @ns_gc_dat: shadow inode of the DAT file inode for GC
 * @ns_gc_inodes: dummy inodes to keep live blocks
 * @ns_blocksize_bits: bit length of block size
85
 * @ns_blocksize: block size
86 87 88 89 90 91 92 93 94 95 96 97
 * @ns_nsegments: number of segments in filesystem
 * @ns_blocks_per_segment: number of blocks per segment
 * @ns_r_segments_percentage: reserved segments percentage
 * @ns_nrsvsegs: number of reserved segments
 * @ns_first_data_block: block number of first data block
 * @ns_inode_size: size of on-disk inode
 * @ns_first_ino: first not-special inode number
 * @ns_crc_seed: seed value of CRC32 calculation
 */
struct the_nilfs {
	unsigned long		ns_flags;
	atomic_t		ns_count;
98
	struct list_head	ns_list;
99 100 101 102 103

	struct block_device    *ns_bdev;
	struct backing_dev_info *ns_bdi;
	struct nilfs_sb_info   *ns_writer;
	struct rw_semaphore	ns_sem;
104
	struct rw_semaphore	ns_super_sem;
105
	struct mutex		ns_mount_mutex;
106
	struct rw_semaphore	ns_writer_sem;
107

108 109 110
	/*
	 * components protected by ns_super_sem
	 */
111
	struct nilfs_sb_info   *ns_current;
112
	struct list_head	ns_supers;
113

114 115 116 117 118 119 120
	/*
	 * used for
	 * - loading the latest checkpoint exclusively.
	 * - allocating a new full segment.
	 * - protecting s_dirt in the super_block struct
	 *   (see nilfs_write_super) and the following fields.
	 */
121 122
	struct buffer_head     *ns_sbh[2];
	struct nilfs_super_block *ns_sbp[2];
J
Jiro SEKIBA 已提交
123 124
	time_t			ns_sbwtime;
	unsigned		ns_sbwcount;
125
	unsigned		ns_sbsize;
126 127 128 129 130
	unsigned		ns_mount_state;

	/*
	 * Following fields are dedicated to a writable FS-instance.
	 * Except for the period seeking checkpoint, code outside the segment
131 132
	 * constructor must lock a segment semaphore while accessing these
	 * fields.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
	 * The writable FS-instance is sole during a lifetime of the_nilfs.
	 */
	u64			ns_seg_seq;
	__u64			ns_segnum;
	__u64			ns_nextnum;
	unsigned long		ns_pseg_offset;
	__u64			ns_cno;
	time_t			ns_ctime;
	time_t			ns_nongc_ctime;
	atomic_t		ns_ndirtyblks;

	/*
	 * The following fields hold information on the latest partial segment
	 * written to disk with a super root.  These fields are protected by
	 * ns_last_segment_lock.
	 */
	spinlock_t		ns_last_segment_lock;
	sector_t		ns_last_pseg;
	u64			ns_last_seq;
	__u64			ns_last_cno;
153
	u64			ns_prot_seq;
154
	u64			ns_prev_seq;
155 156 157 158 159 160 161 162 163 164 165 166

	struct rw_semaphore	ns_segctor_sem;

	/*
	 * Following fields are lock free except for the period before
	 * the_nilfs is initialized.
	 */
	struct inode	       *ns_dat;
	struct inode	       *ns_cpfile;
	struct inode	       *ns_sufile;
	struct inode	       *ns_gc_dat;

167
	/* GC inode list */
168 169 170 171
	struct list_head	ns_gc_inodes;

	/* Disk layout information (static) */
	unsigned int		ns_blocksize_bits;
172
	unsigned int		ns_blocksize;
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
	unsigned long		ns_nsegments;
	unsigned long		ns_blocks_per_segment;
	unsigned long		ns_r_segments_percentage;
	unsigned long		ns_nrsvsegs;
	unsigned long		ns_first_data_block;
	int			ns_inode_size;
	int			ns_first_ino;
	u32			ns_crc_seed;
};

#define THE_NILFS_FNS(bit, name)					\
static inline void set_nilfs_##name(struct the_nilfs *nilfs)		\
{									\
	set_bit(THE_NILFS_##bit, &(nilfs)->ns_flags);			\
}									\
static inline void clear_nilfs_##name(struct the_nilfs *nilfs)		\
{									\
	clear_bit(THE_NILFS_##bit, &(nilfs)->ns_flags);			\
}									\
static inline int nilfs_##name(struct the_nilfs *nilfs)			\
{									\
	return test_bit(THE_NILFS_##bit, &(nilfs)->ns_flags);		\
}

THE_NILFS_FNS(INIT, init)
THE_NILFS_FNS(LOADED, loaded)
THE_NILFS_FNS(DISCONTINUED, discontinued)
200
THE_NILFS_FNS(GC_RUNNING, gc_running)
201
THE_NILFS_FNS(SB_DIRTY, sb_dirty)
202

203 204 205
/* Minimum interval of periodical update of superblocks (in seconds) */
#define NILFS_SB_FREQ		10

J
Jiro SEKIBA 已提交
206 207 208
static inline int nilfs_sb_need_update(struct the_nilfs *nilfs)
{
	u64 t = get_seconds();
J
Jiro SEKIBA 已提交
209
	return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ;
J
Jiro SEKIBA 已提交
210 211
}

J
Jiro SEKIBA 已提交
212
static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs)
J
Jiro SEKIBA 已提交
213
{
J
Jiro SEKIBA 已提交
214 215
	int flip_bits = nilfs->ns_sbwcount & 0x0FL;
	return (flip_bits != 0x08 && flip_bits != 0x0F);
J
Jiro SEKIBA 已提交
216 217
}

218
void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
219
struct the_nilfs *find_or_create_nilfs(struct block_device *);
220 221 222
void put_nilfs(struct the_nilfs *);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
223
int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
224
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
225
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
226 227
int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
int nilfs_near_disk_full(struct the_nilfs *);
228 229
void nilfs_fall_back_super_block(struct the_nilfs *);
void nilfs_swap_super_block(struct the_nilfs *);
230 231 232 233 234 235 236 237 238 239 240


static inline void get_nilfs(struct the_nilfs *nilfs)
{
	/* Caller must have at least one reference of the_nilfs. */
	atomic_inc(&nilfs->ns_count);
}

static inline void
nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{
241
	down_write(&nilfs->ns_writer_sem);
242
	nilfs->ns_writer = sbi;
243
	up_write(&nilfs->ns_writer_sem);
244 245 246 247 248
}

static inline void
nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{
249
	down_write(&nilfs->ns_writer_sem);
250 251
	if (sbi == nilfs->ns_writer)
		nilfs->ns_writer = NULL;
252
	up_write(&nilfs->ns_writer_sem);
253 254
}

255 256
static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
{
257
	if (atomic_dec_and_test(&sbi->s_count))
258 259 260
		kfree(sbi);
}

261 262 263 264 265 266 267 268 269 270
static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
{
	unsigned valid_fs;

	down_read(&nilfs->ns_sem);
	valid_fs = (nilfs->ns_mount_state & NILFS_VALID_FS);
	up_read(&nilfs->ns_sem);
	return valid_fs;
}

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
static inline void
nilfs_get_segment_range(struct the_nilfs *nilfs, __u64 segnum,
			sector_t *seg_start, sector_t *seg_end)
{
	*seg_start = (sector_t)nilfs->ns_blocks_per_segment * segnum;
	*seg_end = *seg_start + nilfs->ns_blocks_per_segment - 1;
	if (segnum == 0)
		*seg_start = nilfs->ns_first_data_block;
}

static inline sector_t
nilfs_get_segment_start_blocknr(struct the_nilfs *nilfs, __u64 segnum)
{
	return (segnum == 0) ? nilfs->ns_first_data_block :
		(sector_t)nilfs->ns_blocks_per_segment * segnum;
}

static inline __u64
nilfs_get_segnum_of_block(struct the_nilfs *nilfs, sector_t blocknr)
{
	sector_t segnum = blocknr;

	sector_div(segnum, nilfs->ns_blocks_per_segment);
	return segnum;
}

static inline void
nilfs_terminate_segment(struct the_nilfs *nilfs, sector_t seg_start,
			sector_t seg_end)
{
	/* terminate the current full segment (used in case of I/O-error) */
	nilfs->ns_pseg_offset = seg_end - seg_start + 1;
}

static inline void nilfs_shift_to_next_segment(struct the_nilfs *nilfs)
{
	/* move forward with a full segment */
	nilfs->ns_segnum = nilfs->ns_nextnum;
	nilfs->ns_pseg_offset = 0;
	nilfs->ns_seg_seq++;
}

static inline __u64 nilfs_last_cno(struct the_nilfs *nilfs)
{
	__u64 cno;

	spin_lock(&nilfs->ns_last_segment_lock);
	cno = nilfs->ns_last_cno;
	spin_unlock(&nilfs->ns_last_segment_lock);
	return cno;
}

323 324 325 326 327
static inline int nilfs_segment_is_active(struct the_nilfs *nilfs, __u64 n)
{
	return n == nilfs->ns_segnum || n == nilfs->ns_nextnum;
}

328
#endif /* _THE_NILFS_H */