Blame view

fs/nilfs2/the_nilfs.c 21 KB
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * the_nilfs.c - 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.
   *
4b420ab4e   Ryusuke Konishi   nilfs2: clean up ...
16
   * Written by Ryusuke Konishi.
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
17
18
19
20
21
22
23
   *
   */
  
  #include <linux/buffer_head.h>
  #include <linux/slab.h>
  #include <linux/blkdev.h>
  #include <linux/backing-dev.h>
9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
24
  #include <linux/random.h>
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
25
  #include <linux/crc32.h>
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
26
27
28
29
30
31
  #include "nilfs.h"
  #include "segment.h"
  #include "alloc.h"
  #include "cpfile.h"
  #include "sufile.h"
  #include "dat.h"
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
32
  #include "segbuf.h"
33c8e57c8   Ryusuke Konishi   nilfs2: get rid o...
33

6c1251608   Ryusuke Konishi   nilfs2: implement...
34
  static int nilfs_valid_sb(struct nilfs_super_block *sbp);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
35
36
37
38
39
40
41
  void nilfs_set_last_segment(struct the_nilfs *nilfs,
  			    sector_t start_blocknr, u64 seq, __u64 cno)
  {
  	spin_lock(&nilfs->ns_last_segment_lock);
  	nilfs->ns_last_pseg = start_blocknr;
  	nilfs->ns_last_seq = seq;
  	nilfs->ns_last_cno = cno;
325020477   Ryusuke Konishi   nilfs2: do not up...
42
43
44
45
46
47
48
49
50
51
  
  	if (!nilfs_sb_dirty(nilfs)) {
  		if (nilfs->ns_prev_seq == nilfs->ns_last_seq)
  			goto stay_cursor;
  
  		set_nilfs_sb_dirty(nilfs);
  	}
  	nilfs->ns_prev_seq = nilfs->ns_last_seq;
  
   stay_cursor:
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
52
53
54
55
  	spin_unlock(&nilfs->ns_last_segment_lock);
  }
  
  /**
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
56
   * alloc_nilfs - allocate a nilfs object
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
57
   * @sb: super block instance
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
58
   *
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
59
60
61
   * Return Value: On success, pointer to the_nilfs is returned.
   * On error, NULL is returned.
   */
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
62
  struct the_nilfs *alloc_nilfs(struct super_block *sb)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
63
64
65
66
67
68
  {
  	struct the_nilfs *nilfs;
  
  	nilfs = kzalloc(sizeof(*nilfs), GFP_KERNEL);
  	if (!nilfs)
  		return NULL;
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
69
70
  	nilfs->ns_sb = sb;
  	nilfs->ns_bdev = sb->s_bdev;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
71
72
  	atomic_set(&nilfs->ns_ndirtyblks, 0);
  	init_rwsem(&nilfs->ns_sem);
572d8b394   Ryusuke Konishi   nilfs2: fix deadl...
73
  	mutex_init(&nilfs->ns_snapshot_mount_mutex);
693dd3212   Ryusuke Konishi   nilfs2: move s_in...
74
  	INIT_LIST_HEAD(&nilfs->ns_dirty_files);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
75
  	INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
693dd3212   Ryusuke Konishi   nilfs2: move s_in...
76
  	spin_lock_init(&nilfs->ns_inode_lock);
9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
77
  	spin_lock_init(&nilfs->ns_next_gen_lock);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
78
  	spin_lock_init(&nilfs->ns_last_segment_lock);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
79
80
  	nilfs->ns_cptree = RB_ROOT;
  	spin_lock_init(&nilfs->ns_cptree_lock);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
81
  	init_rwsem(&nilfs->ns_segctor_sem);
caa05d49d   Vyacheslav Dubeyko   nilfs2: add /sys/...
82
  	nilfs->ns_sb_update_freq = NILFS_SB_FREQ;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
83
84
85
86
87
  
  	return nilfs;
  }
  
  /**
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
88
89
   * destroy_nilfs - destroy nilfs object
   * @nilfs: nilfs object to be released
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
90
   */
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
91
  void destroy_nilfs(struct the_nilfs *nilfs)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
92
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
93
  	might_sleep();
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
94
  	if (nilfs_init(nilfs)) {
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
95
  		nilfs_sysfs_delete_device_group(nilfs);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
96
97
  		brelse(nilfs->ns_sbh[0]);
  		brelse(nilfs->ns_sbh[1]);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
98
99
100
  	}
  	kfree(nilfs);
  }
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
101
102
  static int nilfs_load_super_root(struct the_nilfs *nilfs,
  				 struct super_block *sb, sector_t sr_block)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
103
104
105
  {
  	struct buffer_head *bh_sr;
  	struct nilfs_super_root *raw_sr;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
106
  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
107
  	struct nilfs_inode *rawi;
0c6c44cb9   Ryusuke Konishi   nilfs2: avoid bar...
108
109
  	unsigned int dat_entry_size, segment_usage_size, checkpoint_size;
  	unsigned int inode_size;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
110
  	int err;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
111
  	err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
112
113
114
115
  	if (unlikely(err))
  		return err;
  
  	down_read(&nilfs->ns_sem);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
116
117
118
  	dat_entry_size = le16_to_cpu(sbp[0]->s_dat_entry_size);
  	checkpoint_size = le16_to_cpu(sbp[0]->s_checkpoint_size);
  	segment_usage_size = le16_to_cpu(sbp[0]->s_segment_usage_size);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
119
120
121
  	up_read(&nilfs->ns_sem);
  
  	inode_size = nilfs->ns_inode_size;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
122
123
124
  	rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size);
  	err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat);
  	if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
125
  		goto failed;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
126
127
128
  	rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size);
  	err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile);
  	if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
129
  		goto failed_dat;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
130
131
132
133
  	rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size);
  	err = nilfs_sufile_read(sb, segment_usage_size, rawi,
  				&nilfs->ns_sufile);
  	if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
134
  		goto failed_cpfile;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
135
136
137
138
139
140
  	raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
  	nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime);
  
   failed:
  	brelse(bh_sr);
  	return err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
141
   failed_cpfile:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
142
  	iput(nilfs->ns_cpfile);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
143
144
  
   failed_dat:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
145
  	iput(nilfs->ns_dat);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  	goto failed;
  }
  
  static void nilfs_init_recovery_info(struct nilfs_recovery_info *ri)
  {
  	memset(ri, 0, sizeof(*ri));
  	INIT_LIST_HEAD(&ri->ri_used_segments);
  }
  
  static void nilfs_clear_recovery_info(struct nilfs_recovery_info *ri)
  {
  	nilfs_dispose_segment_list(&ri->ri_used_segments);
  }
  
  /**
843d63baa   Ryusuke Konishi   nilfs2: separate ...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
   * nilfs_store_log_cursor - load log cursor from a super block
   * @nilfs: nilfs object
   * @sbp: buffer storing super block to be read
   *
   * nilfs_store_log_cursor() reads the last position of the log
   * containing a super root from a given super block, and initializes
   * relevant information on the nilfs object preparatory for log
   * scanning and recovery.
   */
  static int nilfs_store_log_cursor(struct the_nilfs *nilfs,
  				  struct nilfs_super_block *sbp)
  {
  	int ret = 0;
  
  	nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg);
  	nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno);
  	nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq);
325020477   Ryusuke Konishi   nilfs2: do not up...
178
  	nilfs->ns_prev_seq = nilfs->ns_last_seq;
843d63baa   Ryusuke Konishi   nilfs2: separate ...
179
180
181
182
183
  	nilfs->ns_seg_seq = nilfs->ns_last_seq;
  	nilfs->ns_segnum =
  		nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg);
  	nilfs->ns_cno = nilfs->ns_last_cno + 1;
  	if (nilfs->ns_segnum >= nilfs->ns_nsegments) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
184
185
186
187
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "pointed segment number is out of range: segnum=%llu, nsegments=%lu",
  			  (unsigned long long)nilfs->ns_segnum,
  			  nilfs->ns_nsegments);
843d63baa   Ryusuke Konishi   nilfs2: separate ...
188
189
190
191
192
193
  		ret = -EINVAL;
  	}
  	return ret;
  }
  
  /**
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
194
195
   * load_nilfs - load and recover the nilfs
   * @nilfs: the_nilfs structure to be released
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
196
   * @sb: super block isntance used to recover past segment
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
197
198
199
200
201
   *
   * load_nilfs() searches and load the latest super root,
   * attaches the last segment, and does recovery if needed.
   * The caller must call this exclusively for simultaneous mounts.
   */
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
202
  int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
