#include <linux/parser.h>
#include <linux/random.h>
#include <linux/crc32.h>
-#include <linux/smp_lock.h>
#include <linux/vfs.h>
#include <linux/writeback.h>
#include <linux/kobject.h>
-#include <linux/exportfs.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include "nilfs.h"
+#include "export.h"
#include "mdt.h"
#include "alloc.h"
#include "btree.h"
return NULL;
ii->i_bh = NULL;
ii->i_state = 0;
+ ii->i_cno = 0;
ii->vfs_inode.i_version = 1;
nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi);
return &ii->vfs_inode;
void nilfs_destroy_inode(struct inode *inode)
{
+ struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
+
+ if (mdi) {
+ kfree(mdi->mi_bgl); /* kfree(NULL) is safe */
+ kfree(mdi);
+ }
kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode));
}
{
struct the_nilfs *nilfs = sbi->s_nilfs;
int err;
- int barrier_done = 0;
- if (nilfs_test_opt(sbi, BARRIER)) {
- set_buffer_ordered(nilfs->ns_sbh[0]);
- barrier_done = 1;
- }
retry:
set_buffer_dirty(nilfs->ns_sbh[0]);
- err = sync_dirty_buffer(nilfs->ns_sbh[0]);
- if (err == -EOPNOTSUPP && barrier_done) {
- nilfs_warning(sbi->s_super, __func__,
- "barrier-based sync failed. "
- "disabling barriers\n");
- nilfs_clear_opt(sbi, BARRIER);
- barrier_done = 0;
- clear_buffer_ordered(nilfs->ns_sbh[0]);
- goto retry;
+
+ if (nilfs_test_opt(sbi, BARRIER)) {
+ err = __sync_dirty_buffer(nilfs->ns_sbh[0],
+ WRITE_SYNC | WRITE_BARRIER);
+ if (err == -EOPNOTSUPP) {
+ nilfs_warning(sbi->s_super, __func__,
+ "barrier-based sync failed. "
+ "disabling barriers\n");
+ nilfs_clear_opt(sbi, BARRIER);
+ goto retry;
+ }
+ } else {
+ err = sync_dirty_buffer(nilfs->ns_sbh[0]);
}
+
if (unlikely(err)) {
printk(KERN_ERR
"NILFS: unable to write superblock (err=%d)\n", err);
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
- lock_kernel();
-
nilfs_detach_segment_constructor(sbi);
if (!(sb->s_flags & MS_RDONLY)) {
sbi->s_super = NULL;
sb->s_fs_info = NULL;
nilfs_put_sbinfo(sbi);
-
- unlock_kernel();
}
static int nilfs_sync_fs(struct super_block *sb, int wait)
return err;
}
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
+int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+ struct nilfs_root **rootp)
{
struct the_nilfs *nilfs = sbi->s_nilfs;
+ struct nilfs_root *root;
struct nilfs_checkpoint *raw_cp;
struct buffer_head *bh_cp;
- int err;
+ int err = -ENOMEM;
+
+ root = nilfs_find_or_create_root(
+ nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno);
+ if (!root)
+ return err;
down_write(&nilfs->ns_super_sem);
list_add(&sbi->s_list, &nilfs->ns_supers);
sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size);
if (!sbi->s_ifile)
- return -ENOMEM;
+ goto delist;
down_read(&nilfs->ns_segctor_sem);
err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp,
atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count));
nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp);
+
+ *rootp = root;
return 0;
failed_bh:
nilfs_mdt_destroy(sbi->s_ifile);
sbi->s_ifile = NULL;
+ delist:
down_write(&nilfs->ns_super_sem);
list_del_init(&sbi->s_list);
up_write(&nilfs->ns_super_sem);
+ nilfs_put_root(root);
return err;
}
.show_options = nilfs_show_options
};
-static struct inode *
-nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
-{
- struct inode *inode;
-
- if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO &&
- ino != NILFS_SKETCH_INO)
- return ERR_PTR(-ESTALE);
-
- inode = nilfs_iget(sb, ino);
- if (IS_ERR(inode))
- return ERR_CAST(inode);
- if (generation && inode->i_generation != generation) {
- iput(inode);
- return ERR_PTR(-ESTALE);
- }
-
- return inode;
-}
-
-static struct dentry *
-nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
- int fh_type)
-{
- return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
- nilfs_nfs_get_inode);
-}
-
-static struct dentry *
-nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len,
- int fh_type)
-{
- return generic_fh_to_parent(sb, fid, fh_len, fh_type,
- nilfs_nfs_get_inode);
-}
-
-static const struct export_operations nilfs_export_ops = {
- .fh_to_dentry = nilfs_fh_to_dentry,
- .fh_to_parent = nilfs_fh_to_parent,
- .get_parent = nilfs_get_parent,
-};
-
enum {
Opt_err_cont, Opt_err_panic, Opt_err_ro,
Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery,
struct the_nilfs *nilfs)
{
struct nilfs_sb_info *sbi;
+ struct nilfs_root *fsroot;
struct inode *root;
__u64 cno;
- int err;
+ int err, curr_mnt;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
goto failed_sbi;
cno = nilfs_last_cno(nilfs);
+ curr_mnt = true;
if (sb->s_flags & MS_RDONLY) {
if (nilfs_test_opt(sbi, SNAPSHOT)) {
goto failed_sbi;
}
cno = sbi->s_snapshot_cno;
+ curr_mnt = false;
}
}
- err = nilfs_attach_checkpoint(sbi, cno);
+ err = nilfs_attach_checkpoint(sbi, cno, curr_mnt, &fsroot);
if (err) {
printk(KERN_ERR "NILFS: error loading a checkpoint"
" (checkpoint number=%llu).\n", (unsigned long long)cno);
goto failed_checkpoint;
}
- root = nilfs_iget(sb, NILFS_ROOT_INO);
+ root = nilfs_iget(sb, fsroot, NILFS_ROOT_INO);
if (IS_ERR(root)) {
printk(KERN_ERR "NILFS: get root inode failed\n");
err = PTR_ERR(root);
goto failed_segctor;
}
+ nilfs_put_root(fsroot);
+
if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi);
failed_checkpoint:
nilfs_detach_checkpoint(sbi);
+ nilfs_put_root(fsroot);
failed_sbi:
put_nilfs(nilfs);
struct nilfs_mount_options old_opts;
int was_snapshot, err;
- lock_kernel();
-
down_write(&nilfs->ns_super_sem);
old_sb_flags = sb->s_flags;
old_opts.mount_opt = sbi->s_mount_opt;
}
out:
up_write(&nilfs->ns_super_sem);
- unlock_kernel();
return 0;
restore_opts:
sbi->s_mount_opt = old_opts.mount_opt;
sbi->s_snapshot_cno = old_opts.snapshot_cno;
up_write(&nilfs->ns_super_sem);
- unlock_kernel();
return err;
}
put_nilfs(nilfs);
failed:
close_bdev_exclusive(sd.bdev, mode);
-
return err;
cancel_new: