aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/the_nilfs.h
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-04-06 22:01:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:12 -0400
commit65b4643d3babeb203fa9571d12fd5e1bf74d27b0 (patch)
treeb9371b765ca1f52c8c7ba046f7cffea92e2bc722 /fs/nilfs2/the_nilfs.h
parenteed10e39b142eb4d284c8e4c751c0eaaa0bcd707 (diff)
nilfs2: add inode and other major structures
This adds the following common structures of the NILFS2 file system. * nilfs_inode_info structure: gives on-memory inode. * nilfs_sb_info structure: keeps per-mount state and a special inode for the ifile. This structure is attached to the super_block structure. * the_nilfs structure: keeps shared state and locks among a read/write mount and snapshot mounts. This keeps special inodes for the sufile, cpfile, dat, and another dat inode used during GC (gcdat). This also has a hash table of dummy inodes to cache disk blocks during GC (gcinodes). * nilfs_transaction_info structure: keeps per task state while nilfs is writing logs or doing indivisible inode or namespace operations. This structure is used to identify context during log making and store nest level of the lock which ensures atomicity of file system operations. Signed-off-by: Koji Sato <sato.koji@lab.ntt.co.jp> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2/the_nilfs.h')
-rw-r--r--fs/nilfs2/the_nilfs.h290
1 files changed, 290 insertions, 0 deletions
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
new file mode 100644
index 000000000000..dee8d83e0549
--- /dev/null
+++ b/fs/nilfs2/the_nilfs.h
@@ -0,0 +1,290 @@
1/*
2 * the_nilfs.h - the_nilfs shared structure.
3 *
4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Written by Ryusuke Konishi <ryusuke@osrg.net>
21 *
22 */
23
24#ifndef _THE_NILFS_H
25#define _THE_NILFS_H
26
27#include <linux/types.h>
28#include <linux/buffer_head.h>
29#include <linux/fs.h>
30#include <linux/blkdev.h>
31#include <linux/backing-dev.h>
32#include "sb.h"
33
34/* the_nilfs struct */
35enum {
36 THE_NILFS_INIT = 0, /* Information from super_block is set */
37 THE_NILFS_LOADED, /* Roll-back/roll-forward has done and
38 the latest checkpoint was loaded */
39 THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */
40 THE_NILFS_COND_NONGC_WRITE, /* Condition to wake up cleanerd */
41};
42
43/**
44 * struct the_nilfs - struct to supervise multiple nilfs mount points
45 * @ns_flags: flags
46 * @ns_count: reference count
47 * @ns_bdev: block device
48 * @ns_bdi: backing dev info
49 * @ns_writer: back pointer to writable nilfs_sb_info
50 * @ns_sem: semaphore for shared states
51 * @ns_writer_mutex: mutex protecting ns_writer attach/detach
52 * @ns_writer_refcount: number of referrers on ns_writer
53 * @ns_sbh: buffer head of the on-disk super block
54 * @ns_sbp: pointer to the super block data
55 * @ns_used_segments: list of full segments in volatile active state
56 * @ns_supers: list of nilfs super block structs
57 * @ns_seg_seq: segment sequence counter
58 * @ns_segnum: index number of the latest full segment.
59 * @ns_nextnum: index number of the full segment index to be used next
60 * @ns_pseg_offset: offset of next partial segment in the current full segment
61 * @ns_cno: next checkpoint number
62 * @ns_ctime: write time of the last segment
63 * @ns_nongc_ctime: write time of the last segment not for cleaner operation
64 * @ns_ndirtyblks: Number of dirty data blocks
65 * @ns_last_segment_lock: lock protecting fields for the latest segment
66 * @ns_last_pseg: start block number of the latest segment
67 * @ns_last_seq: sequence value of the latest segment
68 * @ns_last_cno: checkpoint number of the latest segment
69 * @ns_free_segments_count: counter of free segments
70 * @ns_segctor_sem: segment constructor semaphore
71 * @ns_dat: DAT file inode
72 * @ns_cpfile: checkpoint file inode
73 * @ns_sufile: segusage file inode
74 * @ns_gc_dat: shadow inode of the DAT file inode for GC
75 * @ns_gc_inodes: dummy inodes to keep live blocks
76 * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks
77 * @ns_cleanerd_wq: wait queue for cleanerd
78 * @ns_blocksize_bits: bit length of block size
79 * @ns_nsegments: number of segments in filesystem
80 * @ns_blocks_per_segment: number of blocks per segment
81 * @ns_r_segments_percentage: reserved segments percentage
82 * @ns_nrsvsegs: number of reserved segments
83 * @ns_first_data_block: block number of first data block
84 * @ns_inode_size: size of on-disk inode
85 * @ns_first_ino: first not-special inode number
86 * @ns_crc_seed: seed value of CRC32 calculation
87 */
88struct the_nilfs {
89 unsigned long ns_flags;
90 atomic_t ns_count;
91
92 struct block_device *ns_bdev;
93 struct backing_dev_info *ns_bdi;
94 struct nilfs_sb_info *ns_writer;
95 struct rw_semaphore ns_sem;
96 struct mutex ns_writer_mutex;
97 atomic_t ns_writer_refcount;
98
99 /*
100 * used for
101 * - loading the latest checkpoint exclusively.
102 * - allocating a new full segment.
103 * - protecting s_dirt in the super_block struct
104 * (see nilfs_write_super) and the following fields.
105 */
106 struct buffer_head *ns_sbh;
107 struct nilfs_super_block *ns_sbp;
108 struct list_head ns_used_segments;
109 unsigned ns_mount_state;
110 struct list_head ns_supers;
111
112 /*
113 * Following fields are dedicated to a writable FS-instance.
114 * Except for the period seeking checkpoint, code outside the segment
115 * constructor must lock a segment semaphore with transaction_begin()
116 * and transaction_end(), when accessing these fields.
117 * The writable FS-instance is sole during a lifetime of the_nilfs.
118 */
119 u64 ns_seg_seq;
120 __u64 ns_segnum;
121 __u64 ns_nextnum;
122 unsigned long ns_pseg_offset;
123 __u64 ns_cno;
124 time_t ns_ctime;
125 time_t ns_nongc_ctime;
126 atomic_t ns_ndirtyblks;
127
128 /*
129 * The following fields hold information on the latest partial segment
130 * written to disk with a super root. These fields are protected by
131 * ns_last_segment_lock.
132 */
133 spinlock_t ns_last_segment_lock;
134 sector_t ns_last_pseg;
135 u64 ns_last_seq;
136 __u64 ns_last_cno;
137 unsigned long ns_free_segments_count;
138
139 struct rw_semaphore ns_segctor_sem;
140
141 /*
142 * Following fields are lock free except for the period before
143 * the_nilfs is initialized.
144 */
145 struct inode *ns_dat;
146 struct inode *ns_cpfile;
147 struct inode *ns_sufile;
148 struct inode *ns_gc_dat;
149
150 /* GC inode list and hash table head */
151 struct list_head ns_gc_inodes;
152 struct hlist_head *ns_gc_inodes_h;
153
154 /* cleanerd */
155 wait_queue_head_t ns_cleanerd_wq;
156
157 /* Disk layout information (static) */
158 unsigned int ns_blocksize_bits;
159 unsigned long ns_nsegments;
160 unsigned long ns_blocks_per_segment;
161 unsigned long ns_r_segments_percentage;
162 unsigned long ns_nrsvsegs;
163 unsigned long ns_first_data_block;
164 int ns_inode_size;
165 int ns_first_ino;
166 u32 ns_crc_seed;
167};
168
169#define NILFS_GCINODE_HASH_BITS 8
170#define NILFS_GCINODE_HASH_SIZE (1<<NILFS_GCINODE_HASH_BITS)
171
172#define THE_NILFS_FNS(bit, name) \
173static inline void set_nilfs_##name(struct the_nilfs *nilfs) \
174{ \
175 set_bit(THE_NILFS_##bit, &(nilfs)->ns_flags); \
176} \
177static inline void clear_nilfs_##name(struct the_nilfs *nilfs) \
178{ \
179 clear_bit(THE_NILFS_##bit, &(nilfs)->ns_flags); \
180} \
181static inline int nilfs_##name(struct the_nilfs *nilfs) \
182{ \
183 return test_bit(THE_NILFS_##bit, &(nilfs)->ns_flags); \
184}
185
186THE_NILFS_FNS(INIT, init)
187THE_NILFS_FNS(LOADED, loaded)
188THE_NILFS_FNS(DISCONTINUED, discontinued)
189THE_NILFS_FNS(COND_NONGC_WRITE, cond_nongc_write)
190
191void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
192struct the_nilfs *alloc_nilfs(struct block_device *);
193void put_nilfs(struct the_nilfs *);
194int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
195int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
196int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
197void nilfs_dispose_used_segments(struct the_nilfs *);
198int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
199int nilfs_near_disk_full(struct the_nilfs *);
200
201
202static inline void get_nilfs(struct the_nilfs *nilfs)
203{
204 /* Caller must have at least one reference of the_nilfs. */
205 atomic_inc(&nilfs->ns_count);
206}
207
208static inline struct nilfs_sb_info *nilfs_get_writer(struct the_nilfs *nilfs)
209{
210 if (atomic_inc_and_test(&nilfs->ns_writer_refcount))
211 mutex_lock(&nilfs->ns_writer_mutex);
212 return nilfs->ns_writer;
213}
214
215static inline void nilfs_put_writer(struct the_nilfs *nilfs)
216{
217 if (atomic_add_negative(-1, &nilfs->ns_writer_refcount))
218 mutex_unlock(&nilfs->ns_writer_mutex);
219}
220
221static inline void
222nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
223{
224 mutex_lock(&nilfs->ns_writer_mutex);
225 nilfs->ns_writer = sbi;
226 mutex_unlock(&nilfs->ns_writer_mutex);
227}
228
229static inline void
230nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
231{
232 mutex_lock(&nilfs->ns_writer_mutex);
233 if (sbi == nilfs->ns_writer)
234 nilfs->ns_writer = NULL;
235 mutex_unlock(&nilfs->ns_writer_mutex);
236}
237
238static inline void
239nilfs_get_segment_range(struct the_nilfs *nilfs, __u64 segnum,
240 sector_t *seg_start, sector_t *seg_end)
241{
242 *seg_start = (sector_t)nilfs->ns_blocks_per_segment * segnum;
243 *seg_end = *seg_start + nilfs->ns_blocks_per_segment - 1;
244 if (segnum == 0)
245 *seg_start = nilfs->ns_first_data_block;
246}
247
248static inline sector_t
249nilfs_get_segment_start_blocknr(struct the_nilfs *nilfs, __u64 segnum)
250{
251 return (segnum == 0) ? nilfs->ns_first_data_block :
252 (sector_t)nilfs->ns_blocks_per_segment * segnum;
253}
254
255static inline __u64
256nilfs_get_segnum_of_block(struct the_nilfs *nilfs, sector_t blocknr)
257{
258 sector_t segnum = blocknr;
259
260 sector_div(segnum, nilfs->ns_blocks_per_segment);
261 return segnum;
262}
263
264static inline void
265nilfs_terminate_segment(struct the_nilfs *nilfs, sector_t seg_start,
266 sector_t seg_end)
267{
268 /* terminate the current full segment (used in case of I/O-error) */
269 nilfs->ns_pseg_offset = seg_end - seg_start + 1;
270}
271
272static inline void nilfs_shift_to_next_segment(struct the_nilfs *nilfs)
273{
274 /* move forward with a full segment */
275 nilfs->ns_segnum = nilfs->ns_nextnum;
276 nilfs->ns_pseg_offset = 0;
277 nilfs->ns_seg_seq++;
278}
279
280static inline __u64 nilfs_last_cno(struct the_nilfs *nilfs)
281{
282 __u64 cno;
283
284 spin_lock(&nilfs->ns_last_segment_lock);
285 cno = nilfs->ns_last_cno;
286 spin_unlock(&nilfs->ns_last_segment_lock);
287 return cno;
288}
289
290#endif /* _THE_NILFS_H */