203
204
  {
  	struct nilfs_recovery_info ri;
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
205
  	unsigned int s_flags = sb->s_flags;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
206
  	int really_read_only = bdev_read_only(nilfs->ns_bdev);
a057d2c01   Ryusuke Konishi   nilfs2: add helpe...
207
  	int valid_fs = nilfs_valid_fs(nilfs);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
208
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
209

f50a4c814   Ryusuke Konishi   nilfs2: move reco...
210
  	if (!valid_fs) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
211
  		nilfs_msg(sb, KERN_WARNING, "mounting unchecked fs");
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
212
  		if (s_flags & MS_RDONLY) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
213
214
215
216
  			nilfs_msg(sb, KERN_INFO,
  				  "recovery required for readonly filesystem");
  			nilfs_msg(sb, KERN_INFO,
  				  "write access will be enabled during recovery");
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
217
  		}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
218
  	}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
219
  	nilfs_init_recovery_info(&ri);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
220
  	err = nilfs_search_super_root(nilfs, &ri);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
221
  	if (unlikely(err)) {
6c1251608   Ryusuke Konishi   nilfs2: implement...
222
223
224
225
226
227
228
  		struct nilfs_super_block **sbp = nilfs->ns_sbp;
  		int blocksize;
  
  		if (err != -EINVAL)
  			goto scan_error;
  
  		if (!nilfs_valid_sb(sbp[1])) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
229
230
  			nilfs_msg(sb, KERN_WARNING,
  				  "unable to fall back to spare super block");
6c1251608   Ryusuke Konishi   nilfs2: implement...
231
232
  			goto scan_error;
  		}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
233
234
  		nilfs_msg(sb, KERN_INFO,
  			  "trying rollback from an earlier position");
6c1251608   Ryusuke Konishi   nilfs2: implement...
235
236
237
238
239
240
241
242
243
244
245
246
  
  		/*
  		 * restore super block with its spare and reconfigure
  		 * relevant states of the nilfs object.
  		 */
  		memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
  		nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed);
  		nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime);
  
  		/* verify consistency between two super blocks */
  		blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size);
  		if (blocksize != nilfs->ns_blocksize) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
247
248
249
  			nilfs_msg(sb, KERN_WARNING,
  				  "blocksize differs between two super blocks (%d != %d)",
  				  blocksize, nilfs->ns_blocksize);
6c1251608   Ryusuke Konishi   nilfs2: implement...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  			goto scan_error;
  		}
  
  		err = nilfs_store_log_cursor(nilfs, sbp[0]);
  		if (err)
  			goto scan_error;
  
  		/* drop clean flag to allow roll-forward and recovery */
  		nilfs->ns_mount_state &= ~NILFS_VALID_FS;
  		valid_fs = 0;
  
  		err = nilfs_search_super_root(nilfs, &ri);
  		if (err)
  			goto scan_error;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
264
  	}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
265
  	err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
266
  	if (unlikely(err)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
267
268
  		nilfs_msg(sb, KERN_ERR, "error %d while loading super root",
  			  err);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
269
270
  		goto failed;
  	}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
271
272
273
274
  	if (valid_fs)
  		goto skip_recovery;
  
  	if (s_flags & MS_RDONLY) {
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
275
  		__u64 features;
3b2ce58b0   Ryusuke Konishi   nilfs2: move moun...
276
  		if (nilfs_test_opt(nilfs, NORECOVERY)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
277
278
  			nilfs_msg(sb, KERN_INFO,
  				  "norecovery option specified, skipping roll-forward recovery");
0234576d0   Ryusuke Konishi   nilfs2: add norec...
279
280
  			goto skip_recovery;
  		}
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
281
282
283
  		features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) &
  			~NILFS_FEATURE_COMPAT_RO_SUPP;
  		if (features) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
284
285
286
  			nilfs_msg(sb, KERN_ERR,
  				  "couldn't proceed with recovery because of unsupported optional features (%llx)",
  				  (unsigned long long)features);
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
287
288
289
  			err = -EROFS;
  			goto failed_unload;
  		}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
