Blame view

fs/nilfs2/the_nilfs.c 20.6 KB
ae98043f5   Ryusuke Konishi   nilfs2: convert t...
1
  // SPDX-License-Identifier: GPL-2.0+
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
2
3
4
5
6
  /*
   * the_nilfs.c - the_nilfs shared structure.
   *
   * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
   *
4b420ab4e   Ryusuke Konishi   nilfs2: clean up ...
7
   * Written by Ryusuke Konishi.
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
8
9
10
11
12
13
14
   *
   */
  
  #include <linux/buffer_head.h>
  #include <linux/slab.h>
  #include <linux/blkdev.h>
  #include <linux/backing-dev.h>
9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
15
  #include <linux/random.h>
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
16
  #include <linux/crc32.h>
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
17
18
19
20
21
22
  #include "nilfs.h"
  #include "segment.h"
  #include "alloc.h"
  #include "cpfile.h"
  #include "sufile.h"
  #include "dat.h"
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
23
  #include "segbuf.h"
33c8e57c8   Ryusuke Konishi   nilfs2: get rid o...
24

6c1251608   Ryusuke Konishi   nilfs2: implement...
25
  static int nilfs_valid_sb(struct nilfs_super_block *sbp);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
26
27
28
29
30
31
32
  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...
33
34
35
36
37
38
39
40
41
42
  
  	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...
43
44
45
46
  	spin_unlock(&nilfs->ns_last_segment_lock);
  }
  
  /**
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
47
   * alloc_nilfs - allocate a nilfs object
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
48
   * @sb: super block instance
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
49
   *
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
50
51
52
   * Return Value: On success, pointer to the_nilfs is returned.
   * On error, NULL is returned.
   */
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
53
  struct the_nilfs *alloc_nilfs(struct super_block *sb)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
54
55
56
57
58
59
  {
  	struct the_nilfs *nilfs;
  
  	nilfs = kzalloc(sizeof(*nilfs), GFP_KERNEL);
  	if (!nilfs)
  		return NULL;
6625689e1   Ryusuke Konishi   nilfs2: embed a b...
60
61
  	nilfs->ns_sb = sb;
  	nilfs->ns_bdev = sb->s_bdev;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
62
63
  	atomic_set(&nilfs->ns_ndirtyblks, 0);
  	init_rwsem(&nilfs->ns_sem);
572d8b394   Ryusuke Konishi   nilfs2: fix deadl...
64
  	mutex_init(&nilfs->ns_snapshot_mount_mutex);
693dd3212   Ryusuke Konishi   nilfs2: move s_in...
65
  	INIT_LIST_HEAD(&nilfs->ns_dirty_files);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
66
  	INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
693dd3212   Ryusuke Konishi   nilfs2: move s_in...
67
  	spin_lock_init(&nilfs->ns_inode_lock);
9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
68
  	spin_lock_init(&nilfs->ns_next_gen_lock);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
69
  	spin_lock_init(&nilfs->ns_last_segment_lock);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
70
71
  	nilfs->ns_cptree = RB_ROOT;
  	spin_lock_init(&nilfs->ns_cptree_lock);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
72
  	init_rwsem(&nilfs->ns_segctor_sem);
caa05d49d   Vyacheslav Dubeyko   nilfs2: add /sys/...
73
  	nilfs->ns_sb_update_freq = NILFS_SB_FREQ;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
74
75
76
77
78
  
  	return nilfs;
  }
  
  /**
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
79
80
   * destroy_nilfs - destroy nilfs object
   * @nilfs: nilfs object to be released
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
81
   */
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
82
  void destroy_nilfs(struct the_nilfs *nilfs)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
83
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
84
  	might_sleep();
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
85
  	if (nilfs_init(nilfs)) {
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
86
  		nilfs_sysfs_delete_device_group(nilfs);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
87
88
  		brelse(nilfs->ns_sbh[0]);
  		brelse(nilfs->ns_sbh[1]);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
89
90
91
  	}
  	kfree(nilfs);
  }
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
92
93
  static int nilfs_load_super_root(struct the_nilfs *nilfs,
  				 struct super_block *sb, sector_t sr_block)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
