diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nilfs2/super.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 969 |
1 files changed, 554 insertions, 415 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 922263393c76..8351c44a7320 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -43,22 +43,20 @@ | |||
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <linux/blkdev.h> | 44 | #include <linux/blkdev.h> |
45 | #include <linux/parser.h> | 45 | #include <linux/parser.h> |
46 | #include <linux/random.h> | ||
47 | #include <linux/crc32.h> | 46 | #include <linux/crc32.h> |
48 | #include <linux/smp_lock.h> | ||
49 | #include <linux/vfs.h> | 47 | #include <linux/vfs.h> |
50 | #include <linux/writeback.h> | 48 | #include <linux/writeback.h> |
51 | #include <linux/kobject.h> | ||
52 | #include <linux/exportfs.h> | ||
53 | #include <linux/seq_file.h> | 49 | #include <linux/seq_file.h> |
54 | #include <linux/mount.h> | 50 | #include <linux/mount.h> |
55 | #include "nilfs.h" | 51 | #include "nilfs.h" |
52 | #include "export.h" | ||
56 | #include "mdt.h" | 53 | #include "mdt.h" |
57 | #include "alloc.h" | 54 | #include "alloc.h" |
58 | #include "btree.h" | 55 | #include "btree.h" |
59 | #include "btnode.h" | 56 | #include "btnode.h" |
60 | #include "page.h" | 57 | #include "page.h" |
61 | #include "cpfile.h" | 58 | #include "cpfile.h" |
59 | #include "sufile.h" /* nilfs_sufile_resize(), nilfs_sufile_set_alloc_range() */ | ||
62 | #include "ifile.h" | 60 | #include "ifile.h" |
63 | #include "dat.h" | 61 | #include "dat.h" |
64 | #include "segment.h" | 62 | #include "segment.h" |
@@ -69,27 +67,28 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
69 | "(NILFS)"); | 67 | "(NILFS)"); |
70 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
71 | 69 | ||
72 | struct kmem_cache *nilfs_inode_cachep; | 70 | static struct kmem_cache *nilfs_inode_cachep; |
73 | struct kmem_cache *nilfs_transaction_cachep; | 71 | struct kmem_cache *nilfs_transaction_cachep; |
74 | struct kmem_cache *nilfs_segbuf_cachep; | 72 | struct kmem_cache *nilfs_segbuf_cachep; |
75 | struct kmem_cache *nilfs_btree_path_cache; | 73 | struct kmem_cache *nilfs_btree_path_cache; |
76 | 74 | ||
75 | static int nilfs_setup_super(struct super_block *sb, int is_mount); | ||
77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 76 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
78 | 77 | ||
79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | 78 | static void nilfs_set_error(struct super_block *sb) |
80 | { | 79 | { |
81 | struct the_nilfs *nilfs = sbi->s_nilfs; | 80 | struct the_nilfs *nilfs = sb->s_fs_info; |
82 | struct nilfs_super_block **sbp; | 81 | struct nilfs_super_block **sbp; |
83 | 82 | ||
84 | down_write(&nilfs->ns_sem); | 83 | down_write(&nilfs->ns_sem); |
85 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | 84 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { |
86 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | 85 | nilfs->ns_mount_state |= NILFS_ERROR_FS; |
87 | sbp = nilfs_prepare_super(sbi, 0); | 86 | sbp = nilfs_prepare_super(sb, 0); |
88 | if (likely(sbp)) { | 87 | if (likely(sbp)) { |
89 | sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | 88 | sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); |
90 | if (sbp[1]) | 89 | if (sbp[1]) |
91 | sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | 90 | sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); |
92 | nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | 91 | nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); |
93 | } | 92 | } |
94 | } | 93 | } |
95 | up_write(&nilfs->ns_sem); | 94 | up_write(&nilfs->ns_sem); |
@@ -110,25 +109,30 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) | |||
110 | void nilfs_error(struct super_block *sb, const char *function, | 109 | void nilfs_error(struct super_block *sb, const char *function, |
111 | const char *fmt, ...) | 110 | const char *fmt, ...) |
112 | { | 111 | { |
113 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 112 | struct the_nilfs *nilfs = sb->s_fs_info; |
113 | struct va_format vaf; | ||
114 | va_list args; | 114 | va_list args; |
115 | 115 | ||
116 | va_start(args, fmt); | 116 | va_start(args, fmt); |
117 | printk(KERN_CRIT "NILFS error (device %s): %s: ", sb->s_id, function); | 117 | |
118 | vprintk(fmt, args); | 118 | vaf.fmt = fmt; |
119 | printk("\n"); | 119 | vaf.va = &args; |
120 | |||
121 | printk(KERN_CRIT "NILFS error (device %s): %s: %pV\n", | ||
122 | sb->s_id, function, &vaf); | ||
123 | |||
120 | va_end(args); | 124 | va_end(args); |
121 | 125 | ||
122 | if (!(sb->s_flags & MS_RDONLY)) { | 126 | if (!(sb->s_flags & MS_RDONLY)) { |
123 | nilfs_set_error(sbi); | 127 | nilfs_set_error(sb); |
124 | 128 | ||
125 | if (nilfs_test_opt(sbi, ERRORS_RO)) { | 129 | if (nilfs_test_opt(nilfs, ERRORS_RO)) { |
126 | printk(KERN_CRIT "Remounting filesystem read-only\n"); | 130 | printk(KERN_CRIT "Remounting filesystem read-only\n"); |
127 | sb->s_flags |= MS_RDONLY; | 131 | sb->s_flags |= MS_RDONLY; |
128 | } | 132 | } |
129 | } | 133 | } |
130 | 134 | ||
131 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 135 | if (nilfs_test_opt(nilfs, ERRORS_PANIC)) |
132 | panic("NILFS (device %s): panic forced after error\n", | 136 | panic("NILFS (device %s): panic forced after error\n", |
133 | sb->s_id); | 137 | sb->s_id); |
134 | } | 138 | } |
@@ -136,18 +140,22 @@ void nilfs_error(struct super_block *sb, const char *function, | |||
136 | void nilfs_warning(struct super_block *sb, const char *function, | 140 | void nilfs_warning(struct super_block *sb, const char *function, |
137 | const char *fmt, ...) | 141 | const char *fmt, ...) |
138 | { | 142 | { |
143 | struct va_format vaf; | ||
139 | va_list args; | 144 | va_list args; |
140 | 145 | ||
141 | va_start(args, fmt); | 146 | va_start(args, fmt); |
142 | printk(KERN_WARNING "NILFS warning (device %s): %s: ", | 147 | |
143 | sb->s_id, function); | 148 | vaf.fmt = fmt; |
144 | vprintk(fmt, args); | 149 | vaf.va = &args; |
145 | printk("\n"); | 150 | |
151 | printk(KERN_WARNING "NILFS warning (device %s): %s: %pV\n", | ||
152 | sb->s_id, function, &vaf); | ||
153 | |||
146 | va_end(args); | 154 | va_end(args); |
147 | } | 155 | } |
148 | 156 | ||
149 | 157 | ||
150 | struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | 158 | struct inode *nilfs_alloc_inode(struct super_block *sb) |
151 | { | 159 | { |
152 | struct nilfs_inode_info *ii; | 160 | struct nilfs_inode_info *ii; |
153 | 161 | ||
@@ -156,39 +164,41 @@ struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | |||
156 | return NULL; | 164 | return NULL; |
157 | ii->i_bh = NULL; | 165 | ii->i_bh = NULL; |
158 | ii->i_state = 0; | 166 | ii->i_state = 0; |
167 | ii->i_cno = 0; | ||
159 | ii->vfs_inode.i_version = 1; | 168 | ii->vfs_inode.i_version = 1; |
160 | nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi); | 169 | nilfs_mapping_init(&ii->i_btnode_cache, &ii->vfs_inode, sb->s_bdi); |
161 | return &ii->vfs_inode; | 170 | return &ii->vfs_inode; |
162 | } | 171 | } |
163 | 172 | ||
164 | struct inode *nilfs_alloc_inode(struct super_block *sb) | 173 | static void nilfs_i_callback(struct rcu_head *head) |
165 | { | 174 | { |
166 | return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs); | 175 | struct inode *inode = container_of(head, struct inode, i_rcu); |
176 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | ||
177 | |||
178 | INIT_LIST_HEAD(&inode->i_dentry); | ||
179 | |||
180 | if (mdi) { | ||
181 | kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ | ||
182 | kfree(mdi); | ||
183 | } | ||
184 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | ||
167 | } | 185 | } |
168 | 186 | ||
169 | void nilfs_destroy_inode(struct inode *inode) | 187 | void nilfs_destroy_inode(struct inode *inode) |
170 | { | 188 | { |
171 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | 189 | call_rcu(&inode->i_rcu, nilfs_i_callback); |
172 | } | 190 | } |
173 | 191 | ||
174 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) | 192 | static int nilfs_sync_super(struct super_block *sb, int flag) |
175 | { | 193 | { |
176 | struct the_nilfs *nilfs = sbi->s_nilfs; | 194 | struct the_nilfs *nilfs = sb->s_fs_info; |
177 | int err; | 195 | int err; |
178 | 196 | ||
179 | retry: | 197 | retry: |
180 | set_buffer_dirty(nilfs->ns_sbh[0]); | 198 | set_buffer_dirty(nilfs->ns_sbh[0]); |
181 | 199 | if (nilfs_test_opt(nilfs, BARRIER)) { | |
182 | if (nilfs_test_opt(sbi, BARRIER)) { | ||
183 | err = __sync_dirty_buffer(nilfs->ns_sbh[0], | 200 | err = __sync_dirty_buffer(nilfs->ns_sbh[0], |
184 | WRITE_SYNC | WRITE_BARRIER); | 201 | WRITE_SYNC | WRITE_FLUSH_FUA); |
185 | if (err == -EOPNOTSUPP) { | ||
186 | nilfs_warning(sbi->s_super, __func__, | ||
187 | "barrier-based sync failed. " | ||
188 | "disabling barriers\n"); | ||
189 | nilfs_clear_opt(sbi, BARRIER); | ||
190 | goto retry; | ||
191 | } | ||
192 | } else { | 202 | } else { |
193 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); | 203 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); |
194 | } | 204 | } |
@@ -253,10 +263,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, | |||
253 | spin_unlock(&nilfs->ns_last_segment_lock); | 263 | spin_unlock(&nilfs->ns_last_segment_lock); |
254 | } | 264 | } |
255 | 265 | ||
256 | struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, | 266 | struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, |
257 | int flip) | 267 | int flip) |
258 | { | 268 | { |
259 | struct the_nilfs *nilfs = sbi->s_nilfs; | 269 | struct the_nilfs *nilfs = sb->s_fs_info; |
260 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 270 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
261 | 271 | ||
262 | /* nilfs->ns_sem must be locked by the caller. */ | 272 | /* nilfs->ns_sem must be locked by the caller. */ |
@@ -266,7 +276,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, | |||
266 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); | 276 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); |
267 | } else { | 277 | } else { |
268 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", | 278 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", |
269 | sbi->s_super->s_id); | 279 | sb->s_id); |
270 | return NULL; | 280 | return NULL; |
271 | } | 281 | } |
272 | } else if (sbp[1] && | 282 | } else if (sbp[1] && |
@@ -280,9 +290,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, | |||
280 | return sbp; | 290 | return sbp; |
281 | } | 291 | } |
282 | 292 | ||
283 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) | 293 | int nilfs_commit_super(struct super_block *sb, int flag) |
284 | { | 294 | { |
285 | struct the_nilfs *nilfs = sbi->s_nilfs; | 295 | struct the_nilfs *nilfs = sb->s_fs_info; |
286 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 296 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
287 | time_t t; | 297 | time_t t; |
288 | 298 | ||
@@ -302,27 +312,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) | |||
302 | nilfs->ns_sbsize)); | 312 | nilfs->ns_sbsize)); |
303 | } | 313 | } |
304 | clear_nilfs_sb_dirty(nilfs); | 314 | clear_nilfs_sb_dirty(nilfs); |
305 | return nilfs_sync_super(sbi, flag); | 315 | return nilfs_sync_super(sb, flag); |
306 | } | 316 | } |
307 | 317 | ||
308 | /** | 318 | /** |
309 | * nilfs_cleanup_super() - write filesystem state for cleanup | 319 | * nilfs_cleanup_super() - write filesystem state for cleanup |
310 | * @sbi: nilfs_sb_info to be unmounted or degraded to read-only | 320 | * @sb: super block instance to be unmounted or degraded to read-only |
311 | * | 321 | * |
312 | * This function restores state flags in the on-disk super block. | 322 | * This function restores state flags in the on-disk super block. |
313 | * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the | 323 | * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the |
314 | * filesystem was not clean previously. | 324 | * filesystem was not clean previously. |
315 | */ | 325 | */ |
316 | int nilfs_cleanup_super(struct nilfs_sb_info *sbi) | 326 | int nilfs_cleanup_super(struct super_block *sb) |
317 | { | 327 | { |
328 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
318 | struct nilfs_super_block **sbp; | 329 | struct nilfs_super_block **sbp; |
319 | int flag = NILFS_SB_COMMIT; | 330 | int flag = NILFS_SB_COMMIT; |
320 | int ret = -EIO; | 331 | int ret = -EIO; |
321 | 332 | ||
322 | sbp = nilfs_prepare_super(sbi, 0); | 333 | sbp = nilfs_prepare_super(sb, 0); |
323 | if (sbp) { | 334 | if (sbp) { |
324 | sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); | 335 | sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); |
325 | nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); | 336 | nilfs_set_log_cursor(sbp[0], nilfs); |
326 | if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { | 337 | if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { |
327 | /* | 338 | /* |
328 | * make the "clean" flag also to the opposite | 339 | * make the "clean" flag also to the opposite |
@@ -332,43 +343,162 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi) | |||
332 | sbp[1]->s_state = sbp[0]->s_state; | 343 | sbp[1]->s_state = sbp[0]->s_state; |
333 | flag = NILFS_SB_COMMIT_ALL; | 344 | flag = NILFS_SB_COMMIT_ALL; |
334 | } | 345 | } |
335 | ret = nilfs_commit_super(sbi, flag); | 346 | ret = nilfs_commit_super(sb, flag); |
336 | } | 347 | } |
337 | return ret; | 348 | return ret; |
338 | } | 349 | } |
339 | 350 | ||
340 | static void nilfs_put_super(struct super_block *sb) | 351 | /** |
352 | * nilfs_move_2nd_super - relocate secondary super block | ||
353 | * @sb: super block instance | ||
354 | * @sb2off: new offset of the secondary super block (in bytes) | ||
355 | */ | ||
356 | static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off) | ||
341 | { | 357 | { |
342 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 358 | struct the_nilfs *nilfs = sb->s_fs_info; |
343 | struct the_nilfs *nilfs = sbi->s_nilfs; | 359 | struct buffer_head *nsbh; |
360 | struct nilfs_super_block *nsbp; | ||
361 | sector_t blocknr, newblocknr; | ||
362 | unsigned long offset; | ||
363 | int sb2i = -1; /* array index of the secondary superblock */ | ||
364 | int ret = 0; | ||
344 | 365 | ||
345 | lock_kernel(); | 366 | /* nilfs->ns_sem must be locked by the caller. */ |
367 | if (nilfs->ns_sbh[1] && | ||
368 | nilfs->ns_sbh[1]->b_blocknr > nilfs->ns_first_data_block) { | ||
369 | sb2i = 1; | ||
370 | blocknr = nilfs->ns_sbh[1]->b_blocknr; | ||
371 | } else if (nilfs->ns_sbh[0]->b_blocknr > nilfs->ns_first_data_block) { | ||
372 | sb2i = 0; | ||
373 | blocknr = nilfs->ns_sbh[0]->b_blocknr; | ||
374 | } | ||
375 | if (sb2i >= 0 && (u64)blocknr << nilfs->ns_blocksize_bits == sb2off) | ||
376 | goto out; /* super block location is unchanged */ | ||
377 | |||
378 | /* Get new super block buffer */ | ||
379 | newblocknr = sb2off >> nilfs->ns_blocksize_bits; | ||
380 | offset = sb2off & (nilfs->ns_blocksize - 1); | ||
381 | nsbh = sb_getblk(sb, newblocknr); | ||
382 | if (!nsbh) { | ||
383 | printk(KERN_WARNING | ||
384 | "NILFS warning: unable to move secondary superblock " | ||
385 | "to block %llu\n", (unsigned long long)newblocknr); | ||
386 | ret = -EIO; | ||
387 | goto out; | ||
388 | } | ||
389 | nsbp = (void *)nsbh->b_data + offset; | ||
390 | memset(nsbp, 0, nilfs->ns_blocksize); | ||
391 | |||
392 | if (sb2i >= 0) { | ||
393 | memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize); | ||
394 | brelse(nilfs->ns_sbh[sb2i]); | ||
395 | nilfs->ns_sbh[sb2i] = nsbh; | ||
396 | nilfs->ns_sbp[sb2i] = nsbp; | ||
397 | } else if (nilfs->ns_sbh[0]->b_blocknr < nilfs->ns_first_data_block) { | ||
398 | /* secondary super block will be restored to index 1 */ | ||
399 | nilfs->ns_sbh[1] = nsbh; | ||
400 | nilfs->ns_sbp[1] = nsbp; | ||
401 | } else { | ||
402 | brelse(nsbh); | ||
403 | } | ||
404 | out: | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | /** | ||
409 | * nilfs_resize_fs - resize the filesystem | ||
410 | * @sb: super block instance | ||
411 | * @newsize: new size of the filesystem (in bytes) | ||
412 | */ | ||
413 | int nilfs_resize_fs(struct super_block *sb, __u64 newsize) | ||
414 | { | ||
415 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
416 | struct nilfs_super_block **sbp; | ||
417 | __u64 devsize, newnsegs; | ||
418 | loff_t sb2off; | ||
419 | int ret; | ||
420 | |||
421 | ret = -ERANGE; | ||
422 | devsize = i_size_read(sb->s_bdev->bd_inode); | ||
423 | if (newsize > devsize) | ||
424 | goto out; | ||
425 | |||
426 | /* | ||
427 | * Write lock is required to protect some functions depending | ||
428 | * on the number of segments, the number of reserved segments, | ||
429 | * and so forth. | ||
430 | */ | ||
431 | down_write(&nilfs->ns_segctor_sem); | ||
432 | |||
433 | sb2off = NILFS_SB2_OFFSET_BYTES(newsize); | ||
434 | newnsegs = sb2off >> nilfs->ns_blocksize_bits; | ||
435 | do_div(newnsegs, nilfs->ns_blocks_per_segment); | ||
436 | |||
437 | ret = nilfs_sufile_resize(nilfs->ns_sufile, newnsegs); | ||
438 | up_write(&nilfs->ns_segctor_sem); | ||
439 | if (ret < 0) | ||
440 | goto out; | ||
441 | |||
442 | ret = nilfs_construct_segment(sb); | ||
443 | if (ret < 0) | ||
444 | goto out; | ||
445 | |||
446 | down_write(&nilfs->ns_sem); | ||
447 | nilfs_move_2nd_super(sb, sb2off); | ||
448 | ret = -EIO; | ||
449 | sbp = nilfs_prepare_super(sb, 0); | ||
450 | if (likely(sbp)) { | ||
451 | nilfs_set_log_cursor(sbp[0], nilfs); | ||
452 | /* | ||
453 | * Drop NILFS_RESIZE_FS flag for compatibility with | ||
454 | * mount-time resize which may be implemented in a | ||
455 | * future release. | ||
456 | */ | ||
457 | sbp[0]->s_state = cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & | ||
458 | ~NILFS_RESIZE_FS); | ||
459 | sbp[0]->s_dev_size = cpu_to_le64(newsize); | ||
460 | sbp[0]->s_nsegments = cpu_to_le64(nilfs->ns_nsegments); | ||
461 | if (sbp[1]) | ||
462 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
463 | ret = nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); | ||
464 | } | ||
465 | up_write(&nilfs->ns_sem); | ||
466 | |||
467 | /* | ||
468 | * Reset the range of allocatable segments last. This order | ||
469 | * is important in the case of expansion because the secondary | ||
470 | * superblock must be protected from log write until migration | ||
471 | * completes. | ||
472 | */ | ||
473 | if (!ret) | ||
474 | nilfs_sufile_set_alloc_range(nilfs->ns_sufile, 0, newnsegs - 1); | ||
475 | out: | ||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | static void nilfs_put_super(struct super_block *sb) | ||
480 | { | ||
481 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
346 | 482 | ||
347 | nilfs_detach_segment_constructor(sbi); | 483 | nilfs_detach_log_writer(sb); |
348 | 484 | ||
349 | if (!(sb->s_flags & MS_RDONLY)) { | 485 | if (!(sb->s_flags & MS_RDONLY)) { |
350 | down_write(&nilfs->ns_sem); | 486 | down_write(&nilfs->ns_sem); |
351 | nilfs_cleanup_super(sbi); | 487 | nilfs_cleanup_super(sb); |
352 | up_write(&nilfs->ns_sem); | 488 | up_write(&nilfs->ns_sem); |
353 | } | 489 | } |
354 | down_write(&nilfs->ns_super_sem); | ||
355 | if (nilfs->ns_current == sbi) | ||
356 | nilfs->ns_current = NULL; | ||
357 | up_write(&nilfs->ns_super_sem); | ||
358 | |||
359 | nilfs_detach_checkpoint(sbi); | ||
360 | put_nilfs(sbi->s_nilfs); | ||
361 | sbi->s_super = NULL; | ||
362 | sb->s_fs_info = NULL; | ||
363 | nilfs_put_sbinfo(sbi); | ||
364 | 490 | ||
365 | unlock_kernel(); | 491 | iput(nilfs->ns_sufile); |
492 | iput(nilfs->ns_cpfile); | ||
493 | iput(nilfs->ns_dat); | ||
494 | |||
495 | destroy_nilfs(nilfs); | ||
496 | sb->s_fs_info = NULL; | ||
366 | } | 497 | } |
367 | 498 | ||
368 | static int nilfs_sync_fs(struct super_block *sb, int wait) | 499 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
369 | { | 500 | { |
370 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 501 | struct the_nilfs *nilfs = sb->s_fs_info; |
371 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
372 | struct nilfs_super_block **sbp; | 502 | struct nilfs_super_block **sbp; |
373 | int err = 0; | 503 | int err = 0; |
374 | 504 | ||
@@ -378,10 +508,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
378 | 508 | ||
379 | down_write(&nilfs->ns_sem); | 509 | down_write(&nilfs->ns_sem); |
380 | if (nilfs_sb_dirty(nilfs)) { | 510 | if (nilfs_sb_dirty(nilfs)) { |
381 | sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); | 511 | sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs)); |
382 | if (likely(sbp)) { | 512 | if (likely(sbp)) { |
383 | nilfs_set_log_cursor(sbp[0], nilfs); | 513 | nilfs_set_log_cursor(sbp[0], nilfs); |
384 | nilfs_commit_super(sbi, NILFS_SB_COMMIT); | 514 | nilfs_commit_super(sb, NILFS_SB_COMMIT); |
385 | } | 515 | } |
386 | } | 516 | } |
387 | up_write(&nilfs->ns_sem); | 517 | up_write(&nilfs->ns_sem); |
@@ -389,21 +519,22 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
389 | return err; | 519 | return err; |
390 | } | 520 | } |
391 | 521 | ||
392 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | 522 | int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, |
523 | struct nilfs_root **rootp) | ||
393 | { | 524 | { |
394 | struct the_nilfs *nilfs = sbi->s_nilfs; | 525 | struct the_nilfs *nilfs = sb->s_fs_info; |
526 | struct nilfs_root *root; | ||
395 | struct nilfs_checkpoint *raw_cp; | 527 | struct nilfs_checkpoint *raw_cp; |
396 | struct buffer_head *bh_cp; | 528 | struct buffer_head *bh_cp; |
397 | int err; | 529 | int err = -ENOMEM; |
398 | 530 | ||
399 | down_write(&nilfs->ns_super_sem); | 531 | root = nilfs_find_or_create_root( |
400 | list_add(&sbi->s_list, &nilfs->ns_supers); | 532 | nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno); |
401 | up_write(&nilfs->ns_super_sem); | 533 | if (!root) |
534 | return err; | ||
402 | 535 | ||
403 | err = -ENOMEM; | 536 | if (root->ifile) |
404 | sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); | 537 | goto reuse; /* already attached checkpoint */ |
405 | if (!sbi->s_ifile) | ||
406 | goto delist; | ||
407 | 538 | ||
408 | down_read(&nilfs->ns_segctor_sem); | 539 | down_read(&nilfs->ns_segctor_sem); |
409 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, | 540 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, |
@@ -419,45 +550,62 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
419 | } | 550 | } |
420 | goto failed; | 551 | goto failed; |
421 | } | 552 | } |
422 | err = nilfs_read_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode); | 553 | |
423 | if (unlikely(err)) | 554 | err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size, |
555 | &raw_cp->cp_ifile_inode, &root->ifile); | ||
556 | if (err) | ||
424 | goto failed_bh; | 557 | goto failed_bh; |
425 | atomic_set(&sbi->s_inodes_count, le64_to_cpu(raw_cp->cp_inodes_count)); | 558 | |
426 | atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); | 559 | atomic_set(&root->inodes_count, le64_to_cpu(raw_cp->cp_inodes_count)); |
560 | atomic_set(&root->blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); | ||
427 | 561 | ||
428 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 562 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
563 | |||
564 | reuse: | ||
565 | *rootp = root; | ||
429 | return 0; | 566 | return 0; |
430 | 567 | ||
431 | failed_bh: | 568 | failed_bh: |
432 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 569 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
433 | failed: | 570 | failed: |
434 | nilfs_mdt_destroy(sbi->s_ifile); | 571 | nilfs_put_root(root); |
435 | sbi->s_ifile = NULL; | 572 | |
573 | return err; | ||
574 | } | ||
575 | |||
576 | static int nilfs_freeze(struct super_block *sb) | ||
577 | { | ||
578 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
579 | int err; | ||
436 | 580 | ||
437 | delist: | 581 | if (sb->s_flags & MS_RDONLY) |
438 | down_write(&nilfs->ns_super_sem); | 582 | return 0; |
439 | list_del_init(&sbi->s_list); | ||
440 | up_write(&nilfs->ns_super_sem); | ||
441 | 583 | ||
584 | /* Mark super block clean */ | ||
585 | down_write(&nilfs->ns_sem); | ||
586 | err = nilfs_cleanup_super(sb); | ||
587 | up_write(&nilfs->ns_sem); | ||
442 | return err; | 588 | return err; |
443 | } | 589 | } |
444 | 590 | ||
445 | void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) | 591 | static int nilfs_unfreeze(struct super_block *sb) |
446 | { | 592 | { |
447 | struct the_nilfs *nilfs = sbi->s_nilfs; | 593 | struct the_nilfs *nilfs = sb->s_fs_info; |
448 | 594 | ||
449 | nilfs_mdt_destroy(sbi->s_ifile); | 595 | if (sb->s_flags & MS_RDONLY) |
450 | sbi->s_ifile = NULL; | 596 | return 0; |
451 | down_write(&nilfs->ns_super_sem); | 597 | |
452 | list_del_init(&sbi->s_list); | 598 | down_write(&nilfs->ns_sem); |
453 | up_write(&nilfs->ns_super_sem); | 599 | nilfs_setup_super(sb, false); |
600 | up_write(&nilfs->ns_sem); | ||
601 | return 0; | ||
454 | } | 602 | } |
455 | 603 | ||
456 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 604 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
457 | { | 605 | { |
458 | struct super_block *sb = dentry->d_sb; | 606 | struct super_block *sb = dentry->d_sb; |
459 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 607 | struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root; |
460 | struct the_nilfs *nilfs = sbi->s_nilfs; | 608 | struct the_nilfs *nilfs = root->nilfs; |
461 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 609 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
462 | unsigned long long blocks; | 610 | unsigned long long blocks; |
463 | unsigned long overhead; | 611 | unsigned long overhead; |
@@ -493,7 +641,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
493 | buf->f_bfree = nfreeblocks; | 641 | buf->f_bfree = nfreeblocks; |
494 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? | 642 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? |
495 | (buf->f_bfree - nrsvblocks) : 0; | 643 | (buf->f_bfree - nrsvblocks) : 0; |
496 | buf->f_files = atomic_read(&sbi->s_inodes_count); | 644 | buf->f_files = atomic_read(&root->inodes_count); |
497 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ | 645 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ |
498 | buf->f_namelen = NILFS_NAME_LEN; | 646 | buf->f_namelen = NILFS_NAME_LEN; |
499 | buf->f_fsid.val[0] = (u32)id; | 647 | buf->f_fsid.val[0] = (u32)id; |
@@ -505,22 +653,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
505 | static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | 653 | static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
506 | { | 654 | { |
507 | struct super_block *sb = vfs->mnt_sb; | 655 | struct super_block *sb = vfs->mnt_sb; |
508 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 656 | struct the_nilfs *nilfs = sb->s_fs_info; |
657 | struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; | ||
509 | 658 | ||
510 | if (!nilfs_test_opt(sbi, BARRIER)) | 659 | if (!nilfs_test_opt(nilfs, BARRIER)) |
511 | seq_puts(seq, ",nobarrier"); | 660 | seq_puts(seq, ",nobarrier"); |
512 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 661 | if (root->cno != NILFS_CPTREE_CURRENT_CNO) |
513 | seq_printf(seq, ",cp=%llu", | 662 | seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); |
514 | (unsigned long long int)sbi->s_snapshot_cno); | 663 | if (nilfs_test_opt(nilfs, ERRORS_PANIC)) |
515 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | ||
516 | seq_puts(seq, ",errors=panic"); | 664 | seq_puts(seq, ",errors=panic"); |
517 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 665 | if (nilfs_test_opt(nilfs, ERRORS_CONT)) |
518 | seq_puts(seq, ",errors=continue"); | 666 | seq_puts(seq, ",errors=continue"); |
519 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | 667 | if (nilfs_test_opt(nilfs, STRICT_ORDER)) |
520 | seq_puts(seq, ",order=strict"); | 668 | seq_puts(seq, ",order=strict"); |
521 | if (nilfs_test_opt(sbi, NORECOVERY)) | 669 | if (nilfs_test_opt(nilfs, NORECOVERY)) |
522 | seq_puts(seq, ",norecovery"); | 670 | seq_puts(seq, ",norecovery"); |
523 | if (nilfs_test_opt(sbi, DISCARD)) | 671 | if (nilfs_test_opt(nilfs, DISCARD)) |
524 | seq_puts(seq, ",discard"); | 672 | seq_puts(seq, ",discard"); |
525 | 673 | ||
526 | return 0; | 674 | return 0; |
@@ -537,6 +685,8 @@ static const struct super_operations nilfs_sops = { | |||
537 | .put_super = nilfs_put_super, | 685 | .put_super = nilfs_put_super, |
538 | /* .write_super = nilfs_write_super, */ | 686 | /* .write_super = nilfs_write_super, */ |
539 | .sync_fs = nilfs_sync_fs, | 687 | .sync_fs = nilfs_sync_fs, |
688 | .freeze_fs = nilfs_freeze, | ||
689 | .unfreeze_fs = nilfs_unfreeze, | ||
540 | /* .write_super_lockfs */ | 690 | /* .write_super_lockfs */ |
541 | /* .unlockfs */ | 691 | /* .unlockfs */ |
542 | .statfs = nilfs_statfs, | 692 | .statfs = nilfs_statfs, |
@@ -545,48 +695,6 @@ static const struct super_operations nilfs_sops = { | |||
545 | .show_options = nilfs_show_options | 695 | .show_options = nilfs_show_options |
546 | }; | 696 | }; |
547 | 697 | ||
548 | static struct inode * | ||
549 | nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) | ||
550 | { | ||
551 | struct inode *inode; | ||
552 | |||
553 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && | ||
554 | ino != NILFS_SKETCH_INO) | ||
555 | return ERR_PTR(-ESTALE); | ||
556 | |||
557 | inode = nilfs_iget(sb, ino); | ||
558 | if (IS_ERR(inode)) | ||
559 | return ERR_CAST(inode); | ||
560 | if (generation && inode->i_generation != generation) { | ||
561 | iput(inode); | ||
562 | return ERR_PTR(-ESTALE); | ||
563 | } | ||
564 | |||
565 | return inode; | ||
566 | } | ||
567 | |||
568 | static struct dentry * | ||
569 | nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, | ||
570 | int fh_type) | ||
571 | { | ||
572 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
573 | nilfs_nfs_get_inode); | ||
574 | } | ||
575 | |||
576 | static struct dentry * | ||
577 | nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, | ||
578 | int fh_type) | ||
579 | { | ||
580 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
581 | nilfs_nfs_get_inode); | ||
582 | } | ||
583 | |||
584 | static const struct export_operations nilfs_export_ops = { | ||
585 | .fh_to_dentry = nilfs_fh_to_dentry, | ||
586 | .fh_to_parent = nilfs_fh_to_parent, | ||
587 | .get_parent = nilfs_get_parent, | ||
588 | }; | ||
589 | |||
590 | enum { | 698 | enum { |
591 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 699 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
592 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 700 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
@@ -609,10 +717,9 @@ static match_table_t tokens = { | |||
609 | 717 | ||
610 | static int parse_options(char *options, struct super_block *sb, int is_remount) | 718 | static int parse_options(char *options, struct super_block *sb, int is_remount) |
611 | { | 719 | { |
612 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 720 | struct the_nilfs *nilfs = sb->s_fs_info; |
613 | char *p; | 721 | char *p; |
614 | substring_t args[MAX_OPT_ARGS]; | 722 | substring_t args[MAX_OPT_ARGS]; |
615 | int option; | ||
616 | 723 | ||
617 | if (!options) | 724 | if (!options) |
618 | return 1; | 725 | return 1; |
@@ -625,64 +732,46 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
625 | token = match_token(p, tokens, args); | 732 | token = match_token(p, tokens, args); |
626 | switch (token) { | 733 | switch (token) { |
627 | case Opt_barrier: | 734 | case Opt_barrier: |
628 | nilfs_set_opt(sbi, BARRIER); | 735 | nilfs_set_opt(nilfs, BARRIER); |
629 | break; | 736 | break; |
630 | case Opt_nobarrier: | 737 | case Opt_nobarrier: |
631 | nilfs_clear_opt(sbi, BARRIER); | 738 | nilfs_clear_opt(nilfs, BARRIER); |
632 | break; | 739 | break; |
633 | case Opt_order: | 740 | case Opt_order: |
634 | if (strcmp(args[0].from, "relaxed") == 0) | 741 | if (strcmp(args[0].from, "relaxed") == 0) |
635 | /* Ordered data semantics */ | 742 | /* Ordered data semantics */ |
636 | nilfs_clear_opt(sbi, STRICT_ORDER); | 743 | nilfs_clear_opt(nilfs, STRICT_ORDER); |
637 | else if (strcmp(args[0].from, "strict") == 0) | 744 | else if (strcmp(args[0].from, "strict") == 0) |
638 | /* Strict in-order semantics */ | 745 | /* Strict in-order semantics */ |
639 | nilfs_set_opt(sbi, STRICT_ORDER); | 746 | nilfs_set_opt(nilfs, STRICT_ORDER); |
640 | else | 747 | else |
641 | return 0; | 748 | return 0; |
642 | break; | 749 | break; |
643 | case Opt_err_panic: | 750 | case Opt_err_panic: |
644 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC); | 751 | nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC); |
645 | break; | 752 | break; |
646 | case Opt_err_ro: | 753 | case Opt_err_ro: |
647 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO); | 754 | nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO); |
648 | break; | 755 | break; |
649 | case Opt_err_cont: | 756 | case Opt_err_cont: |
650 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); | 757 | nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT); |
651 | break; | 758 | break; |
652 | case Opt_snapshot: | 759 | case Opt_snapshot: |
653 | if (match_int(&args[0], &option) || option <= 0) | ||
654 | return 0; | ||
655 | if (is_remount) { | 760 | if (is_remount) { |
656 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | 761 | printk(KERN_ERR |
657 | printk(KERN_ERR | 762 | "NILFS: \"%s\" option is invalid " |
658 | "NILFS: cannot change regular " | 763 | "for remount.\n", p); |
659 | "mount to snapshot.\n"); | ||
660 | return 0; | ||
661 | } else if (option != sbi->s_snapshot_cno) { | ||
662 | printk(KERN_ERR | ||
663 | "NILFS: cannot remount to a " | ||
664 | "different snapshot.\n"); | ||
665 | return 0; | ||
666 | } | ||
667 | break; | ||
668 | } | ||
669 | if (!(sb->s_flags & MS_RDONLY)) { | ||
670 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
671 | "read/write. A read-only option is " | ||
672 | "required.\n"); | ||
673 | return 0; | 764 | return 0; |
674 | } | 765 | } |
675 | sbi->s_snapshot_cno = option; | ||
676 | nilfs_set_opt(sbi, SNAPSHOT); | ||
677 | break; | 766 | break; |
678 | case Opt_norecovery: | 767 | case Opt_norecovery: |
679 | nilfs_set_opt(sbi, NORECOVERY); | 768 | nilfs_set_opt(nilfs, NORECOVERY); |
680 | break; | 769 | break; |
681 | case Opt_discard: | 770 | case Opt_discard: |
682 | nilfs_set_opt(sbi, DISCARD); | 771 | nilfs_set_opt(nilfs, DISCARD); |
683 | break; | 772 | break; |
684 | case Opt_nodiscard: | 773 | case Opt_nodiscard: |
685 | nilfs_clear_opt(sbi, DISCARD); | 774 | nilfs_clear_opt(nilfs, DISCARD); |
686 | break; | 775 | break; |
687 | default: | 776 | default: |
688 | printk(KERN_ERR | 777 | printk(KERN_ERR |
@@ -694,25 +783,30 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
694 | } | 783 | } |
695 | 784 | ||
696 | static inline void | 785 | static inline void |
697 | nilfs_set_default_options(struct nilfs_sb_info *sbi, | 786 | nilfs_set_default_options(struct super_block *sb, |
698 | struct nilfs_super_block *sbp) | 787 | struct nilfs_super_block *sbp) |
699 | { | 788 | { |
700 | sbi->s_mount_opt = | 789 | struct the_nilfs *nilfs = sb->s_fs_info; |
790 | |||
791 | nilfs->ns_mount_opt = | ||
701 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; | 792 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; |
702 | } | 793 | } |
703 | 794 | ||
704 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 795 | static int nilfs_setup_super(struct super_block *sb, int is_mount) |
705 | { | 796 | { |
706 | struct the_nilfs *nilfs = sbi->s_nilfs; | 797 | struct the_nilfs *nilfs = sb->s_fs_info; |
707 | struct nilfs_super_block **sbp; | 798 | struct nilfs_super_block **sbp; |
708 | int max_mnt_count; | 799 | int max_mnt_count; |
709 | int mnt_count; | 800 | int mnt_count; |
710 | 801 | ||
711 | /* nilfs->ns_sem must be locked by the caller. */ | 802 | /* nilfs->ns_sem must be locked by the caller. */ |
712 | sbp = nilfs_prepare_super(sbi, 0); | 803 | sbp = nilfs_prepare_super(sb, 0); |
713 | if (!sbp) | 804 | if (!sbp) |
714 | return -EIO; | 805 | return -EIO; |
715 | 806 | ||
807 | if (!is_mount) | ||
808 | goto skip_mount_setup; | ||
809 | |||
716 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); | 810 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); |
717 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | 811 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); |
718 | 812 | ||
@@ -729,12 +823,15 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
729 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); | 823 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
730 | 824 | ||
731 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); | 825 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); |
826 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | ||
827 | |||
828 | skip_mount_setup: | ||
732 | sbp[0]->s_state = | 829 | sbp[0]->s_state = |
733 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); | 830 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); |
734 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | ||
735 | /* synchronize sbp[1] with sbp[0] */ | 831 | /* synchronize sbp[1] with sbp[0] */ |
736 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 832 | if (sbp[1]) |
737 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | 833 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
834 | return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); | ||
738 | } | 835 | } |
739 | 836 | ||
740 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, | 837 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, |
@@ -755,7 +852,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
755 | struct nilfs_super_block *sbp, | 852 | struct nilfs_super_block *sbp, |
756 | char *data) | 853 | char *data) |
757 | { | 854 | { |
758 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 855 | struct the_nilfs *nilfs = sb->s_fs_info; |
759 | 856 | ||
760 | sb->s_magic = le16_to_cpu(sbp->s_magic); | 857 | sb->s_magic = le16_to_cpu(sbp->s_magic); |
761 | 858 | ||
@@ -764,12 +861,12 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
764 | sb->s_flags |= MS_NOATIME; | 861 | sb->s_flags |= MS_NOATIME; |
765 | #endif | 862 | #endif |
766 | 863 | ||
767 | nilfs_set_default_options(sbi, sbp); | 864 | nilfs_set_default_options(sb, sbp); |
768 | 865 | ||
769 | sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); | 866 | nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid); |
770 | sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); | 867 | nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid); |
771 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); | 868 | nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval); |
772 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); | 869 | nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max); |
773 | 870 | ||
774 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; | 871 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; |
775 | } | 872 | } |
@@ -798,164 +895,233 @@ int nilfs_check_feature_compatibility(struct super_block *sb, | |||
798 | return 0; | 895 | return 0; |
799 | } | 896 | } |
800 | 897 | ||
898 | static int nilfs_get_root_dentry(struct super_block *sb, | ||
899 | struct nilfs_root *root, | ||
900 | struct dentry **root_dentry) | ||
901 | { | ||
902 | struct inode *inode; | ||
903 | struct dentry *dentry; | ||
904 | int ret = 0; | ||
905 | |||
906 | inode = nilfs_iget(sb, root, NILFS_ROOT_INO); | ||
907 | if (IS_ERR(inode)) { | ||
908 | printk(KERN_ERR "NILFS: get root inode failed\n"); | ||
909 | ret = PTR_ERR(inode); | ||
910 | goto out; | ||
911 | } | ||
912 | if (!S_ISDIR(inode->i_mode) || !inode->i_blocks || !inode->i_size) { | ||
913 | iput(inode); | ||
914 | printk(KERN_ERR "NILFS: corrupt root inode.\n"); | ||
915 | ret = -EINVAL; | ||
916 | goto out; | ||
917 | } | ||
918 | |||
919 | if (root->cno == NILFS_CPTREE_CURRENT_CNO) { | ||
920 | dentry = d_find_alias(inode); | ||
921 | if (!dentry) { | ||
922 | dentry = d_alloc_root(inode); | ||
923 | if (!dentry) { | ||
924 | iput(inode); | ||
925 | ret = -ENOMEM; | ||
926 | goto failed_dentry; | ||
927 | } | ||
928 | } else { | ||
929 | iput(inode); | ||
930 | } | ||
931 | } else { | ||
932 | dentry = d_obtain_alias(inode); | ||
933 | if (IS_ERR(dentry)) { | ||
934 | ret = PTR_ERR(dentry); | ||
935 | goto failed_dentry; | ||
936 | } | ||
937 | } | ||
938 | *root_dentry = dentry; | ||
939 | out: | ||
940 | return ret; | ||
941 | |||
942 | failed_dentry: | ||
943 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
944 | goto out; | ||
945 | } | ||
946 | |||
947 | static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, | ||
948 | struct dentry **root_dentry) | ||
949 | { | ||
950 | struct the_nilfs *nilfs = s->s_fs_info; | ||
951 | struct nilfs_root *root; | ||
952 | int ret; | ||
953 | |||
954 | down_read(&nilfs->ns_segctor_sem); | ||
955 | ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno); | ||
956 | up_read(&nilfs->ns_segctor_sem); | ||
957 | if (ret < 0) { | ||
958 | ret = (ret == -ENOENT) ? -EINVAL : ret; | ||
959 | goto out; | ||
960 | } else if (!ret) { | ||
961 | printk(KERN_ERR "NILFS: The specified checkpoint is " | ||
962 | "not a snapshot (checkpoint number=%llu).\n", | ||
963 | (unsigned long long)cno); | ||
964 | ret = -EINVAL; | ||
965 | goto out; | ||
966 | } | ||
967 | |||
968 | ret = nilfs_attach_checkpoint(s, cno, false, &root); | ||
969 | if (ret) { | ||
970 | printk(KERN_ERR "NILFS: error loading snapshot " | ||
971 | "(checkpoint number=%llu).\n", | ||
972 | (unsigned long long)cno); | ||
973 | goto out; | ||
974 | } | ||
975 | ret = nilfs_get_root_dentry(s, root, root_dentry); | ||
976 | nilfs_put_root(root); | ||
977 | out: | ||
978 | return ret; | ||
979 | } | ||
980 | |||
981 | static int nilfs_tree_was_touched(struct dentry *root_dentry) | ||
982 | { | ||
983 | return root_dentry->d_count > 1; | ||
984 | } | ||
985 | |||
986 | /** | ||
987 | * nilfs_try_to_shrink_tree() - try to shrink dentries of a checkpoint | ||
988 | * @root_dentry: root dentry of the tree to be shrunk | ||
989 | * | ||
990 | * This function returns true if the tree was in-use. | ||
991 | */ | ||
992 | static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) | ||
993 | { | ||
994 | if (have_submounts(root_dentry)) | ||
995 | return true; | ||
996 | shrink_dcache_parent(root_dentry); | ||
997 | return nilfs_tree_was_touched(root_dentry); | ||
998 | } | ||
999 | |||
1000 | int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) | ||
1001 | { | ||
1002 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
1003 | struct nilfs_root *root; | ||
1004 | struct inode *inode; | ||
1005 | struct dentry *dentry; | ||
1006 | int ret; | ||
1007 | |||
1008 | if (cno < 0 || cno > nilfs->ns_cno) | ||
1009 | return false; | ||
1010 | |||
1011 | if (cno >= nilfs_last_cno(nilfs)) | ||
1012 | return true; /* protect recent checkpoints */ | ||
1013 | |||
1014 | ret = false; | ||
1015 | root = nilfs_lookup_root(nilfs, cno); | ||
1016 | if (root) { | ||
1017 | inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO); | ||
1018 | if (inode) { | ||
1019 | dentry = d_find_alias(inode); | ||
1020 | if (dentry) { | ||
1021 | if (nilfs_tree_was_touched(dentry)) | ||
1022 | ret = nilfs_try_to_shrink_tree(dentry); | ||
1023 | dput(dentry); | ||
1024 | } | ||
1025 | iput(inode); | ||
1026 | } | ||
1027 | nilfs_put_root(root); | ||
1028 | } | ||
1029 | return ret; | ||
1030 | } | ||
1031 | |||
801 | /** | 1032 | /** |
802 | * nilfs_fill_super() - initialize a super block instance | 1033 | * nilfs_fill_super() - initialize a super block instance |
803 | * @sb: super_block | 1034 | * @sb: super_block |
804 | * @data: mount options | 1035 | * @data: mount options |
805 | * @silent: silent mode flag | 1036 | * @silent: silent mode flag |
806 | * @nilfs: the_nilfs struct | ||
807 | * | 1037 | * |
808 | * This function is called exclusively by nilfs->ns_mount_mutex. | 1038 | * This function is called exclusively by nilfs->ns_mount_mutex. |
809 | * So, the recovery process is protected from other simultaneous mounts. | 1039 | * So, the recovery process is protected from other simultaneous mounts. |
810 | */ | 1040 | */ |
811 | static int | 1041 | static int |
812 | nilfs_fill_super(struct super_block *sb, void *data, int silent, | 1042 | nilfs_fill_super(struct super_block *sb, void *data, int silent) |
813 | struct the_nilfs *nilfs) | ||
814 | { | 1043 | { |
815 | struct nilfs_sb_info *sbi; | 1044 | struct the_nilfs *nilfs; |
816 | struct inode *root; | 1045 | struct nilfs_root *fsroot; |
1046 | struct backing_dev_info *bdi; | ||
817 | __u64 cno; | 1047 | __u64 cno; |
818 | int err; | 1048 | int err; |
819 | 1049 | ||
820 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 1050 | nilfs = alloc_nilfs(sb->s_bdev); |
821 | if (!sbi) | 1051 | if (!nilfs) |
822 | return -ENOMEM; | 1052 | return -ENOMEM; |
823 | 1053 | ||
824 | sb->s_fs_info = sbi; | 1054 | sb->s_fs_info = nilfs; |
825 | 1055 | ||
826 | get_nilfs(nilfs); | 1056 | err = init_nilfs(nilfs, sb, (char *)data); |
827 | sbi->s_nilfs = nilfs; | ||
828 | sbi->s_super = sb; | ||
829 | atomic_set(&sbi->s_count, 1); | ||
830 | |||
831 | err = init_nilfs(nilfs, sbi, (char *)data); | ||
832 | if (err) | 1057 | if (err) |
833 | goto failed_sbi; | 1058 | goto failed_nilfs; |
834 | |||
835 | spin_lock_init(&sbi->s_inode_lock); | ||
836 | INIT_LIST_HEAD(&sbi->s_dirty_files); | ||
837 | INIT_LIST_HEAD(&sbi->s_list); | ||
838 | |||
839 | /* | ||
840 | * Following initialization is overlapped because | ||
841 | * nilfs_sb_info structure has been cleared at the beginning. | ||
842 | * But we reserve them to keep our interest and make ready | ||
843 | * for the future change. | ||
844 | */ | ||
845 | get_random_bytes(&sbi->s_next_generation, | ||
846 | sizeof(sbi->s_next_generation)); | ||
847 | spin_lock_init(&sbi->s_next_gen_lock); | ||
848 | 1059 | ||
849 | sb->s_op = &nilfs_sops; | 1060 | sb->s_op = &nilfs_sops; |
850 | sb->s_export_op = &nilfs_export_ops; | 1061 | sb->s_export_op = &nilfs_export_ops; |
851 | sb->s_root = NULL; | 1062 | sb->s_root = NULL; |
852 | sb->s_time_gran = 1; | 1063 | sb->s_time_gran = 1; |
853 | sb->s_bdi = nilfs->ns_bdi; | ||
854 | 1064 | ||
855 | err = load_nilfs(nilfs, sbi); | 1065 | bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; |
1066 | sb->s_bdi = bdi ? : &default_backing_dev_info; | ||
1067 | |||
1068 | err = load_nilfs(nilfs, sb); | ||
856 | if (err) | 1069 | if (err) |
857 | goto failed_sbi; | 1070 | goto failed_nilfs; |
858 | 1071 | ||
859 | cno = nilfs_last_cno(nilfs); | 1072 | cno = nilfs_last_cno(nilfs); |
860 | 1073 | err = nilfs_attach_checkpoint(sb, cno, true, &fsroot); | |
861 | if (sb->s_flags & MS_RDONLY) { | ||
862 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
863 | down_read(&nilfs->ns_segctor_sem); | ||
864 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, | ||
865 | sbi->s_snapshot_cno); | ||
866 | up_read(&nilfs->ns_segctor_sem); | ||
867 | if (err < 0) { | ||
868 | if (err == -ENOENT) | ||
869 | err = -EINVAL; | ||
870 | goto failed_sbi; | ||
871 | } | ||
872 | if (!err) { | ||
873 | printk(KERN_ERR | ||
874 | "NILFS: The specified checkpoint is " | ||
875 | "not a snapshot " | ||
876 | "(checkpoint number=%llu).\n", | ||
877 | (unsigned long long)sbi->s_snapshot_cno); | ||
878 | err = -EINVAL; | ||
879 | goto failed_sbi; | ||
880 | } | ||
881 | cno = sbi->s_snapshot_cno; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | err = nilfs_attach_checkpoint(sbi, cno); | ||
886 | if (err) { | 1074 | if (err) { |
887 | printk(KERN_ERR "NILFS: error loading a checkpoint" | 1075 | printk(KERN_ERR "NILFS: error loading last checkpoint " |
888 | " (checkpoint number=%llu).\n", (unsigned long long)cno); | 1076 | "(checkpoint number=%llu).\n", (unsigned long long)cno); |
889 | goto failed_sbi; | 1077 | goto failed_unload; |
890 | } | 1078 | } |
891 | 1079 | ||
892 | if (!(sb->s_flags & MS_RDONLY)) { | 1080 | if (!(sb->s_flags & MS_RDONLY)) { |
893 | err = nilfs_attach_segment_constructor(sbi); | 1081 | err = nilfs_attach_log_writer(sb, fsroot); |
894 | if (err) | 1082 | if (err) |
895 | goto failed_checkpoint; | 1083 | goto failed_checkpoint; |
896 | } | 1084 | } |
897 | 1085 | ||
898 | root = nilfs_iget(sb, NILFS_ROOT_INO); | 1086 | err = nilfs_get_root_dentry(sb, fsroot, &sb->s_root); |
899 | if (IS_ERR(root)) { | 1087 | if (err) |
900 | printk(KERN_ERR "NILFS: get root inode failed\n"); | ||
901 | err = PTR_ERR(root); | ||
902 | goto failed_segctor; | ||
903 | } | ||
904 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | ||
905 | iput(root); | ||
906 | printk(KERN_ERR "NILFS: corrupt root inode.\n"); | ||
907 | err = -EINVAL; | ||
908 | goto failed_segctor; | ||
909 | } | ||
910 | sb->s_root = d_alloc_root(root); | ||
911 | if (!sb->s_root) { | ||
912 | iput(root); | ||
913 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
914 | err = -ENOMEM; | ||
915 | goto failed_segctor; | 1088 | goto failed_segctor; |
916 | } | 1089 | |
1090 | nilfs_put_root(fsroot); | ||
917 | 1091 | ||
918 | if (!(sb->s_flags & MS_RDONLY)) { | 1092 | if (!(sb->s_flags & MS_RDONLY)) { |
919 | down_write(&nilfs->ns_sem); | 1093 | down_write(&nilfs->ns_sem); |
920 | nilfs_setup_super(sbi); | 1094 | nilfs_setup_super(sb, true); |
921 | up_write(&nilfs->ns_sem); | 1095 | up_write(&nilfs->ns_sem); |
922 | } | 1096 | } |
923 | 1097 | ||
924 | down_write(&nilfs->ns_super_sem); | ||
925 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | ||
926 | nilfs->ns_current = sbi; | ||
927 | up_write(&nilfs->ns_super_sem); | ||
928 | |||
929 | return 0; | 1098 | return 0; |
930 | 1099 | ||
931 | failed_segctor: | 1100 | failed_segctor: |
932 | nilfs_detach_segment_constructor(sbi); | 1101 | nilfs_detach_log_writer(sb); |
933 | 1102 | ||
934 | failed_checkpoint: | 1103 | failed_checkpoint: |
935 | nilfs_detach_checkpoint(sbi); | 1104 | nilfs_put_root(fsroot); |
936 | 1105 | ||
937 | failed_sbi: | 1106 | failed_unload: |
938 | put_nilfs(nilfs); | 1107 | iput(nilfs->ns_sufile); |
939 | sb->s_fs_info = NULL; | 1108 | iput(nilfs->ns_cpfile); |
940 | nilfs_put_sbinfo(sbi); | 1109 | iput(nilfs->ns_dat); |
1110 | |||
1111 | failed_nilfs: | ||
1112 | destroy_nilfs(nilfs); | ||
941 | return err; | 1113 | return err; |
942 | } | 1114 | } |
943 | 1115 | ||
944 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) | 1116 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) |
945 | { | 1117 | { |
946 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 1118 | struct the_nilfs *nilfs = sb->s_fs_info; |
947 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
948 | unsigned long old_sb_flags; | 1119 | unsigned long old_sb_flags; |
949 | struct nilfs_mount_options old_opts; | 1120 | unsigned long old_mount_opt; |
950 | int was_snapshot, err; | 1121 | int err; |
951 | |||
952 | lock_kernel(); | ||
953 | 1122 | ||
954 | down_write(&nilfs->ns_super_sem); | ||
955 | old_sb_flags = sb->s_flags; | 1123 | old_sb_flags = sb->s_flags; |
956 | old_opts.mount_opt = sbi->s_mount_opt; | 1124 | old_mount_opt = nilfs->ns_mount_opt; |
957 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | ||
958 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | ||
959 | 1125 | ||
960 | if (!parse_options(data, sb, 1)) { | 1126 | if (!parse_options(data, sb, 1)) { |
961 | err = -EINVAL; | 1127 | err = -EINVAL; |
@@ -964,11 +1130,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
964 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 1130 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
965 | 1131 | ||
966 | err = -EINVAL; | 1132 | err = -EINVAL; |
967 | if (was_snapshot && !(*flags & MS_RDONLY)) { | ||
968 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " | ||
969 | "read/write.\n", sb->s_id); | ||
970 | goto restore_opts; | ||
971 | } | ||
972 | 1133 | ||
973 | if (!nilfs_valid_fs(nilfs)) { | 1134 | if (!nilfs_valid_fs(nilfs)) { |
974 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 1135 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
@@ -980,8 +1141,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
980 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 1141 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
981 | goto out; | 1142 | goto out; |
982 | if (*flags & MS_RDONLY) { | 1143 | if (*flags & MS_RDONLY) { |
983 | /* Shutting down the segment constructor */ | 1144 | /* Shutting down log writer */ |
984 | nilfs_detach_segment_constructor(sbi); | 1145 | nilfs_detach_log_writer(sb); |
985 | sb->s_flags |= MS_RDONLY; | 1146 | sb->s_flags |= MS_RDONLY; |
986 | 1147 | ||
987 | /* | 1148 | /* |
@@ -989,10 +1150,11 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
989 | * the RDONLY flag and then mark the partition as valid again. | 1150 | * the RDONLY flag and then mark the partition as valid again. |
990 | */ | 1151 | */ |
991 | down_write(&nilfs->ns_sem); | 1152 | down_write(&nilfs->ns_sem); |
992 | nilfs_cleanup_super(sbi); | 1153 | nilfs_cleanup_super(sb); |
993 | up_write(&nilfs->ns_sem); | 1154 | up_write(&nilfs->ns_sem); |
994 | } else { | 1155 | } else { |
995 | __u64 features; | 1156 | __u64 features; |
1157 | struct nilfs_root *root; | ||
996 | 1158 | ||
997 | /* | 1159 | /* |
998 | * Mounting a RDONLY partition read-write, so reread and | 1160 | * Mounting a RDONLY partition read-write, so reread and |
@@ -1014,31 +1176,26 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
1014 | 1176 | ||
1015 | sb->s_flags &= ~MS_RDONLY; | 1177 | sb->s_flags &= ~MS_RDONLY; |
1016 | 1178 | ||
1017 | err = nilfs_attach_segment_constructor(sbi); | 1179 | root = NILFS_I(sb->s_root->d_inode)->i_root; |
1180 | err = nilfs_attach_log_writer(sb, root); | ||
1018 | if (err) | 1181 | if (err) |
1019 | goto restore_opts; | 1182 | goto restore_opts; |
1020 | 1183 | ||
1021 | down_write(&nilfs->ns_sem); | 1184 | down_write(&nilfs->ns_sem); |
1022 | nilfs_setup_super(sbi); | 1185 | nilfs_setup_super(sb, true); |
1023 | up_write(&nilfs->ns_sem); | 1186 | up_write(&nilfs->ns_sem); |
1024 | } | 1187 | } |
1025 | out: | 1188 | out: |
1026 | up_write(&nilfs->ns_super_sem); | ||
1027 | unlock_kernel(); | ||
1028 | return 0; | 1189 | return 0; |
1029 | 1190 | ||
1030 | restore_opts: | 1191 | restore_opts: |
1031 | sb->s_flags = old_sb_flags; | 1192 | sb->s_flags = old_sb_flags; |
1032 | sbi->s_mount_opt = old_opts.mount_opt; | 1193 | nilfs->ns_mount_opt = old_mount_opt; |
1033 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | ||
1034 | up_write(&nilfs->ns_super_sem); | ||
1035 | unlock_kernel(); | ||
1036 | return err; | 1194 | return err; |
1037 | } | 1195 | } |
1038 | 1196 | ||
1039 | struct nilfs_super_data { | 1197 | struct nilfs_super_data { |
1040 | struct block_device *bdev; | 1198 | struct block_device *bdev; |
1041 | struct nilfs_sb_info *sbi; | ||
1042 | __u64 cno; | 1199 | __u64 cno; |
1043 | int flags; | 1200 | int flags; |
1044 | }; | 1201 | }; |
@@ -1052,7 +1209,7 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1052 | { | 1209 | { |
1053 | char *p, *options = data; | 1210 | char *p, *options = data; |
1054 | substring_t args[MAX_OPT_ARGS]; | 1211 | substring_t args[MAX_OPT_ARGS]; |
1055 | int option, token; | 1212 | int token; |
1056 | int ret = 0; | 1213 | int ret = 0; |
1057 | 1214 | ||
1058 | do { | 1215 | do { |
@@ -1060,16 +1217,18 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1060 | if (p != NULL && *p) { | 1217 | if (p != NULL && *p) { |
1061 | token = match_token(p, tokens, args); | 1218 | token = match_token(p, tokens, args); |
1062 | if (token == Opt_snapshot) { | 1219 | if (token == Opt_snapshot) { |
1063 | if (!(sd->flags & MS_RDONLY)) | 1220 | if (!(sd->flags & MS_RDONLY)) { |
1064 | ret++; | 1221 | ret++; |
1065 | else { | 1222 | } else { |
1066 | ret = match_int(&args[0], &option); | 1223 | sd->cno = simple_strtoull(args[0].from, |
1067 | if (!ret) { | 1224 | NULL, 0); |
1068 | if (option > 0) | 1225 | /* |
1069 | sd->cno = option; | 1226 | * No need to see the end pointer; |
1070 | else | 1227 | * match_token() has done syntax |
1071 | ret++; | 1228 | * checking. |
1072 | } | 1229 | */ |
1230 | if (sd->cno == 0) | ||
1231 | ret++; | ||
1073 | } | 1232 | } |
1074 | } | 1233 | } |
1075 | if (ret) | 1234 | if (ret) |
@@ -1086,43 +1245,33 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1086 | 1245 | ||
1087 | static int nilfs_set_bdev_super(struct super_block *s, void *data) | 1246 | static int nilfs_set_bdev_super(struct super_block *s, void *data) |
1088 | { | 1247 | { |
1089 | struct nilfs_super_data *sd = data; | 1248 | s->s_bdev = data; |
1090 | |||
1091 | s->s_bdev = sd->bdev; | ||
1092 | s->s_dev = s->s_bdev->bd_dev; | 1249 | s->s_dev = s->s_bdev->bd_dev; |
1093 | return 0; | 1250 | return 0; |
1094 | } | 1251 | } |
1095 | 1252 | ||
1096 | static int nilfs_test_bdev_super(struct super_block *s, void *data) | 1253 | static int nilfs_test_bdev_super(struct super_block *s, void *data) |
1097 | { | 1254 | { |
1098 | struct nilfs_super_data *sd = data; | 1255 | return (void *)s->s_bdev == data; |
1099 | |||
1100 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; | ||
1101 | } | 1256 | } |
1102 | 1257 | ||
1103 | static int | 1258 | static struct dentry * |
1104 | nilfs_get_sb(struct file_system_type *fs_type, int flags, | 1259 | nilfs_mount(struct file_system_type *fs_type, int flags, |
1105 | const char *dev_name, void *data, struct vfsmount *mnt) | 1260 | const char *dev_name, void *data) |
1106 | { | 1261 | { |
1107 | struct nilfs_super_data sd; | 1262 | struct nilfs_super_data sd; |
1108 | struct super_block *s; | 1263 | struct super_block *s; |
1109 | fmode_t mode = FMODE_READ; | 1264 | fmode_t mode = FMODE_READ | FMODE_EXCL; |
1110 | struct the_nilfs *nilfs; | 1265 | struct dentry *root_dentry; |
1111 | int err, need_to_close = 1; | 1266 | int err, s_new = false; |
1112 | 1267 | ||
1113 | if (!(flags & MS_RDONLY)) | 1268 | if (!(flags & MS_RDONLY)) |
1114 | mode |= FMODE_WRITE; | 1269 | mode |= FMODE_WRITE; |
1115 | 1270 | ||
1116 | sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type); | 1271 | sd.bdev = blkdev_get_by_path(dev_name, mode, fs_type); |
1117 | if (IS_ERR(sd.bdev)) | 1272 | if (IS_ERR(sd.bdev)) |
1118 | return PTR_ERR(sd.bdev); | 1273 | return ERR_CAST(sd.bdev); |
1119 | 1274 | ||
1120 | /* | ||
1121 | * To get mount instance using sget() vfs-routine, NILFS needs | ||
1122 | * much more information than normal filesystems to identify mount | ||
1123 | * instance. For snapshot mounts, not only a mount type (ro-mount | ||
1124 | * or rw-mount) but also a checkpoint number is required. | ||
1125 | */ | ||
1126 | sd.cno = 0; | 1275 | sd.cno = 0; |
1127 | sd.flags = flags; | 1276 | sd.flags = flags; |
1128 | if (nilfs_identify((char *)data, &sd)) { | 1277 | if (nilfs_identify((char *)data, &sd)) { |
@@ -1130,101 +1279,91 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1130 | goto failed; | 1279 | goto failed; |
1131 | } | 1280 | } |
1132 | 1281 | ||
1133 | nilfs = find_or_create_nilfs(sd.bdev); | ||
1134 | if (!nilfs) { | ||
1135 | err = -ENOMEM; | ||
1136 | goto failed; | ||
1137 | } | ||
1138 | |||
1139 | mutex_lock(&nilfs->ns_mount_mutex); | ||
1140 | |||
1141 | if (!sd.cno) { | ||
1142 | /* | ||
1143 | * Check if an exclusive mount exists or not. | ||
1144 | * Snapshot mounts coexist with a current mount | ||
1145 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | ||
1146 | * ro-mount are mutually exclusive. | ||
1147 | */ | ||
1148 | down_read(&nilfs->ns_super_sem); | ||
1149 | if (nilfs->ns_current && | ||
1150 | ((nilfs->ns_current->s_super->s_flags ^ flags) | ||
1151 | & MS_RDONLY)) { | ||
1152 | up_read(&nilfs->ns_super_sem); | ||
1153 | err = -EBUSY; | ||
1154 | goto failed_unlock; | ||
1155 | } | ||
1156 | up_read(&nilfs->ns_super_sem); | ||
1157 | } | ||
1158 | |||
1159 | /* | ||
1160 | * Find existing nilfs_sb_info struct | ||
1161 | */ | ||
1162 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | ||
1163 | |||
1164 | /* | 1282 | /* |
1165 | * Get super block instance holding the nilfs_sb_info struct. | 1283 | * once the super is inserted into the list by sget, s_umount |
1166 | * A new instance is allocated if no existing mount is present or | 1284 | * will protect the lockfs code from trying to start a snapshot |
1167 | * existing instance has been unmounted. | 1285 | * while we are mounting |
1168 | */ | 1286 | */ |
1169 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | 1287 | mutex_lock(&sd.bdev->bd_fsfreeze_mutex); |
1170 | if (sd.sbi) | 1288 | if (sd.bdev->bd_fsfreeze_count > 0) { |
1171 | nilfs_put_sbinfo(sd.sbi); | 1289 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); |
1172 | 1290 | err = -EBUSY; | |
1291 | goto failed; | ||
1292 | } | ||
1293 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); | ||
1294 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | ||
1173 | if (IS_ERR(s)) { | 1295 | if (IS_ERR(s)) { |
1174 | err = PTR_ERR(s); | 1296 | err = PTR_ERR(s); |
1175 | goto failed_unlock; | 1297 | goto failed; |
1176 | } | 1298 | } |
1177 | 1299 | ||
1178 | if (!s->s_root) { | 1300 | if (!s->s_root) { |
1179 | char b[BDEVNAME_SIZE]; | 1301 | char b[BDEVNAME_SIZE]; |
1180 | 1302 | ||
1303 | s_new = true; | ||
1304 | |||
1181 | /* New superblock instance created */ | 1305 | /* New superblock instance created */ |
1182 | s->s_flags = flags; | 1306 | s->s_flags = flags; |
1183 | s->s_mode = mode; | 1307 | s->s_mode = mode; |
1184 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1308 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
1185 | sb_set_blocksize(s, block_size(sd.bdev)); | 1309 | sb_set_blocksize(s, block_size(sd.bdev)); |
1186 | 1310 | ||
1187 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0, | 1311 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
1188 | nilfs); | ||
1189 | if (err) | 1312 | if (err) |
1190 | goto cancel_new; | 1313 | goto failed_super; |
1191 | 1314 | ||
1192 | s->s_flags |= MS_ACTIVE; | 1315 | s->s_flags |= MS_ACTIVE; |
1193 | need_to_close = 0; | 1316 | } else if (!sd.cno) { |
1317 | int busy = false; | ||
1318 | |||
1319 | if (nilfs_tree_was_touched(s->s_root)) { | ||
1320 | busy = nilfs_try_to_shrink_tree(s->s_root); | ||
1321 | if (busy && (flags ^ s->s_flags) & MS_RDONLY) { | ||
1322 | printk(KERN_ERR "NILFS: the device already " | ||
1323 | "has a %s mount.\n", | ||
1324 | (s->s_flags & MS_RDONLY) ? | ||
1325 | "read-only" : "read/write"); | ||
1326 | err = -EBUSY; | ||
1327 | goto failed_super; | ||
1328 | } | ||
1329 | } | ||
1330 | if (!busy) { | ||
1331 | /* | ||
1332 | * Try remount to setup mount states if the current | ||
1333 | * tree is not mounted and only snapshots use this sb. | ||
1334 | */ | ||
1335 | err = nilfs_remount(s, &flags, data); | ||
1336 | if (err) | ||
1337 | goto failed_super; | ||
1338 | } | ||
1194 | } | 1339 | } |
1195 | 1340 | ||
1196 | mutex_unlock(&nilfs->ns_mount_mutex); | 1341 | if (sd.cno) { |
1197 | put_nilfs(nilfs); | 1342 | err = nilfs_attach_snapshot(s, sd.cno, &root_dentry); |
1198 | if (need_to_close) | 1343 | if (err) |
1199 | close_bdev_exclusive(sd.bdev, mode); | 1344 | goto failed_super; |
1200 | simple_set_mnt(mnt, s); | 1345 | } else { |
1201 | return 0; | 1346 | root_dentry = dget(s->s_root); |
1347 | } | ||
1202 | 1348 | ||
1203 | failed_unlock: | 1349 | if (!s_new) |
1204 | mutex_unlock(&nilfs->ns_mount_mutex); | 1350 | blkdev_put(sd.bdev, mode); |
1205 | put_nilfs(nilfs); | ||
1206 | failed: | ||
1207 | close_bdev_exclusive(sd.bdev, mode); | ||
1208 | 1351 | ||
1209 | return err; | 1352 | return root_dentry; |
1210 | 1353 | ||
1211 | cancel_new: | 1354 | failed_super: |
1212 | /* Abandoning the newly allocated superblock */ | ||
1213 | mutex_unlock(&nilfs->ns_mount_mutex); | ||
1214 | put_nilfs(nilfs); | ||
1215 | deactivate_locked_super(s); | 1355 | deactivate_locked_super(s); |
1216 | /* | 1356 | |
1217 | * deactivate_locked_super() invokes close_bdev_exclusive(). | 1357 | failed: |
1218 | * We must finish all post-cleaning before this call; | 1358 | if (!s_new) |
1219 | * put_nilfs() needs the block device. | 1359 | blkdev_put(sd.bdev, mode); |
1220 | */ | 1360 | return ERR_PTR(err); |
1221 | return err; | ||
1222 | } | 1361 | } |
1223 | 1362 | ||
1224 | struct file_system_type nilfs_fs_type = { | 1363 | struct file_system_type nilfs_fs_type = { |
1225 | .owner = THIS_MODULE, | 1364 | .owner = THIS_MODULE, |
1226 | .name = "nilfs2", | 1365 | .name = "nilfs2", |
1227 | .get_sb = nilfs_get_sb, | 1366 | .mount = nilfs_mount, |
1228 | .kill_sb = kill_block_super, | 1367 | .kill_sb = kill_block_super, |
1229 | .fs_flags = FS_REQUIRES_DEV, | 1368 | .fs_flags = FS_REQUIRES_DEV, |
1230 | }; | 1369 | }; |
@@ -1237,7 +1376,7 @@ static void nilfs_inode_init_once(void *obj) | |||
1237 | #ifdef CONFIG_NILFS_XATTR | 1376 | #ifdef CONFIG_NILFS_XATTR |
1238 | init_rwsem(&ii->xattr_sem); | 1377 | init_rwsem(&ii->xattr_sem); |
1239 | #endif | 1378 | #endif |
1240 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); | 1379 | address_space_init_once(&ii->i_btnode_cache); |
1241 | ii->i_bmap = &ii->i_bmap_data; | 1380 | ii->i_bmap = &ii->i_bmap_data; |
1242 | inode_init_once(&ii->vfs_inode); | 1381 | inode_init_once(&ii->vfs_inode); |
1243 | } | 1382 | } |