290
  		if (really_read_only) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
291
292
  			nilfs_msg(sb, KERN_ERR,
  				  "write access unavailable, cannot proceed");
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
293
294
  			err = -EROFS;
  			goto failed_unload;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
295
  		}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
296
  		sb->s_flags &= ~MS_RDONLY;
3b2ce58b0   Ryusuke Konishi   nilfs2: move moun...
297
  	} else if (nilfs_test_opt(nilfs, NORECOVERY)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
298
299
  		nilfs_msg(sb, KERN_ERR,
  			  "recovery cancelled because norecovery option was specified for a read/write mount");
0234576d0   Ryusuke Konishi   nilfs2: add norec...
300
301
  		err = -EINVAL;
  		goto failed_unload;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
302
  	}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
303
  	err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
304
305
306
307
  	if (err)
  		goto failed_unload;
  
  	down_write(&nilfs->ns_sem);
7ecaa46cf   Ryusuke Konishi   nilfs2: add nilfs...
308
  	nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
309
  	err = nilfs_cleanup_super(sb);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
310
311
312
  	up_write(&nilfs->ns_sem);
  
  	if (err) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
313
314
315
  		nilfs_msg(sb, KERN_ERR,
  			  "error %d updating super block. recovery unfinished.",
  			  err);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
316
  		goto failed_unload;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
317
  	}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
318
  	nilfs_msg(sb, KERN_INFO, "recovery complete");
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
319

f50a4c814   Ryusuke Konishi   nilfs2: move reco...
320
   skip_recovery:
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
321
  	nilfs_clear_recovery_info(&ri);
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
322
  	sb->s_flags = s_flags;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
323
  	return 0;
6c1251608   Ryusuke Konishi   nilfs2: implement...
324
   scan_error:
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
325
  	nilfs_msg(sb, KERN_ERR, "error %d while searching super root", err);
6c1251608   Ryusuke Konishi   nilfs2: implement...
326
  	goto failed;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
327
   failed_unload:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
328
329
330
  	iput(nilfs->ns_cpfile);
  	iput(nilfs->ns_sufile);
  	iput(nilfs->ns_dat);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
331
332
333
  
   failed:
  	nilfs_clear_recovery_info(&ri);
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
334
  	sb->s_flags = s_flags;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
335
336
337
338
339
340
341
342
343
344
345
346
347
  	return err;
  }
  
  static unsigned long long nilfs_max_size(unsigned int blkbits)
  {
  	unsigned int max_bits;
  	unsigned long long res = MAX_LFS_FILESIZE; /* page cache limit */
  
  	max_bits = blkbits + NILFS_BMAP_KEY_BIT; /* bmap size limit */
  	if (max_bits < 64)
  		res = min_t(unsigned long long, res, (1ULL << max_bits) - 1);
  	return res;
  }
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  /**
   * nilfs_nrsvsegs - calculate the number of reserved segments
   * @nilfs: nilfs object
   * @nsegs: total number of segments
   */
  unsigned long nilfs_nrsvsegs(struct the_nilfs *nilfs, unsigned long nsegs)
  {
  	return max_t(unsigned long, NILFS_MIN_NRSVSEGS,
  		     DIV_ROUND_UP(nsegs * nilfs->ns_r_segments_percentage,
  				  100));
  }
  
  void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs)
  {
  	nilfs->ns_nsegments = nsegs;
  	nilfs->ns_nrsvsegs = nilfs_nrsvsegs(nilfs, nsegs);
  }
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
365
366
  static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
  				   struct nilfs_super_block *sbp)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
367
  {
9566a7a85   Ryusuke Konishi   nilfs2: accept fu...
368
  	if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
369
370
371
372
373
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).",
  			  le32_to_cpu(sbp->s_rev_level),
  			  le16_to_cpu(sbp->s_minor_rev_level),
  			  NILFS_CURRENT_REV, NILFS_MINOR_REV);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
374
375
  		return -EINVAL;
  	}
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
376
377
378
  	nilfs->ns_sbsize = le16_to_cpu(sbp->s_bytes);
  	if (nilfs->ns_sbsize > BLOCK_SIZE)
  		return -EINVAL;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
379
  	nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
380
  	if (nilfs->ns_inode_size > nilfs->ns_blocksize) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