94
95
96
  {
  	struct buffer_head *bh_sr;
  	struct nilfs_super_root *raw_sr;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
97
  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
98
  	struct nilfs_inode *rawi;
0c6c44cb9   Ryusuke Konishi   nilfs2: avoid bar...
99
100
  	unsigned int dat_entry_size, segment_usage_size, checkpoint_size;
  	unsigned int inode_size;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
101
  	int err;
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
102
  	err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
103
104
105
106
  	if (unlikely(err))
  		return err;
  
  	down_read(&nilfs->ns_sem);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
107
108
109
  	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...
110
111
112
  	up_read(&nilfs->ns_sem);
  
  	inode_size = nilfs->ns_inode_size;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
113
114
115
  	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...
116
  		goto failed;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
117
118
119
  	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...
120
  		goto failed_dat;
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
121
122
123
124
  	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...
125
  		goto failed_cpfile;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
126
127
128
129
130
131
  	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...
132
   failed_cpfile:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
133
  	iput(nilfs->ns_cpfile);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
134
135
  
   failed_dat:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
136
  	iput(nilfs->ns_dat);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	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 ...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
   * 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...
169
  	nilfs->ns_prev_seq = nilfs->ns_last_seq;
843d63baa   Ryusuke Konishi   nilfs2: separate ...
170
171
172
173
174
  	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...
175
176
177
178
  		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 ...
179
180
181
182
183
184
  		ret = -EINVAL;
  	}
  	return ret;
  }
  
  /**
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
185
186
   * load_nilfs - load and recover the nilfs
   * @nilfs: the_nilfs structure to be released
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
187
   * @sb: super block isntance used to recover past segment
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
188
189
190
191
192
   *
   * 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...
193
  int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
194
195
  {
  	struct nilfs_recovery_info ri;
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
196
  	unsigned int s_flags = sb->s_flags;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
197
  	int really_read_only = bdev_read_only(nilfs->ns_bdev);
a057d2c01   Ryusuke Konishi   nilfs2: add helpe...
198
  	int valid_fs = nilfs_valid_fs(nilfs);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
199
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
200

f50a4c814   Ryusuke Konishi   nilfs2: move reco...
201
  	if (!valid_fs) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
202
  		nilfs_msg(sb, KERN_WARNING, "mounting unchecked fs");
1751e8a6c   Linus Torvalds   Rename superblock...
203
  		if (s_flags & SB_RDONLY) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
204
205
206
207
  			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...
208
  		}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
209
  	}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
210
  	nilfs_init_recovery_info(&ri);
8b94025c0   Ryusuke Konishi   nilfs2: refactor ...
211
  	err = nilfs_search_super_root(nilfs, &ri);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
212
  	if (unlikely(err)) {
6c1251608   Ryusuke Konishi   nilfs2: implement...
213
214
215
216
217
218
219
  		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...
220
221
  			nilfs_msg(sb, KERN_WARNING,
  				  "unable to fall back to spare super block");
6c1251608   Ryusuke Konishi   nilfs2: implement...
222
223
  			goto scan_error;
  		}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
224
225
  		nilfs_msg(sb, KERN_INFO,
  			  "trying rollback from an earlier position");
6c1251608   Ryusuke Konishi   nilfs2: implement...
226
227
228
229
230
231
232
233
234
235
236
237
  
  		/*
  		 * 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...
238
239
240
  			nilfs_msg(sb, KERN_WARNING,
  				  "blocksize differs between two super blocks (%d != %d)",
  				  blocksize, nilfs->ns_blocksize);
6c1251608   Ryusuke Konishi   nilfs2: implement...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  			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...
255
  	}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
256
  	err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
257
  	if (unlikely(err)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
258
259
  		nilfs_msg(sb, KERN_ERR, "error %d while loading super root",
  			  err);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
260
261
  		goto failed;
  	}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
262
263
  	if (valid_fs)
  		goto skip_recovery;
1751e8a6c   Linus Torvalds   Rename superblock...
264
  	if (s_flags & SB_RDONLY) {
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
265
  		__u64 features;
3b2ce58b0   Ryusuke Konishi   nilfs2: move moun...
266
  		if (nilfs_test_opt(nilfs, NORECOVERY)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
267
268
  			nilfs_msg(sb, KERN_INFO,
  				  "norecovery option specified, skipping roll-forward recovery");
0234576d0   Ryusuke Konishi   nilfs2: add norec...
269
270
  			goto skip_recovery;
  		}
c5ca48aab   Ryusuke Konishi   nilfs2: reject in...
271
272
273
  		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...
274
275
276
  			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...
277
278
279
  			err = -EROFS;
  			goto failed_unload;
  		}
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
280
  		if (really_read_only) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
281
282
  			nilfs_msg(sb, KERN_ERR,
  				  "write access unavailable, cannot proceed");
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
283
284
  			err = -EROFS;
  			goto failed_unload;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
285
  		}
1751e8a6c   Linus Torvalds   Rename superblock...
286
  		sb->s_flags &= ~SB_RDONLY;
3b2ce58b0   Ryusuke Konishi   nilfs2: move moun...
287
  	} else if (nilfs_test_opt(nilfs, NORECOVERY)) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
288
289
  		nilfs_msg(sb, KERN_ERR,
  			  "recovery cancelled because norecovery option was specified for a read/write mount");
0234576d0   Ryusuke Konishi   nilfs2: add norec...
290
291
  		err = -EINVAL;
  		goto failed_unload;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
292
  	}
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
293
  	err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
294
295
296
297
  	if (err)
  		goto failed_unload;
  
  	down_write(&nilfs->ns_sem);
7ecaa46cf   Ryusuke Konishi   nilfs2: add nilfs...
298
  	nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
299
  	err = nilfs_cleanup_super(sb);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
300
301
302
  	up_write(&nilfs->ns_sem);
  
  	if (err) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
303
304
305
  		nilfs_msg(sb, KERN_ERR,
  			  "error %d updating super block. recovery unfinished.",
  			  err);
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
306
  		goto failed_unload;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
307
  	}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
308
  	nilfs_msg(sb, KERN_INFO, "recovery complete");
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
309

f50a4c814   Ryusuke Konishi   nilfs2: move reco...
310
   skip_recovery:
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
311
  	nilfs_clear_recovery_info(&ri);
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
312
  	sb->s_flags = s_flags;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
313
  	return 0;
6c1251608   Ryusuke Konishi   nilfs2: implement...
314
   scan_error:
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
315
  	nilfs_msg(sb, KERN_ERR, "error %d while searching super root", err);
6c1251608   Ryusuke Konishi   nilfs2: implement...
316
  	goto failed;
f50a4c814   Ryusuke Konishi   nilfs2: move reco...
317
   failed_unload:
f1e89c86f   Ryusuke Konishi   nilfs2: use iget ...
318
319
320
  	iput(nilfs->ns_cpfile);
  	iput(nilfs->ns_sufile);
  	iput(nilfs->ns_dat);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
321
322
323
  
   failed:
  	nilfs_clear_recovery_info(&ri);
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
324
  	sb->s_flags = s_flags;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
325
326
327
328
329
330
331
332
333
334
335
336
337
  	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...
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  /**
   * 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...
355
356
  static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
  				   struct nilfs_super_block *sbp)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
357
  {
9566a7a85   Ryusuke Konishi   nilfs2: accept fu...
358
  	if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
359
360
361
362
363
  		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...
364
365
  		return -EINVAL;
  	}
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
366
367
368
  	nilfs->ns_sbsize = le16_to_cpu(sbp->s_bytes);
  	if (nilfs->ns_sbsize > BLOCK_SIZE)
  		return -EINVAL;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
369
  	nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
370
  	if (nilfs->ns_inode_size > nilfs->ns_blocksize) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
371
372
373
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too large inode size: %d bytes",
  			  nilfs->ns_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
374
375
  		return -EINVAL;
  	} else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
376
377
378
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too small inode size: %d bytes",
  			  nilfs->ns_inode_size);
0ec060d18   Ryusuke Konishi   nilfs2: verify me...
379
380
  		return -EINVAL;
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
381
382
383
384
  	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...
385
386
387
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "too short segment: %lu blocks",
  			  nilfs->ns_blocks_per_segment);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
388
389
390
391
  		return -EINVAL;
  	}
  
  	nilfs->ns_first_data_block = le64_to_cpu(sbp->s_first_data_block);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
392
393
  	nilfs->ns_r_segments_percentage =
  		le32_to_cpu(sbp->s_r_segments_percentage);
3d777a640   Haogang Chen   nilfs2: clamp ns_...
394
395
  	if (nilfs->ns_r_segments_percentage < 1 ||
  	    nilfs->ns_r_segments_percentage > 99) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
396
397
398
  		nilfs_msg(nilfs->ns_sb, KERN_ERR,
  			  "invalid reserved segments percentage: %lu",
  			  nilfs->ns_r_segments_percentage);
3d777a640   Haogang Chen   nilfs2: clamp ns_...
399
400
  		return -EINVAL;
  	}
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
401
  	nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments));
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
402
403
404
  	nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed);
  	return 0;
  }
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
405
406
407
408
409
410
411
412
413
414
  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...
415
  	if (bytes < sumoff + 4 || bytes > BLOCK_SIZE)
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
416
417
418
419
420
421
422
423
424
425
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
  		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...
480
  			nilfs_msg(sb, KERN_ERR, "unable to read superblock");
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
481
482
  			return -EIO;
  		}
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
483
484
485
  		nilfs_msg(sb, KERN_WARNING,
  			  "unable to read primary superblock (blocksize = %d)",
  			  blocksize);
4138ec238   Ryusuke Konishi   nilfs2: append bl...
486
  	} else if (!sbp[1]) {
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
487
488
489
  		nilfs_msg(sb, KERN_WARNING,
  			  "unable to read secondary superblock (blocksize = %d)",
  			  blocksize);
4138ec238   Ryusuke Konishi   nilfs2: append bl...
490
  	}
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
491

25294d8c3   Ryusuke Konishi   nilfs2: use check...
492
493
494
495
  	/*
  	 * 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...
496
497
  	valid[0] = nilfs_valid_sb(sbp[0]);
  	valid[1] = nilfs_valid_sb(sbp[1]);
25294d8c3   Ryusuke Konishi   nilfs2: use check...
498
499
500
  	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...
501
502
503
504
505
  
  	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 ...
506
  		valid[1] = 0;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
507
508
509
510
  		swp = 0;
  	}
  	if (!valid[swp]) {
  		nilfs_release_super_block(nilfs);
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
511
  		nilfs_msg(sb, KERN_ERR, "couldn't find nilfs on the device");
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
512
513
  		return -EINVAL;
  	}
ea1a16f71   Ryusuke Konishi   nilfs2: fix false...
514
  	if (!valid[!swp])
feee880fa   Ryusuke Konishi   nilfs2: reduce ba...
515
516
517
  		nilfs_msg(sb, KERN_WARNING,
  			  "broken superblock, retrying with spare superblock (blocksize = %d)",
  			  blocksize);
ea1a16f71   Ryusuke Konishi   nilfs2: fix false...
518
  	if (swp)
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
519
  		nilfs_swap_super_block(nilfs);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
520

b2ac86e1a   Jiro SEKIBA   nilfs2: sync supe...
521
522
  	nilfs->ns_sbwcount = 0;
  	nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime);
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
523
524
525
526
  	nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq);
  	*sbpp = sbp[0];
  	return 0;
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
527
528
529
  /**
   * init_nilfs - initialize a NILFS instance.
   * @nilfs: the_nilfs structure
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
530
531
532
533
534
   * @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...
535
   * shared fields in the_nilfs).
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
536
537
538
539
   *
   * Return Value: On success, 0 is returned. On error, a negative error
   * code is returned.
   */
f7545144c   Ryusuke Konishi   nilfs2: use sb in...
540
  int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
541
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
542
  	struct nilfs_super_block *sbp;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
543
  	int blocksize;
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
544
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
545
546
  
  	down_write(&nilfs->ns_sem);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
547

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

9b1fc4e49   Ryusuke Konishi   nilfs2: move next...
596
597
  	get_random_bytes(&nilfs->ns_next_generation,
  			 sizeof(nilfs->ns_next_generation));
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
598
  	err = nilfs_store_disk_layout(nilfs, sbp);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
599
600
601
602
603
604
  	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...
605

843d63baa   Ryusuke Konishi   nilfs2: separate ...
606
607
  	err = nilfs_store_log_cursor(nilfs, sbp);
  	if (err)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
608
  		goto failed_sbh;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
609

dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
610
611
612
  	err = nilfs_sysfs_create_device_group(sb);
  	if (err)
  		goto failed_sbh;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
613
614
615
616
617
618
619
  	set_nilfs_init(nilfs);
  	err = 0;
   out:
  	up_write(&nilfs->ns_sem);
  	return err;
  
   failed_sbh:
e339ad31f   Ryusuke Konishi   nilfs2: introduce...
620
  	nilfs_release_super_block(nilfs);
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
621
622
  	goto out;
  }
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
  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...
646
  						   GFP_NOFS, 0);
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
647
648
649
650
651
652
653
654
655
  			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...
656
  					   GFP_NOFS, 0);
e902ec990   Jiro SEKIBA   nilfs2: issue dis...
657
658
  	return ret;
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
659
660
  int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
661
  	unsigned long ncleansegs;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
662

365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
663
  	down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
664
  	ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile);
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
665
  	up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
666
667
  	*nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment;
  	return 0;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
668
  }
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
669
670
  int nilfs_near_disk_full(struct the_nilfs *nilfs)
  {
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
671
  	unsigned long ncleansegs, nincsegs;
ef7d4757a   Ryusuke Konishi   nilfs2: simplify ...
672
673
674
675
676
677
  
  	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...
678
  }
ba65ae472   Ryusuke Konishi   nilfs2: add check...
679
  struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
680
  {
ba65ae472   Ryusuke Konishi   nilfs2: add check...
681
682
683
684
685
686
687
688
689
690
691
692
693
  	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 {
d4f0284a5   Elena Reshetova   fs, nilfs: conver...
694
  			refcount_inc(&root->count);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
695
696
697
  			spin_unlock(&nilfs->ns_cptree_lock);
  			return root;
  		}
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
698
  	}
ba65ae472   Ryusuke Konishi   nilfs2: add check...
699
  	spin_unlock(&nilfs->ns_cptree_lock);
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
700