381
382
383
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too large inode size: %d bytes",
  			  nilfs->ns_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
384
385
  		return -EINVAL;
  	} else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
386
387
388
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too small inode size: %d bytes",
  			  nilfs->ns_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
389
390
  		return -EINVAL;
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
391
392
393
394
  	nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
  
  	nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
  	if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
395
396
397
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too short segment: %lu blocks",
  			  nilfs->ns_blocks_per_segment);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
398
399
400
401
  		return -EINVAL;
  	}
  
  	nilfs->ns_first_data_block = le64_to_cpu(sbp->s_first_data_block);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
402
403
  	nilfs->ns_r_segments_percentage =
  		le32_to_cpu(sbp->s_r_segments_percentage);
3d777a640   Haogang Chen   nilfs2: clamp ns_...
404
405
  	if (nilfs->ns_r_segments_percentage < 1 ||
  	    nilfs->ns_r_segments_percentage > 99) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
406
407
408
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "invalid reserved segments percentage: %lu",
  			  nilfs->ns_r_segments_percentage);
3d777a640   Haogang Chen   nilfs2: clamp ns_...
409
410
  		return -EINVAL;
  	}
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
411
  	nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments));
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
412
413
414
  	nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed);
  	return 0;
  }
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
415
416
417
418
419
420
421
422
423
424
  static int nilfs_valid_sb(struct nilfs_super_block *sbp)
  {
  	static unsigned char sum[4];
  	const int sumoff = offsetof(struct nilfs_super_block, s_sum);
  	size_t bytes;
  	u32 crc;
  
  	if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
  		return 0;
  	bytes = le16_to_cpu(sbp->s_bytes);
63d2f95d6   Torsten Hilbrich   fs/nilfs2: fix po...
425
  	if (bytes < sumoff + 4 || bytes > BLOCK_SIZE)
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  		return 0;
  	crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
  		       sumoff);
  	crc = crc32_le(crc, sum, 4);
  	crc = crc32_le(crc, (unsigned char *)sbp + sumoff + 4,
  		       bytes - sumoff - 4);
  	return crc == le32_to_cpu(sbp->s_sum);
  }
  
  static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset)
  {
  	return offset < ((le64_to_cpu(sbp->s_nsegments) *
  			  le32_to_cpu(sbp->s_blocks_per_segment)) <<
  			 (le32_to_cpu(sbp->s_log_block_size) + 10));
  }
  
  static void nilfs_release_super_block(struct the_nilfs *nilfs)
  {
  	int i;
  
  	for (i = 0; i < 2; i++) {
  		if (nilfs->ns_sbp[i]) {
  			brelse(nilfs->ns_sbh[i]);
  			nilfs->ns_sbh[i] = NULL;
  			nilfs->ns_sbp[i] = NULL;
  		}
  	}
  }
  
  void nilfs_fall_back_super_block(struct the_nilfs *nilfs)
  {
  	brelse(nilfs->ns_sbh[0]);
  	nilfs->ns_sbh[0] = nilfs->ns_sbh[1];
  	nilfs->ns_sbp[0] = nilfs->ns_sbp[1];
  	nilfs->ns_sbh[1] = NULL;
  	nilfs->ns_sbp[1] = NULL;
  }
  
  void nilfs_swap_super_block(struct the_nilfs *nilfs)
  {
  	struct buffer_head *tsbh = nilfs->ns_sbh[0];
  	struct nilfs_super_block *tsbp = nilfs->ns_sbp[0];
  
  	nilfs->ns_sbh[0] = nilfs->ns_sbh[1];
  	nilfs->ns_sbp[0] = nilfs->ns_sbp[1];
  	nilfs->ns_sbh[1] = tsbh;
  	nilfs->ns_sbp[1] = tsbp;
  }
  
  static int nilfs_load_super_block(struct the_nilfs *nilfs,
  				  struct super_block *sb, int blocksize,
  				  struct nilfs_super_block **sbpp)
  {
  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
  	struct buffer_head **sbh = nilfs->ns_sbh;
  	u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size);
  	int valid[2], swp = 0;
  
  	sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize,
  					&sbh[0]);
  	sbp[1] = nilfs_read_super_block(sb, sb2off, blocksize, &sbh[1]);
  
  	if (!sbp[0]) {
  		if (!sbp[1]) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
490
  			nilfs_msg(sb, KERN_ERR, "unable to read superblock");
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
491
492
  			return -EIO;
  		}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
493
494
495
  		nilfs_msg(sb, KERN_WARNING,
  			  "unable to read primary superblock (blocksize = %d)",
  			  blocksize);
4138ec238   Ryusuke Konishi   nilfs2: append bl...
496
  	} else if (!sbp[1]) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
497
498
499
  		nilfs_msg(sb, KERN_WARNING,
  			  "unable to read secondary superblock (blocksize = %d)",
  			  blocksize);
4138ec238   Ryusuke Konishi   nilfs2: append bl...
500
  	}
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
501

25294d8c3   Ryusuke Konishi   nilfs2: use check...
502
503
504
505
  	/*
  	 * Compare two super blocks and set 1 in swp if the secondary
  	 * super block is valid and newer.  Otherwise, set 0 in swp.
  	 */
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
506
507
  	valid[0] = nilfs_valid_sb(sbp[0]);
  	valid[1] = nilfs_valid_sb(sbp[1]);
25294d8c3   Ryusuke Konishi   nilfs2: use check...
508
509
510
  	swp = valid[1] && (!valid[0] ||
  			   le64_to_cpu(sbp[1]->s_last_cno) >
  			   le64_to_cpu(sbp[0]->s_last_cno));
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
511
512
513
514
515
  
  	if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) {
  		brelse(sbh[1]);
  		sbh[1] = NULL;
  		sbp[1] = NULL;
d7178c79d   Ryusuke Konishi   nilfs2: fix NULL ...
516
  		valid[1] = 0;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
517
518
519
520
  		swp = 0;
  	}
  	if (!valid[swp]) {
  		nilfs_release_super_block(nilfs);
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
521
  		nilfs_msg(sb, KERN_ERR, "couldn't find nilfs on the device");
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
522
523
  		return -EINVAL;
  	}
ea1a16f71   Ryusuke Konishi   nilfs2: fix false...
524
  	if (!valid[!swp])
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
525
526
527
  		nilfs_msg(sb, KERN_WARNING,
  			  "broken superblock, retrying with spare superblock (blocksize = %d)",
  			  blocksize);
ea1a16f71   Ryusuke Konishi   nilfs2: fix false...
528
  	if (swp)
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
529
  		nilfs_swap_super_block(nilfs);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
530

b2ac86e1a   Jiro SEKIBA   nilfs2: sync supe...
531
532
  	nilfs->ns_sbwcount = 0;
  	nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
533
534
535
536
  	nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq);
  	*sbpp = sbp[0];
  	return 0;
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
537
538
539
  /**
   * init_nilfs - initialize a NILFS instance.
   * @nilfs: the_nilfs structure
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
540
541
542
543
544
   * @sb: super block
   * @data: mount options
   *
   * init_nilfs() performs common initialization per block device (e.g.
   * reading the super block, getting disk layout information, initializing
f11459ad7   Ryusuke Konishi   nilfs2: do not al...
545
   * shared fields in the_nilfs).
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
546
547
548
549
   *
   * Return Value: On success, 0 is returned. On error, a negative error
   * code is returned.
   */
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
550
  int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
551
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
552
  	struct nilfs_super_block *sbp;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
553
  	int blocksize;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
554
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
555
556
  
  	down_write(&nilfs->ns_sem);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
557

89c0fd014   Ryusuke Konishi   nilfs2: reject fi...
558
  	blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
559
  	if (!blocksize) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
560
  		nilfs_msg(sb, KERN_ERR, "unable to set blocksize");
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
561
562
563
  		err = -EINVAL;
  		goto out;
  	}
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
564
565
566
  	err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
  	if (err)
  		goto out;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
567
568
569
  	err = nilfs_store_magic_and_option(sb, sbp, data);
  	if (err)
  		goto failed_sbh;
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
570
571
572
  	err = nilfs_check_feature_compatibility(sb, sbp);
  	if (err)
  		goto failed_sbh;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
573
  	blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
89c0fd014   Ryusuke Konishi   nilfs2: reject fi...
574
575
  	if (blocksize < NILFS_MIN_BLOCK_SIZE ||
  	    blocksize > NILFS_MAX_BLOCK_SIZE) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