6dd474066   Ryusuke Konishi   nilfs2: simplify ...
701
  	return NULL;
6dd474066   Ryusuke Konishi   nilfs2: simplify ...
702
  }
ba65ae472   Ryusuke Konishi   nilfs2: add check...
703
704
  struct nilfs_root *
  nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
705
  {
ba65ae472   Ryusuke Konishi   nilfs2: add check...
706
707
  	struct rb_node **p, *parent;
  	struct nilfs_root *root, *new;
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
708
  	int err;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
709

ba65ae472   Ryusuke Konishi   nilfs2: add check...
710
711
712
  	root = nilfs_lookup_root(nilfs, cno);
  	if (root)
  		return root;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
713

dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
714
  	new = kzalloc(sizeof(*root), GFP_KERNEL);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
  	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 {
d4f0284a5   Elena Reshetova   fs, nilfs: conver...
732
  			refcount_inc(&root->count);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
733
734
735
  			spin_unlock(&nilfs->ns_cptree_lock);
  			kfree(new);
  			return root;
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
736
737
  		}
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
738

ba65ae472   Ryusuke Konishi   nilfs2: add check...
739
740
741
  	new->cno = cno;
  	new->ifile = NULL;
  	new->nilfs = nilfs;
d4f0284a5   Elena Reshetova   fs, nilfs: conver...
742
  	refcount_set(&new->count, 1);
e5f7f8484   Vyacheslav Dubeyko   ] nilfs2: use ato...
743
744
  	atomic64_set(&new->inodes_count, 0);
  	atomic64_set(&new->blocks_count, 0);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
745
746
747
748
749
  
  	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...
750
751
752
753
754
  	err = nilfs_sysfs_create_snapshot_group(new);
  	if (err) {
  		kfree(new);
  		new = NULL;
  	}
ba65ae472   Ryusuke Konishi   nilfs2: add check...
755
756
757
758
759
  	return new;
  }
  
  void nilfs_put_root(struct nilfs_root *root)
  {
d4f0284a5   Elena Reshetova   fs, nilfs: conver...
760
  	if (refcount_dec_and_test(&root->count)) {
ba65ae472   Ryusuke Konishi   nilfs2: add check...
761
  		struct the_nilfs *nilfs = root->nilfs;
dd70edbde   Vyacheslav Dubeyko   nilfs2: integrate...
762
  		nilfs_sysfs_delete_snapshot_group(root);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
763
764
765
  		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 ...
766
  		iput(root->ifile);
ba65ae472   Ryusuke Konishi   nilfs2: add check...
767
768
769
  
  		kfree(root);
  	}
8a9d2191e   Ryusuke Konishi   nilfs2: operation...
770
  }