576
577
578
  		nilfs_msg(sb, KERN_ERR,
  			  "couldn't mount because of unsupported filesystem blocksize %d",
  			  blocksize);
89c0fd014   Ryusuke Konishi   nilfs2: reject fi...
579
580
581
  		err = -EINVAL;
  		goto failed_sbh;
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
582
  	if (sb->s_blocksize != blocksize) {
e1defc4ff   Martin K. Petersen   block: Do away wi...
583
  		int hw_blocksize = bdev_logical_block_size(sb->s_bdev);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
584
585
  
  		if (blocksize < hw_blocksize) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
586
587
588
  			nilfs_msg(sb, KERN_ERR,
  				  "blocksize %d too small for device (sector-size = %d)",
  				  blocksize, hw_blocksize);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
589
  			err = -EINVAL;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
590
591
592
593
594
595
596
  			goto failed_sbh;
  		}
  		nilfs_release_super_block(nilfs);
  		sb_set_blocksize(sb, blocksize);
  
  		err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
  		if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
597
  			goto out;
076a378ba   Ryusuke Konishi   nilfs2: fix block...
598
599
600
601
  			/*
  			 * Not to failed_sbh; sbh is released automatically
  			 * when reloading fails.
  			 */
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
602
603
  	}
  	nilfs->ns_blocksize_bits = sb->s_blocksize_bits;
92c60ccaf   Ryusuke Konishi   nilfs2: add block...
604
  	nilfs->ns_blocksize = blocksize;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
605

9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
606
607
  	get_random_bytes(&nilfs->ns_next_generation,
  			 sizeof(nilfs->ns_next_generation));
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
608
  	err = nilfs_store_disk_layout(nilfs, sbp);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
609
610
611
612
613
614
  	if (err)
  		goto failed_sbh;
  
  	sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits);
  
  	nilfs->ns_mount_state = le16_to_cpu(sbp->s_state);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
615

843d63baa   Ryusuke Konishi   nilfs2: separate ...
616
617
  	err = nilfs_store_log_cursor(nilfs, sbp);
  	if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
618
  		goto failed_sbh;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
619

dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
620
621
622
  	err = nilfs_sysfs_create_device_group(sb);
  	if (err)
  		goto failed_sbh;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
623
624
625
626
627
628
629
  	set_nilfs_init(nilfs);
  	err = 0;
   out:
  	up_write(&nilfs->ns_sem);
  	return err;
  
   failed_sbh:
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
630
  	nilfs_release_super_block(nilfs);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
631
632
  	goto out;
  }
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump,
  			    size_t nsegs)
  {
  	sector_t seg_start, seg_end;
  	sector_t start = 0, nblocks = 0;
  	unsigned int sects_per_block;
  	__u64 *sn;
  	int ret = 0;
  
  	sects_per_block = (1 << nilfs->ns_blocksize_bits) /
  		bdev_logical_block_size(nilfs->ns_bdev);
  	for (sn = segnump; sn < segnump + nsegs; sn++) {
  		nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end);
  
  		if (!nblocks) {
  			start = seg_start;
  			nblocks = seg_end - seg_start + 1;
  		} else if (start + nblocks == seg_start) {
  			nblocks += seg_end - seg_start + 1;
  		} else {
  			ret = blkdev_issue_discard(nilfs->ns_bdev,
  						   start * sects_per_block,
  						   nblocks * sects_per_block,
dd3932edd   Christoph Hellwig   block: remove BLK...
656
  						   GFP_NOFS, 0);
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
657
658
659
660
661
662
663
664
665
  			if (ret < 0)
  				return ret;
  			nblocks = 0;
  		}
  	}
  	if (nblocks)
  		ret = blkdev_issue_discard(nilfs->ns_bdev,
  					   start * sects_per_block,
  					   nblocks * sects_per_block,
dd3932edd   Christoph Hellwig   block: remove BLK...
666
  					   GFP_NOFS, 0);
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
667
668
  	return ret;
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
669
670
  int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
671
  	unsigned long ncleansegs;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
672

365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
673
  	down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
674
  	ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile);
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
675
  	up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
676
677
  	*nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment;
  	return 0;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
678
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
679
680
  int nilfs_near_disk_full(struct the_nilfs *nilfs)
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
681
  	unsigned long ncleansegs, nincsegs;
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
682
683
684
685
686
687
  
  	ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile);
  	nincsegs = atomic_read(&nilfs->ns_ndirtyblks) /
  		nilfs->ns_blocks_per_segment + 1;
  
  	return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
688
  }
ba65ae472   Ryusuke Konishi   nilfs2: add check...
689
  struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
690
  {
ba65ae472   Ryusuke Konishi   nilfs2: add check...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
  	struct rb_node *n;
  	struct nilfs_root *root;
  
  	spin_lock(&nilfs->ns_cptree_lock);
  	n = nilfs->ns_cptree.rb_node;
  	while (n) {
  		root = rb_entry(n, struct nilfs_root, rb_node);
  
  		if (cno < root->cno) {
  			n = n->rb_left;
  		} else if (cno > root->cno) {
  			n = n->rb_right;
  		} else {
  			atomic_inc(&root->count);
  			spin_unlock(&nilfs->ns_cptree_lock);
  			return root;
  		}
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
708
  	}
ba65ae472   Ryusuke Konishi   nilfs2: add check...
709
  	spin_unlock(&nilfs->ns_cptree_lock);
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
710

6dd474066   Ryusuke Konishi   nilfs2: simplify ...
711
  	return NULL;
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
712
  }
ba65ae472   Ryusuke Konishi   nilfs2: add check...
713
714
  struct nilfs_root *
  nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
715
  {
ba65ae472   Ryusuke Konishi   nilfs2: add check...
716
717
  	struct rb_node **p, *parent;
  	struct nilfs_root *root, *new;
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
718
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
719

ba65ae472   Ryusuke Konishi   nilfs2: add check...
720
721
722
  	root = nilfs_lookup_root(nilfs, cno);
  	if (root)
  		return root;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
723

dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
724
  	new = kzalloc(sizeof(*root), GFP_KERNEL);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  	if (!new)
  		return NULL;
  
  	spin_lock(&nilfs->ns_cptree_lock);
  
  	p = &nilfs->ns_cptree.rb_node;
  	parent = NULL;
  
  	while (*p) {
  		parent = *p;
  		root = rb_entry(parent, struct nilfs_root, rb_node);
  
  		if (cno < root->cno) {
  			p = &(*p)->rb_left;
  		} else if (cno > root->cno) {
  			p = &(*p)->rb_right;
  		} else {
  			atomic_inc(&root->count);
  			spin_unlock(&nilfs->ns_cptree_lock);
  			kfree(new);
  			return root;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
746
747
  		}
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
748

ba65ae472   Ryusuke Konishi   nilfs2: add check...
749
750
751
752
  	new->cno = cno;
  	new->ifile = NULL;
  	new->nilfs = nilfs;
  	atomic_set(&new->count, 1);
e5f7f8484   Vyacheslav Dubeyko   ] nilfs2: use ato...
753
754
  	atomic64_set(&new->inodes_count, 0);
  	atomic64_set(&new->blocks_count, 0);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
755
756
757
758
759
  
  	rb_link_node(&new->rb_node, parent, p);
  	rb_insert_color(&new->rb_node, &nilfs->ns_cptree);
  
  	spin_unlock(&nilfs->ns_cptree_lock);
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
760
761
762
763
764
  	err = nilfs_sysfs_create_snapshot_group(new);
  	if (err) {
  		kfree(new);
  		new = NULL;
  	}
ba65ae472   Ryusuke Konishi   nilfs2: add check...
765
766
767
768
769
770
771
  	return new;
  }
  
  void nilfs_put_root(struct nilfs_root *root)
  {
  	if (atomic_dec_and_test(&root->count)) {
  		struct the_nilfs *nilfs = root->nilfs;
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
772
  		nilfs_sysfs_delete_snapshot_group(root);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
773
774
775
  		spin_lock(&nilfs->ns_cptree_lock);
  		rb_erase(&root->rb_node, &nilfs->ns_cptree);
  		spin_unlock(&nilfs->ns_cptree_lock);
72b9918ea   Markus Elfring   nilfs2: deletion ...
776
  		iput(root->ifile);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
777
778
779
  
  		kfree(root);
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
780
  }