Commit 5bab188a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2:
  nilfs2: move NILFS_SUPER_MAGIC to linux/magic.h
  nilfs2: get rid of nilfs_sb_info structure
  nilfs2: use sb instance instead of nilfs_sb_info struct
  nilfs2: get rid of sc_sbi back pointer
  nilfs2: move log writer onto nilfs object
  nilfs2: move next generation counter into nilfs object
  nilfs2: move s_inode_lock and s_dirty_files into nilfs object
  nilfs2: move parameters on nilfs_sb_info into nilfs object
  nilfs2: move mount options to nilfs object
  nilfs2: record used amount of each checkpoint in checkpoint list
  nilfs2: optimize rec_len functions
  nilfs2: append blocksize info to warnings during loading super blocks
  nilfs2: add compat ioctl
  nilfs2: implement FS_IOC_GETFLAGS/SETFLAGS/GETVERSION
  nilfs2: tighten restrictions on inode flags
  nilfs2: mark S_NOATIME on inodes only if NOATIME attribute is set
  nilfs2: use common file attribute macros
  nilfs2: add free entries count only if clear bit operation succeeded
  nilfs2: decrement inodes count only if raw inode was successfully deleted
parents a8c91da5 4d3cf1bc
...@@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, ...@@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
group_offset, bitmap)) group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n", printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr); __func__, (unsigned long long)req->pr_entry_nr);
else
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_bitmap_bh->b_page);
kunmap(req->pr_desc_bh->b_page); kunmap(req->pr_desc_bh->b_page);
...@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, ...@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
group_offset, bitmap)) group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n", printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr); __func__, (unsigned long long)req->pr_entry_nr);
else
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_bitmap_bh->b_page);
kunmap(req->pr_desc_bh->b_page); kunmap(req->pr_desc_bh->b_page);
...@@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) ...@@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
for (j = i, n = 0; for (j = i, n = 0;
(j < nitems) && nilfs_palloc_group_is_in(inode, group, (j < nitems) && nilfs_palloc_group_is_in(inode, group,
entry_nrs[j]); entry_nrs[j]);
j++, n++) { j++) {
nilfs_palloc_group(inode, entry_nrs[j], &group_offset); nilfs_palloc_group(inode, entry_nrs[j], &group_offset);
if (!nilfs_clear_bit_atomic( if (!nilfs_clear_bit_atomic(
nilfs_mdt_bgl_lock(inode, group), nilfs_mdt_bgl_lock(inode, group),
...@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) ...@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
"%s: entry number %llu already freed\n", "%s: entry number %llu already freed\n",
__func__, __func__,
(unsigned long long)entry_nrs[j]); (unsigned long long)entry_nrs[j]);
} else {
n++;
} }
} }
nilfs_palloc_group_desc_add_entries(inode, group, desc, n); nilfs_palloc_group_desc_add_entries(inode, group, desc, n);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include "nilfs.h" #include "nilfs.h"
#include "bmap.h" #include "bmap.h"
#include "sb.h"
#include "btree.h" #include "btree.h"
#include "direct.h" #include "direct.h"
#include "btnode.h" #include "btnode.h"
...@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap) ...@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
/* /*
* Internal use only * Internal use only
*/ */
void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
{
inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
}
void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
{
inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
}
__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
const struct buffer_head *bh) const struct buffer_head *bh)
{ {
......
...@@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, ...@@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
/* Assume that bmap semaphore is locked. */ /* Assume that bmap semaphore is locked. */
static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap) static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
......
...@@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr) ...@@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
if (ret < 0) if (ret < 0)
goto out; goto out;
nilfs_btree_commit_insert(btree, path, level, key, ptr); nilfs_btree_commit_insert(btree, path, level, key, ptr);
nilfs_bmap_add_blocks(btree, stats.bs_nblocks); nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
out: out:
nilfs_btree_free_path(path); nilfs_btree_free_path(path);
...@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) ...@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
if (ret < 0) if (ret < 0)
goto out; goto out;
nilfs_btree_commit_delete(btree, path, level, dat); nilfs_btree_commit_delete(btree, path, level, dat);
nilfs_bmap_sub_blocks(btree, stats.bs_nblocks); nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
out: out:
nilfs_btree_free_path(path); nilfs_btree_free_path(path);
...@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree, ...@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
return ret; return ret;
nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n, nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
di, ni, bh); di, ni, bh);
nilfs_bmap_add_blocks(btree, stats.bs_nblocks); nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
return 0; return 0;
} }
......
...@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, ...@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
nilfs_commit_chunk(page, mapping, from, to); nilfs_commit_chunk(page, mapping, from, to);
nilfs_put_page(page); nilfs_put_page(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_mtime = dir->i_ctime = CURRENT_TIME;
/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
} }
/* /*
...@@ -531,7 +530,6 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) ...@@ -531,7 +530,6 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
nilfs_set_de_type(de, inode); nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, page->mapping, from, to); nilfs_commit_chunk(page, page->mapping, from, to);
dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_mtime = dir->i_ctime = CURRENT_TIME;
/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
nilfs_mark_inode_dirty(dir); nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */ /* OFFSET_CACHE */
out_put: out_put:
...@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) ...@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
dir->inode = 0; dir->inode = 0;
nilfs_commit_chunk(page, mapping, from, to); nilfs_commit_chunk(page, mapping, from, to);
inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_ctime = inode->i_mtime = CURRENT_TIME;
/* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */
out: out:
nilfs_put_page(page); nilfs_put_page(page);
return err; return err;
...@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = { ...@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = {
.readdir = nilfs_readdir, .readdir = nilfs_readdir,
.unlocked_ioctl = nilfs_ioctl, .unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = nilfs_ioctl, .compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
.fsync = nilfs_sync_file, .fsync = nilfs_sync_file,
......
...@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) ...@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
if (NILFS_BMAP_USE_VBN(bmap)) if (NILFS_BMAP_USE_VBN(bmap))
nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr); nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
nilfs_bmap_add_blocks(bmap, 1); nilfs_inode_add_blocks(bmap->b_inode, 1);
} }
return ret; return ret;
} }
...@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) ...@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
if (!ret) { if (!ret) {
nilfs_bmap_commit_end_ptr(bmap, &req, dat); nilfs_bmap_commit_end_ptr(bmap, &req, dat);
nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR); nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
nilfs_bmap_sub_blocks(bmap, 1); nilfs_inode_sub_blocks(bmap->b_inode, 1);
} }
return ret; return ret;
} }
......
...@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int ret; int ret;
if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs))) if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
return VM_FAULT_SIGBUS; /* -ENOSPC */ return VM_FAULT_SIGBUS; /* -ENOSPC */
lock_page(page); lock_page(page);
...@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = { ...@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = {
.aio_write = generic_file_aio_write, .aio_write = generic_file_aio_write,
.unlocked_ioctl = nilfs_ioctl, .unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = nilfs_ioctl, .compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
.mmap = nilfs_file_mmap, .mmap = nilfs_file_mmap,
.open = generic_file_open, .open = generic_file_open,
......
...@@ -41,6 +41,24 @@ struct nilfs_iget_args { ...@@ -41,6 +41,24 @@ struct nilfs_iget_args {
int for_gc; int for_gc;
}; };
void nilfs_inode_add_blocks(struct inode *inode, int n)
{
struct nilfs_root *root = NILFS_I(inode)->i_root;
inode_add_bytes(inode, (1 << inode->i_blkbits) * n);
if (root)
atomic_add(n, &root->blocks_count);
}
void nilfs_inode_sub_blocks(struct inode *inode, int n)
{
struct nilfs_root *root = NILFS_I(inode)->i_root;
inode_sub_bytes(inode, (1 << inode->i_blkbits) * n);
if (root)
atomic_sub(n, &root->blocks_count);
}
/** /**
* nilfs_get_block() - get a file block on the filesystem (callback function) * nilfs_get_block() - get a file block on the filesystem (callback function)
* @inode - inode struct of the target file * @inode - inode struct of the target file
...@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = { ...@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = {
struct inode *nilfs_new_inode(struct inode *dir, int mode) struct inode *nilfs_new_inode(struct inode *dir, int mode)
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct inode *inode; struct inode *inode;
struct nilfs_inode_info *ii; struct nilfs_inode_info *ii;
struct nilfs_root *root; struct nilfs_root *root;
...@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) ...@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
/* No lock is needed; iget() ensures it. */ /* No lock is needed; iget() ensures it. */
} }
ii->i_flags = NILFS_I(dir)->i_flags; ii->i_flags = nilfs_mask_flags(
if (S_ISLNK(mode)) mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL);
if (!S_ISDIR(mode))
ii->i_flags &= ~NILFS_DIRSYNC_FL;
/* ii->i_file_acl = 0; */ /* ii->i_file_acl = 0; */
/* ii->i_dir_acl = 0; */ /* ii->i_dir_acl = 0; */
ii->i_dir_start_lookup = 0; ii->i_dir_start_lookup = 0;
nilfs_set_inode_flags(inode); nilfs_set_inode_flags(inode);
spin_lock(&sbi->s_next_gen_lock); spin_lock(&nilfs->ns_next_gen_lock);
inode->i_generation = sbi->s_next_generation++; inode->i_generation = nilfs->ns_next_generation++;
spin_unlock(&sbi->s_next_gen_lock); spin_unlock(&nilfs->ns_next_gen_lock);
insert_inode_hash(inode); insert_inode_hash(inode);
err = nilfs_init_acl(inode, dir); err = nilfs_init_acl(inode, dir);
...@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode) ...@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode)
inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
S_DIRSYNC); S_DIRSYNC);
if (flags & NILFS_SYNC_FL) if (flags & FS_SYNC_FL)
inode->i_flags |= S_SYNC; inode->i_flags |= S_SYNC;
if (flags & NILFS_APPEND_FL) if (flags & FS_APPEND_FL)
inode->i_flags |= S_APPEND; inode->i_flags |= S_APPEND;
if (flags & NILFS_IMMUTABLE_FL) if (flags & FS_IMMUTABLE_FL)
inode->i_flags |= S_IMMUTABLE; inode->i_flags |= S_IMMUTABLE;
#ifndef NILFS_ATIME_DISABLE if (flags & FS_NOATIME_FL)
if (flags & NILFS_NOATIME_FL)
#endif
inode->i_flags |= S_NOATIME; inode->i_flags |= S_NOATIME;
if (flags & NILFS_DIRSYNC_FL) if (flags & FS_DIRSYNC_FL)
inode->i_flags |= S_DIRSYNC; inode->i_flags |= S_DIRSYNC;
mapping_set_gfp_mask(inode->i_mapping, mapping_set_gfp_mask(inode->i_mapping,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
...@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb, ...@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb,
struct nilfs_root *root, unsigned long ino, struct nilfs_root *root, unsigned long ino,
struct inode *inode) struct inode *inode)
{ {
struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct buffer_head *bh; struct buffer_head *bh;
struct nilfs_inode *raw_inode; struct nilfs_inode *raw_inode;
int err; int err;
...@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode) ...@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode)
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct nilfs_inode_info *ii = NILFS_I(inode); struct nilfs_inode_info *ii = NILFS_I(inode);
int ret;
if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
if (inode->i_data.nrpages) if (inode->i_data.nrpages)
...@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode) ...@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode)
nilfs_mark_inode_dirty(inode); nilfs_mark_inode_dirty(inode);
end_writeback(inode); end_writeback(inode);
nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
atomic_dec(&ii->i_root->inodes_count); if (!ret)
atomic_dec(&ii->i_root->inodes_count);
nilfs_clear_inode(inode); nilfs_clear_inode(inode);
...@@ -792,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) ...@@ -792,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_inode_info *ii = NILFS_I(inode); struct nilfs_inode_info *ii = NILFS_I(inode);
int err; int err;
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (ii->i_bh == NULL) { if (ii->i_bh == NULL) {
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
err = nilfs_ifile_get_inode_block(ii->i_root->ifile, err = nilfs_ifile_get_inode_block(ii->i_root->ifile,
inode->i_ino, pbh); inode->i_ino, pbh);
if (unlikely(err)) if (unlikely(err))
return err; return err;
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (ii->i_bh == NULL) if (ii->i_bh == NULL)
ii->i_bh = *pbh; ii->i_bh = *pbh;
else { else {
...@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) ...@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
*pbh = ii->i_bh; *pbh = ii->i_bh;
get_bh(*pbh); get_bh(*pbh);
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
return 0; return 0;
} }
int nilfs_inode_dirty(struct inode *inode) int nilfs_inode_dirty(struct inode *inode)
{ {
struct nilfs_inode_info *ii = NILFS_I(inode); struct nilfs_inode_info *ii = NILFS_I(inode);
struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
int ret = 0; int ret = 0;
if (!list_empty(&ii->i_dirty)) { if (!list_empty(&ii->i_dirty)) {
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
ret = test_bit(NILFS_I_DIRTY, &ii->i_state) || ret = test_bit(NILFS_I_DIRTY, &ii->i_state) ||
test_bit(NILFS_I_BUSY, &ii->i_state); test_bit(NILFS_I_BUSY, &ii->i_state);
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
} }
return ret; return ret;
} }
int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
struct nilfs_inode_info *ii = NILFS_I(inode); struct nilfs_inode_info *ii = NILFS_I(inode);
struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks); atomic_add(nr_dirty, &nilfs->ns_ndirtyblks);
if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state)) if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state))
return 0; return 0;
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
!test_bit(NILFS_I_BUSY, &ii->i_state)) { !test_bit(NILFS_I_BUSY, &ii->i_state)) {
/* Because this routine may race with nilfs_dispose_list(), /* Because this routine may race with nilfs_dispose_list(),
...@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) ...@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) { if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) {
/* This will happen when somebody is freeing /* This will happen when somebody is freeing
this inode. */ this inode. */
nilfs_warning(sbi->s_super, __func__, nilfs_warning(inode->i_sb, __func__,
"cannot get inode (ino=%lu)\n", "cannot get inode (ino=%lu)\n",
inode->i_ino); inode->i_ino);
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
return -EINVAL; /* NILFS_I_DIRTY may remain for return -EINVAL; /* NILFS_I_DIRTY may remain for
freeing inode */ freeing inode */
} }
list_del(&ii->i_dirty); list_del(&ii->i_dirty);
list_add_tail(&ii->i_dirty, &sbi->s_dirty_files); list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files);
set_bit(NILFS_I_QUEUED, &ii->i_state); set_bit(NILFS_I_QUEUED, &ii->i_state);
} }
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
return 0; return 0;
} }
......
...@@ -26,7 +26,9 @@ ...@@ -26,7 +26,9 @@
#include <linux/capability.h> /* capable() */ #include <linux/capability.h> /* capable() */
#include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */ #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/compat.h> /* compat_ptr() */
#include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */ #include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */
#include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "nilfs.h" #include "nilfs.h"
#include "segment.h" #include "segment.h"
...@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, ...@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
return ret; return ret;
} }
static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
{
unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
return put_user(flags, (int __user *)argp);
}
static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
void __user *argp)
{
struct nilfs_transaction_info ti;
unsigned int flags, oldflags;
int ret;
if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *)argp))
return -EFAULT;
ret = mnt_want_write(filp->f_path.mnt);
if (ret)
return ret;
flags = nilfs_mask_flags(inode->i_mode, flags);
mutex_lock(&inode->i_mutex);
oldflags = NILFS_I(inode)->i_flags;
/*
* The IMMUTABLE and APPEND_ONLY flags can only be changed by the
* relevant capability.
*/
ret = -EPERM;
if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
!capable(CAP_LINUX_IMMUTABLE))
goto out;
ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
if (ret)
goto out;
NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
(flags & FS_FL_USER_MODIFIABLE);
nilfs_set_inode_flags(inode);
inode->i_ctime = CURRENT_TIME;
if (IS_SYNC(inode))
nilfs_set_transaction_flag(NILFS_TI_SYNC);
nilfs_mark_inode_dirty(inode);
ret = nilfs_transaction_commit(inode->i_sb);
out:
mutex_unlock(&inode->i_mutex);
mnt_drop_write(filp->f_path.mnt);
return ret;
}
static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
{
return put_user(inode->i_generation, (int __user *)argp);
}
static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp) unsigned int cmd, void __user *argp)
{ {
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct inode *cpfile = nilfs->ns_cpfile;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
struct nilfs_cpmode cpmode; struct nilfs_cpmode cpmode;
int ret; int ret;
...@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, ...@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
nilfs_transaction_begin(inode->i_sb, &ti, 0); nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_change_cpmode( ret = nilfs_cpfile_change_cpmode(
cpfile, cpmode.cm_cno, cpmode.cm_mode); nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
nilfs_transaction_abort(inode->i_sb); nilfs_transaction_abort(inode->i_sb);
else else
...@@ -137,7 +202,7 @@ static int ...@@ -137,7 +202,7 @@ static int
nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp) unsigned int cmd, void __user *argp)
{ {
struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
__u64 cno; __u64 cno;
int ret; int ret;
...@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, ...@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
goto out; goto out;
nilfs_transaction_begin(inode->i_sb, &ti, 0); nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
nilfs_transaction_abort(inode->i_sb); nilfs_transaction_abort(inode->i_sb);
else else
...@@ -180,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, ...@@ -180,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp) unsigned int cmd, void __user *argp)
{ {
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_cpstat cpstat; struct nilfs_cpstat cpstat;
int ret; int ret;
...@@ -211,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, ...@@ -211,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp) unsigned int cmd, void __user *argp)
{ {
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_sustat sustat; struct nilfs_sustat sustat;
int ret; int ret;
...@@ -267,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, ...@@ -267,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp) unsigned int cmd, void __user *argp)
{ {
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_argv argv; struct nilfs_argv argv;
int ret; int ret;
...@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, ...@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
struct nilfs_argv *argv, void *buf) struct nilfs_argv *argv, void *buf)
{ {
size_t nmembs = argv->v_nmembs; size_t nmembs = argv->v_nmembs;
struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct inode *inode; struct inode *inode;
struct nilfs_vdesc *vdesc; struct nilfs_vdesc *vdesc;
struct buffer_head *bh, *n; struct buffer_head *bh, *n;
...@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ...@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
ret = PTR_ERR(kbufs[4]); ret = PTR_ERR(kbufs[4]);
goto out; goto out;
} }
nilfs = NILFS_SB(inode->i_sb)->s_nilfs; nilfs = inode->i_sb->s_fs_info;
for (n = 0; n < 4; n++) { for (n = 0; n < 4; n++) {
ret = -EINVAL; ret = -EINVAL;
...@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, ...@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
return ret; return ret;
if (argp != NULL) { if (argp != NULL) {
nilfs = NILFS_SB(inode->i_sb)->s_nilfs; nilfs = inode->i_sb->s_fs_info;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
cno = nilfs->ns_cno - 1; cno = nilfs->ns_cno - 1;
up_read(&nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
...@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, ...@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
void *, size_t, size_t)) void *, size_t, size_t))
{ {
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_argv argv; struct nilfs_argv argv;
int ret; int ret;
...@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
switch (cmd) { switch (cmd) {
case FS_IOC_GETFLAGS:
return nilfs_ioctl_getflags(inode, argp);
case FS_IOC_SETFLAGS:
return nilfs_ioctl_setflags(inode, filp, argp);
case FS_IOC_GETVERSION:
return nilfs_ioctl_getversion(inode, argp);
case NILFS_IOCTL_CHANGE_CPMODE: case NILFS_IOCTL_CHANGE_CPMODE:
return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
case NILFS_IOCTL_DELETE_CHECKPOINT: case NILFS_IOCTL_DELETE_CHECKPOINT:
...@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -ENOTTY; return -ENOTTY;
} }
} }
#ifdef CONFIG_COMPAT
long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case FS_IOC32_GETFLAGS:
cmd = FS_IOC_GETFLAGS;
break;
case FS_IOC32_SETFLAGS:
cmd = FS_IOC_SETFLAGS;
break;
case FS_IOC32_GETVERSION:
cmd = FS_IOC_GETVERSION;
break;
default:
return -ENOIOCTLCMD;
}
return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
}
#endif
...@@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode) ...@@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode)
static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode) static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode)
{ {
return NILFS_SB(inode->i_sb)->s_nilfs; return inode->i_sb->s_fs_info;
} }
/* Default GFP flags using highmem */ /* Default GFP flags using highmem */
......
...@@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno, ...@@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO) if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); root = nilfs_lookup_root(sb->s_fs_info, cno);
if (!root) if (!root)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "the_nilfs.h" #include "the_nilfs.h"
#include "sb.h"
#include "bmap.h" #include "bmap.h"
/* /*
...@@ -122,7 +121,7 @@ enum { ...@@ -122,7 +121,7 @@ enum {
#define NILFS_SYS_INO_BITS \ #define NILFS_SYS_INO_BITS \
((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS) ((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS)
#define NILFS_FIRST_INO(sb) (NILFS_SB(sb)->s_nilfs->ns_first_ino) #define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
#define NILFS_MDT_INODE(sb, ino) \ #define NILFS_MDT_INODE(sb, ino) \
((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino)))) ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino))))
...@@ -212,6 +211,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir) ...@@ -212,6 +211,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
#define NILFS_ATIME_DISABLE #define NILFS_ATIME_DISABLE
/* Flags that should be inherited by new inodes from their parent. */
#define NILFS_FL_INHERITED \
(FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL | \
FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\
FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL)
/* Mask out flags that are inappropriate for the given type of inode. */
static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags)
{
if (S_ISDIR(mode))
return flags;
else if (S_ISREG(mode))
return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL);
else
return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
}
/* dir.c */ /* dir.c */
extern int nilfs_add_link(struct dentry *, struct inode *); extern int nilfs_add_link(struct dentry *, struct inode *);
extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *); extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
...@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int); ...@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int);
/* ioctl.c */ /* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long); long nilfs_ioctl(struct file *, unsigned int, unsigned long);
long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *, int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
void **); void **);
/* inode.c */ /* inode.c */
void nilfs_inode_add_blocks(struct inode *inode, int n);
void nilfs_inode_sub_blocks(struct inode *inode, int n);
extern struct inode *nilfs_new_inode(struct inode *, int); extern struct inode *nilfs_new_inode(struct inode *, int);
extern void nilfs_free_inode(struct inode *); extern void nilfs_free_inode(struct inode *);
extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
...@@ -275,11 +294,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *, ...@@ -275,11 +294,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *,
struct nilfs_super_block *); struct nilfs_super_block *);
extern void nilfs_set_log_cursor(struct nilfs_super_block *, extern void nilfs_set_log_cursor(struct nilfs_super_block *,
struct the_nilfs *); struct the_nilfs *);
extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
int flip); int flip);
extern int nilfs_commit_super(struct nilfs_sb_info *, int); int nilfs_commit_super(struct super_block *sb, int flag);
extern int nilfs_cleanup_super(struct nilfs_sb_info *); int nilfs_cleanup_super(struct super_block *sb);
int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
struct nilfs_root **root); struct nilfs_root **root);
int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno); int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
......
...@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head) ...@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
} }
static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, struct super_block *sb,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
struct list_head *head = &ri->ri_used_segments; struct list_head *head = &ri->ri_used_segments;
...@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, ...@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
} }
static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, struct super_block *sb,
struct nilfs_root *root, struct nilfs_root *root,
struct list_head *head, struct list_head *head,
unsigned long *nr_salvaged_blocks) unsigned long *nr_salvaged_blocks)
...@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, ...@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
int err = 0, err2 = 0; int err = 0, err2 = 0;
list_for_each_entry_safe(rb, n, head, list) { list_for_each_entry_safe(rb, n, head, list) {
inode = nilfs_iget(sbi->s_super, root, rb->ino); inode = nilfs_iget(sb, root, rb->ino);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
inode = NULL; inode = NULL;
...@@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, ...@@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
* nilfs_do_roll_forward - salvage logical segments newer than the latest * nilfs_do_roll_forward - salvage logical segments newer than the latest
* checkpoint * checkpoint
* @nilfs: nilfs object * @nilfs: nilfs object
* @sbi: nilfs_sb_info * @sb: super block instance
* @ri: pointer to a nilfs_recovery_info * @ri: pointer to a nilfs_recovery_info
*/ */
static int nilfs_do_roll_forward(struct the_nilfs *nilfs, static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, struct super_block *sb,
struct nilfs_root *root, struct nilfs_root *root,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
...@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
goto failed; goto failed;
if (flags & NILFS_SS_LOGEND) { if (flags & NILFS_SS_LOGEND) {
err = nilfs_recover_dsync_blocks( err = nilfs_recover_dsync_blocks(
nilfs, sbi, root, &dsync_blocks, nilfs, sb, root, &dsync_blocks,
&nsalvaged_blocks); &nsalvaged_blocks);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
...@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
if (nsalvaged_blocks) { if (nsalvaged_blocks) {
printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n", printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
sbi->s_super->s_id, nsalvaged_blocks); sb->s_id, nsalvaged_blocks);
ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
} }
out: out:
...@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
printk(KERN_ERR printk(KERN_ERR
"NILFS (device %s): Error roll-forwarding " "NILFS (device %s): Error roll-forwarding "
"(err=%d, pseg block=%llu). ", "(err=%d, pseg block=%llu). ",
sbi->s_super->s_id, err, (unsigned long long)pseg_start); sb->s_id, err, (unsigned long long)pseg_start);
goto out; goto out;
} }
...@@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, ...@@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
/** /**
* nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
* @nilfs: nilfs object * @nilfs: nilfs object
* @sbi: nilfs_sb_info * @sb: super block instance
* @ri: pointer to a nilfs_recovery_info struct to store search results. * @ri: pointer to a nilfs_recovery_info struct to store search results.
* *
* Return Value: On success, 0 is returned. On error, one of the following * Return Value: On success, 0 is returned. On error, one of the following
...@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, ...@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
* %-ENOMEM - Insufficient memory available. * %-ENOMEM - Insufficient memory available.
*/ */
int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, struct super_block *sb,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
struct nilfs_root *root; struct nilfs_root *root;
...@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, ...@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
return 0; return 0;
err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root); err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
if (unlikely(err)) { if (unlikely(err)) {
printk(KERN_ERR printk(KERN_ERR
"NILFS: error loading the latest checkpoint.\n"); "NILFS: error loading the latest checkpoint.\n");
return err; return err;
} }
err = nilfs_do_roll_forward(nilfs, sbi, root, ri); err = nilfs_do_roll_forward(nilfs, sb, root, ri);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri); err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
if (unlikely(err)) { if (unlikely(err)) {
printk(KERN_ERR "NILFS: Error preparing segments for " printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n"); "recovery.\n");
goto failed; goto failed;
} }
err = nilfs_attach_segment_constructor(sbi, root); err = nilfs_attach_log_writer(sb, root);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
set_nilfs_discontinued(nilfs); set_nilfs_discontinued(nilfs);
err = nilfs_construct_segment(sbi->s_super); err = nilfs_construct_segment(sb);
nilfs_detach_segment_constructor(sbi); nilfs_detach_log_writer(sb);
if (unlikely(err)) { if (unlikely(err)) {
printk(KERN_ERR "NILFS: Oops! recovery failed. " printk(KERN_ERR "NILFS: Oops! recovery failed. "
......
/*
* sb.h - NILFS on-memory super block structure.
*
* Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Written by Ryusuke Konishi <ryusuke@osrg.net>
*
*/
#ifndef _NILFS_SB
#define _NILFS_SB
#include <linux/types.h>
#include <linux/fs.h>
struct the_nilfs;
struct nilfs_sc_info;
/*
* NILFS super-block data in memory
*/
struct nilfs_sb_info {
/* Mount options */
unsigned long s_mount_opt;
uid_t s_resuid;
gid_t s_resgid;
unsigned long s_interval; /* construction interval */
unsigned long s_watermark; /* threshold of data amount
for the segment construction */
/* Fundamental members */
struct super_block *s_super; /* reverse pointer to super_block */
struct the_nilfs *s_nilfs;
/* Segment constructor */
struct list_head s_dirty_files; /* dirty files list */
struct nilfs_sc_info *s_sc_info; /* segment constructor info */
spinlock_t s_inode_lock; /* Lock for the nilfs inode.
It covers s_dirty_files list */
/* Inode allocator */
spinlock_t s_next_gen_lock;
u32 s_next_generation;
};
static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb)
{
return sb->s_fs_info;
}
static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi)
{
return sbi->s_sc_info;
}
/*
* Bit operations for the mount option
*/
#define nilfs_clear_opt(sbi, opt) \
do { (sbi)->s_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
#define nilfs_set_opt(sbi, opt) \
do { (sbi)->s_mount_opt |= NILFS_MOUNT_##opt; } while (0)
#define nilfs_test_opt(sbi, opt) ((sbi)->s_mount_opt & NILFS_MOUNT_##opt)
#define nilfs_write_opt(sbi, mask, opt) \
do { (sbi)->s_mount_opt = \
(((sbi)->s_mount_opt & ~NILFS_MOUNT_##mask) | \
NILFS_MOUNT_##opt); \
} while (0)
#endif /* _NILFS_SB */
...@@ -104,8 +104,7 @@ struct nilfs_sc_operations { ...@@ -104,8 +104,7 @@ struct nilfs_sc_operations {
static void nilfs_segctor_start_timer(struct nilfs_sc_info *); static void nilfs_segctor_start_timer(struct nilfs_sc_info *);
static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int); static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);
static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *); static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *);
static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
int);
#define nilfs_cnt32_gt(a, b) \ #define nilfs_cnt32_gt(a, b) \
(typecheck(__u32, a) && typecheck(__u32, b) && \ (typecheck(__u32, a) && typecheck(__u32, b) && \
...@@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb, ...@@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb,
struct nilfs_transaction_info *ti, struct nilfs_transaction_info *ti,
int vacancy_check) int vacancy_check)
{ {
struct nilfs_sb_info *sbi;
struct the_nilfs *nilfs; struct the_nilfs *nilfs;
int ret = nilfs_prepare_segment_lock(ti); int ret = nilfs_prepare_segment_lock(ti);
...@@ -193,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb, ...@@ -193,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb,
vfs_check_frozen(sb, SB_FREEZE_WRITE); vfs_check_frozen(sb, SB_FREEZE_WRITE);
sbi = NILFS_SB(sb); nilfs = sb->s_fs_info;
nilfs = sbi->s_nilfs;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
if (vacancy_check && nilfs_near_disk_full(nilfs)) { if (vacancy_check && nilfs_near_disk_full(nilfs)) {
up_read(&nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
...@@ -225,8 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb, ...@@ -225,8 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb,
int nilfs_transaction_commit(struct super_block *sb) int nilfs_transaction_commit(struct super_block *sb)
{ {
struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_transaction_info *ti = current->journal_info;
struct nilfs_sb_info *sbi; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci;
int err = 0; int err = 0;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
...@@ -235,16 +231,15 @@ int nilfs_transaction_commit(struct super_block *sb) ...@@ -235,16 +231,15 @@ int nilfs_transaction_commit(struct super_block *sb)
ti->ti_count--; ti->ti_count--;
return 0; return 0;
} }
sbi = NILFS_SB(sb); if (nilfs->ns_writer) {
sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
if (sci != NULL) {
if (ti->ti_flags & NILFS_TI_COMMIT) if (ti->ti_flags & NILFS_TI_COMMIT)
nilfs_segctor_start_timer(sci); nilfs_segctor_start_timer(sci);
if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) > if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)
sci->sc_watermark)
nilfs_segctor_do_flush(sci, 0); nilfs_segctor_do_flush(sci, 0);
} }
up_read(&sbi->s_nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
current->journal_info = ti->ti_save; current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_SYNC) if (ti->ti_flags & NILFS_TI_SYNC)
...@@ -257,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb) ...@@ -257,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb)
void nilfs_transaction_abort(struct super_block *sb) void nilfs_transaction_abort(struct super_block *sb)
{ {
struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_transaction_info *ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
if (ti->ti_count > 0) { if (ti->ti_count > 0) {
ti->ti_count--; ti->ti_count--;
return; return;
} }
up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
current->journal_info = ti->ti_save; current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
...@@ -272,9 +268,8 @@ void nilfs_transaction_abort(struct super_block *sb) ...@@ -272,9 +268,8 @@ void nilfs_transaction_abort(struct super_block *sb)
void nilfs_relax_pressure_in_lock(struct super_block *sb) void nilfs_relax_pressure_in_lock(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
struct the_nilfs *nilfs = sbi->s_nilfs;
if (!sci || !sci->sc_flush_request) if (!sci || !sci->sc_flush_request)
return; return;
...@@ -294,11 +289,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb) ...@@ -294,11 +289,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)
downgrade_write(&nilfs->ns_segctor_sem); downgrade_write(&nilfs->ns_segctor_sem);
} }
static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, static void nilfs_transaction_lock(struct super_block *sb,
struct nilfs_transaction_info *ti, struct nilfs_transaction_info *ti,
int gcflag) int gcflag)
{ {
struct nilfs_transaction_info *cur_ti = current->journal_info; struct nilfs_transaction_info *cur_ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
WARN_ON(cur_ti); WARN_ON(cur_ti);
ti->ti_flags = NILFS_TI_WRITER; ti->ti_flags = NILFS_TI_WRITER;
...@@ -309,30 +306,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, ...@@ -309,30 +306,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
current->journal_info = ti; current->journal_info = ti;
for (;;) { for (;;) {
down_write(&sbi->s_nilfs->ns_segctor_sem); down_write(&nilfs->ns_segctor_sem);
if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags)) if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))
break; break;
nilfs_segctor_do_immediate_flush(NILFS_SC(sbi)); nilfs_segctor_do_immediate_flush(sci);
up_write(&sbi->s_nilfs->ns_segctor_sem); up_write(&nilfs->ns_segctor_sem);
yield(); yield();
} }
if (gcflag) if (gcflag)
ti->ti_flags |= NILFS_TI_GC; ti->ti_flags |= NILFS_TI_GC;
} }
static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) static void nilfs_transaction_unlock(struct super_block *sb)
{ {
struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_transaction_info *ti = current->journal_info;
struct the_nilfs *nilfs = sb->s_fs_info;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
BUG_ON(ti->ti_count > 0); BUG_ON(ti->ti_count > 0);
up_write(&sbi->s_nilfs->ns_segctor_sem); up_write(&nilfs->ns_segctor_sem);
current->journal_info = ti->ti_save; current->journal_info = ti->ti_save;
if (!list_empty(&ti->ti_garbage)) if (!list_empty(&ti->ti_garbage))
nilfs_dispose_list(sbi, &ti->ti_garbage, 0); nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
} }
static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
...@@ -714,7 +712,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode, ...@@ -714,7 +712,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,
} }
} }
static void nilfs_dispose_list(struct nilfs_sb_info *sbi, static void nilfs_dispose_list(struct the_nilfs *nilfs,
struct list_head *head, int force) struct list_head *head, int force)
{ {
struct nilfs_inode_info *ii, *n; struct nilfs_inode_info *ii, *n;
...@@ -722,7 +720,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, ...@@ -722,7 +720,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
unsigned nv = 0; unsigned nv = 0;
while (!list_empty(head)) { while (!list_empty(head)) {
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
list_for_each_entry_safe(ii, n, head, i_dirty) { list_for_each_entry_safe(ii, n, head, i_dirty) {
list_del_init(&ii->i_dirty); list_del_init(&ii->i_dirty);
if (force) { if (force) {
...@@ -733,14 +731,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, ...@@ -733,14 +731,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
} else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) { } else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) {
set_bit(NILFS_I_QUEUED, &ii->i_state); set_bit(NILFS_I_QUEUED, &ii->i_state);
list_add_tail(&ii->i_dirty, list_add_tail(&ii->i_dirty,
&sbi->s_dirty_files); &nilfs->ns_dirty_files);
continue; continue;
} }
ivec[nv++] = ii; ivec[nv++] = ii;
if (nv == SC_N_INODEVEC) if (nv == SC_N_INODEVEC)
break; break;
} }
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
for (pii = ivec; nv > 0; pii++, nv--) for (pii = ivec; nv > 0; pii++, nv--)
iput(&(*pii)->vfs_inode); iput(&(*pii)->vfs_inode);
...@@ -773,24 +771,23 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) ...@@ -773,24 +771,23 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int ret = 0; int ret = 0;
if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root)) if (nilfs_test_metadata_dirty(nilfs, sci->sc_root))
set_bit(NILFS_SC_DIRTY, &sci->sc_flags); set_bit(NILFS_SC_DIRTY, &sci->sc_flags);
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci)) if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci))
ret++; ret++;
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
return ret; return ret;
} }
static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
nilfs_mdt_clear_dirty(sci->sc_root->ifile); nilfs_mdt_clear_dirty(sci->sc_root->ifile);
nilfs_mdt_clear_dirty(nilfs->ns_cpfile); nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
...@@ -800,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) ...@@ -800,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
{ {
struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct buffer_head *bh_cp; struct buffer_head *bh_cp;
struct nilfs_checkpoint *raw_cp; struct nilfs_checkpoint *raw_cp;
int err; int err;
...@@ -824,8 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) ...@@ -824,8 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct buffer_head *bh_cp; struct buffer_head *bh_cp;
struct nilfs_checkpoint *raw_cp; struct nilfs_checkpoint *raw_cp;
int err; int err;
...@@ -1049,8 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci, ...@@ -1049,8 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci,
static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct list_head *head; struct list_head *head;
struct nilfs_inode_info *ii; struct nilfs_inode_info *ii;
size_t ndone; size_t ndone;
...@@ -1859,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) ...@@ -1859,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
{ {
struct nilfs_segment_buffer *segbuf; struct nilfs_segment_buffer *segbuf;
struct page *bd_page = NULL, *fs_page = NULL; struct page *bd_page = NULL, *fs_page = NULL;
struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int update_sr = false; int update_sr = false;
list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) {
...@@ -1963,30 +1958,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci) ...@@ -1963,30 +1958,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci)
return ret; return ret;
} }
static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
struct nilfs_sb_info *sbi) struct the_nilfs *nilfs)
{ {
struct nilfs_inode_info *ii, *n; struct nilfs_inode_info *ii, *n;
struct inode *ifile = sci->sc_root->ifile; struct inode *ifile = sci->sc_root->ifile;
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
retry: retry:
list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) { list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) {
if (!ii->i_bh) { if (!ii->i_bh) {
struct buffer_head *ibh; struct buffer_head *ibh;
int err; int err;
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
err = nilfs_ifile_get_inode_block( err = nilfs_ifile_get_inode_block(
ifile, ii->vfs_inode.i_ino, &ibh); ifile, ii->vfs_inode.i_ino, &ibh);
if (unlikely(err)) { if (unlikely(err)) {
nilfs_warning(sbi->s_super, __func__, nilfs_warning(sci->sc_super, __func__,
"failed to get inode block.\n"); "failed to get inode block.\n");
return err; return err;
} }
nilfs_mdt_mark_buffer_dirty(ibh); nilfs_mdt_mark_buffer_dirty(ibh);
nilfs_mdt_mark_dirty(ifile); nilfs_mdt_mark_dirty(ifile);
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (likely(!ii->i_bh)) if (likely(!ii->i_bh))
ii->i_bh = ibh; ii->i_bh = ibh;
else else
...@@ -1999,18 +1994,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, ...@@ -1999,18 +1994,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
list_del(&ii->i_dirty); list_del(&ii->i_dirty);
list_add_tail(&ii->i_dirty, &sci->sc_dirty_files); list_add_tail(&ii->i_dirty, &sci->sc_dirty_files);
} }
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
return 0; return 0;
} }
static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
struct nilfs_sb_info *sbi) struct the_nilfs *nilfs)
{ {
struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_transaction_info *ti = current->journal_info;
struct nilfs_inode_info *ii, *n; struct nilfs_inode_info *ii, *n;
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) ||
test_bit(NILFS_I_DIRTY, &ii->i_state)) test_bit(NILFS_I_DIRTY, &ii->i_state))
...@@ -2022,7 +2017,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, ...@@ -2022,7 +2017,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
list_del(&ii->i_dirty); list_del(&ii->i_dirty);
list_add_tail(&ii->i_dirty, &ti->ti_garbage); list_add_tail(&ii->i_dirty, &ti->ti_garbage);
} }
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
} }
/* /*
...@@ -2030,15 +2025,14 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, ...@@ -2030,15 +2025,14 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
*/ */
static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct page *failed_page; struct page *failed_page;
int err; int err;
sci->sc_stage.scnt = NILFS_ST_INIT; sci->sc_stage.scnt = NILFS_ST_INIT;
sci->sc_cno = nilfs->ns_cno; sci->sc_cno = nilfs->ns_cno;
err = nilfs_segctor_check_in_files(sci, sbi); err = nilfs_segctor_collect_dirty_files(sci, nilfs);
if (unlikely(err)) if (unlikely(err))
goto out; goto out;
...@@ -2116,7 +2110,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) ...@@ -2116,7 +2110,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
} while (sci->sc_stage.scnt != NILFS_ST_DONE); } while (sci->sc_stage.scnt != NILFS_ST_DONE);
out: out:
nilfs_segctor_check_out_files(sci, sbi); nilfs_segctor_drop_written_files(sci, nilfs);
return err; return err;
failed_to_write: failed_to_write:
...@@ -2169,8 +2163,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn) ...@@ -2169,8 +2163,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn)
*/ */
void nilfs_flush_segment(struct super_block *sb, ino_t ino) void nilfs_flush_segment(struct super_block *sb, ino_t ino)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
if (!sci || nilfs_doing_construction()) if (!sci || nilfs_doing_construction())
return; return;
...@@ -2259,8 +2253,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) ...@@ -2259,8 +2253,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
*/ */
int nilfs_construct_segment(struct super_block *sb) int nilfs_construct_segment(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_transaction_info *ti; struct nilfs_transaction_info *ti;
int err; int err;
...@@ -2297,8 +2291,8 @@ int nilfs_construct_segment(struct super_block *sb) ...@@ -2297,8 +2291,8 @@ int nilfs_construct_segment(struct super_block *sb)
int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
loff_t start, loff_t end) loff_t start, loff_t end)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_inode_info *ii; struct nilfs_inode_info *ii;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err = 0; int err = 0;
...@@ -2306,33 +2300,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, ...@@ -2306,33 +2300,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
if (!sci) if (!sci)
return -EROFS; return -EROFS;
nilfs_transaction_lock(sbi, &ti, 0); nilfs_transaction_lock(sb, &ti, 0);
ii = NILFS_I(inode); ii = NILFS_I(inode);
if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) ||
nilfs_test_opt(sbi, STRICT_ORDER) || nilfs_test_opt(nilfs, STRICT_ORDER) ||
test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) ||
nilfs_discontinued(sbi->s_nilfs)) { nilfs_discontinued(nilfs)) {
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sb);
err = nilfs_segctor_sync(sci); err = nilfs_segctor_sync(sci);
return err; return err;
} }
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
!test_bit(NILFS_I_BUSY, &ii->i_state)) { !test_bit(NILFS_I_BUSY, &ii->i_state)) {
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sb);
return 0; return 0;
} }
spin_unlock(&sbi->s_inode_lock); spin_unlock(&nilfs->ns_inode_lock);
sci->sc_dsync_inode = ii; sci->sc_dsync_inode = ii;
sci->sc_dsync_start = start; sci->sc_dsync_start = start;
sci->sc_dsync_end = end; sci->sc_dsync_end = end;
err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sb);
return err; return err;
} }
...@@ -2388,8 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) ...@@ -2388,8 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
*/ */
static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
int err = 0; int err = 0;
...@@ -2407,11 +2400,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) ...@@ -2407,11 +2400,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
nilfs_discontinued(nilfs)) { nilfs_discontinued(nilfs)) {
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
err = -EIO; err = -EIO;
sbp = nilfs_prepare_super(sbi, sbp = nilfs_prepare_super(sci->sc_super,
nilfs_sb_will_flip(nilfs)); nilfs_sb_will_flip(nilfs));
if (likely(sbp)) { if (likely(sbp)) {
nilfs_set_log_cursor(sbp[0], nilfs); nilfs_set_log_cursor(sbp[0], nilfs);
err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); err = nilfs_commit_super(sci->sc_super,
NILFS_SB_COMMIT);
} }
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
...@@ -2443,16 +2437,15 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) ...@@ -2443,16 +2437,15 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
void **kbufs) void **kbufs)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = nilfs->ns_writer;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err; int err;
if (unlikely(!sci)) if (unlikely(!sci))
return -EROFS; return -EROFS;
nilfs_transaction_lock(sbi, &ti, 1); nilfs_transaction_lock(sb, &ti, 1);
err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
if (unlikely(err)) if (unlikely(err))
...@@ -2480,14 +2473,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, ...@@ -2480,14 +2473,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(sci->sc_interval); schedule_timeout(sci->sc_interval);
} }
if (nilfs_test_opt(sbi, DISCARD)) { if (nilfs_test_opt(nilfs, DISCARD)) {
int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs, int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,
sci->sc_nfreesegs); sci->sc_nfreesegs);
if (ret) { if (ret) {
printk(KERN_WARNING printk(KERN_WARNING
"NILFS warning: error %d on discard request, " "NILFS warning: error %d on discard request, "
"turning discards off for the device\n", ret); "turning discards off for the device\n", ret);
nilfs_clear_opt(sbi, DISCARD); nilfs_clear_opt(nilfs, DISCARD);
} }
} }
...@@ -2495,16 +2488,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, ...@@ -2495,16 +2488,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
sci->sc_freesegs = NULL; sci->sc_freesegs = NULL;
sci->sc_nfreesegs = 0; sci->sc_nfreesegs = 0;
nilfs_mdt_clear_shadow_map(nilfs->ns_dat); nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sb);
return err; return err;
} }
static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
nilfs_transaction_lock(sbi, &ti, 0); nilfs_transaction_lock(sci->sc_super, &ti, 0);
nilfs_segctor_construct(sci, mode); nilfs_segctor_construct(sci, mode);
/* /*
...@@ -2515,7 +2507,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) ...@@ -2515,7 +2507,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags)) if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags))
nilfs_segctor_start_timer(sci); nilfs_segctor_start_timer(sci);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sci->sc_super);
} }
static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci) static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci)
...@@ -2561,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci) ...@@ -2561,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)
static int nilfs_segctor_thread(void *arg) static int nilfs_segctor_thread(void *arg)
{ {
struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg;
struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int timeout = 0; int timeout = 0;
sci->sc_timer.data = (unsigned long)current; sci->sc_timer.data = (unsigned long)current;
...@@ -2672,17 +2664,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) ...@@ -2672,17 +2664,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)
/* /*
* Setup & clean-up functions * Setup & clean-up functions
*/ */
static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
struct nilfs_root *root) struct nilfs_root *root)
{ {
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci; struct nilfs_sc_info *sci;
sci = kzalloc(sizeof(*sci), GFP_KERNEL); sci = kzalloc(sizeof(*sci), GFP_KERNEL);
if (!sci) if (!sci)
return NULL; return NULL;
sci->sc_sbi = sbi; sci->sc_super = sb;
sci->sc_super = sbi->s_super;
nilfs_get_root(root); nilfs_get_root(root);
sci->sc_root = root; sci->sc_root = root;
...@@ -2702,10 +2694,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, ...@@ -2702,10 +2694,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,
sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;
sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK;
if (sbi->s_interval) if (nilfs->ns_interval)
sci->sc_interval = sbi->s_interval; sci->sc_interval = nilfs->ns_interval;
if (sbi->s_watermark) if (nilfs->ns_watermark)
sci->sc_watermark = sbi->s_watermark; sci->sc_watermark = nilfs->ns_watermark;
return sci; return sci;
} }
...@@ -2716,12 +2708,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) ...@@ -2716,12 +2708,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
/* The segctord thread was stopped and its timer was removed. /* The segctord thread was stopped and its timer was removed.
But some tasks remain. */ But some tasks remain. */
do { do {
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
nilfs_transaction_lock(sbi, &ti, 0); nilfs_transaction_lock(sci->sc_super, &ti, 0);
ret = nilfs_segctor_construct(sci, SC_LSEG_SR); ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sci->sc_super);
} while (ret && retrycount-- > 0); } while (ret && retrycount-- > 0);
} }
...@@ -2736,10 +2727,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) ...@@ -2736,10 +2727,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
*/ */
static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
{ {
struct nilfs_sb_info *sbi = sci->sc_sbi; struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int flag; int flag;
up_write(&sbi->s_nilfs->ns_segctor_sem); up_write(&nilfs->ns_segctor_sem);
spin_lock(&sci->sc_state_lock); spin_lock(&sci->sc_state_lock);
nilfs_segctor_kill_thread(sci); nilfs_segctor_kill_thread(sci);
...@@ -2753,9 +2744,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) ...@@ -2753,9 +2744,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
WARN_ON(!list_empty(&sci->sc_copied_buffers)); WARN_ON(!list_empty(&sci->sc_copied_buffers));
if (!list_empty(&sci->sc_dirty_files)) { if (!list_empty(&sci->sc_dirty_files)) {
nilfs_warning(sbi->s_super, __func__, nilfs_warning(sci->sc_super, __func__,
"dirty file(s) after the final construction\n"); "dirty file(s) after the final construction\n");
nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
} }
WARN_ON(!list_empty(&sci->sc_segbufs)); WARN_ON(!list_empty(&sci->sc_segbufs));
...@@ -2763,79 +2754,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) ...@@ -2763,79 +2754,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
nilfs_put_root(sci->sc_root); nilfs_put_root(sci->sc_root);
down_write(&sbi->s_nilfs->ns_segctor_sem); down_write(&nilfs->ns_segctor_sem);
del_timer_sync(&sci->sc_timer); del_timer_sync(&sci->sc_timer);
kfree(sci); kfree(sci);
} }
/** /**
* nilfs_attach_segment_constructor - attach a segment constructor * nilfs_attach_log_writer - attach log writer
* @sbi: nilfs_sb_info * @sb: super block instance
* @root: root object of the current filesystem tree * @root: root object of the current filesystem tree
* *
* nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, * This allocates a log writer object, initializes it, and starts the
* initializes it, and starts the segment constructor. * log writer.
* *
* Return Value: On success, 0 is returned. On error, one of the following * Return Value: On success, 0 is returned. On error, one of the following
* negative error code is returned. * negative error code is returned.
* *
* %-ENOMEM - Insufficient memory available. * %-ENOMEM - Insufficient memory available.
*/ */
int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)
struct nilfs_root *root)
{ {
struct the_nilfs *nilfs = sb->s_fs_info;
int err; int err;
if (NILFS_SC(sbi)) { if (nilfs->ns_writer) {
/* /*
* This happens if the filesystem was remounted * This happens if the filesystem was remounted
* read/write after nilfs_error degenerated it into a * read/write after nilfs_error degenerated it into a
* read-only mount. * read-only mount.
*/ */
nilfs_detach_segment_constructor(sbi); nilfs_detach_log_writer(sb);
} }
sbi->s_sc_info = nilfs_segctor_new(sbi, root); nilfs->ns_writer = nilfs_segctor_new(sb, root);
if (!sbi->s_sc_info) if (!nilfs->ns_writer)
return -ENOMEM; return -ENOMEM;
err = nilfs_segctor_start_thread(NILFS_SC(sbi)); err = nilfs_segctor_start_thread(nilfs->ns_writer);
if (err) { if (err) {
kfree(sbi->s_sc_info); kfree(nilfs->ns_writer);
sbi->s_sc_info = NULL; nilfs->ns_writer = NULL;
} }
return err; return err;
} }
/** /**
* nilfs_detach_segment_constructor - destroy the segment constructor * nilfs_detach_log_writer - destroy log writer
* @sbi: nilfs_sb_info * @sb: super block instance
* *
* nilfs_detach_segment_constructor() kills the segment constructor daemon, * This kills log writer daemon, frees the log writer object, and
* frees the struct nilfs_sc_info, and destroy the dirty file list. * destroys list of dirty files.
*/ */
void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) void nilfs_detach_log_writer(struct super_block *sb)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
LIST_HEAD(garbage_list); LIST_HEAD(garbage_list);
down_write(&nilfs->ns_segctor_sem); down_write(&nilfs->ns_segctor_sem);
if (NILFS_SC(sbi)) { if (nilfs->ns_writer) {
nilfs_segctor_destroy(NILFS_SC(sbi)); nilfs_segctor_destroy(nilfs->ns_writer);
sbi->s_sc_info = NULL; nilfs->ns_writer = NULL;
} }
/* Force to free the list of dirty files */ /* Force to free the list of dirty files */
spin_lock(&sbi->s_inode_lock); spin_lock(&nilfs->ns_inode_lock);
if (!list_empty(&sbi->s_dirty_files)) { if (!list_empty(&nilfs->ns_dirty_files)) {
list_splice_init(&sbi->s_dirty_files, &garbage_list); list_splice_init(&nilfs->ns_dirty_files, &garbage_list);
nilfs_warning(sbi->s_super, __func__, nilfs_warning(sb, __func__,
"Non empty dirty list after the last " "Hit dirty file after stopped log writer\n");
"segment construction\n"); }
} spin_unlock(&nilfs->ns_inode_lock);
spin_unlock(&sbi->s_inode_lock);
up_write(&nilfs->ns_segctor_sem); up_write(&nilfs->ns_segctor_sem);
nilfs_dispose_list(sbi, &garbage_list, 1); nilfs_dispose_list(nilfs, &garbage_list, 1);
} }
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "sb.h" #include "nilfs.h"
struct nilfs_root; struct nilfs_root;
...@@ -88,7 +88,6 @@ struct nilfs_segsum_pointer { ...@@ -88,7 +88,6 @@ struct nilfs_segsum_pointer {
/** /**
* struct nilfs_sc_info - Segment constructor information * struct nilfs_sc_info - Segment constructor information
* @sc_super: Back pointer to super_block struct * @sc_super: Back pointer to super_block struct
* @sc_sbi: Back pointer to nilfs_sb_info struct
* @sc_root: root object of the current filesystem tree * @sc_root: root object of the current filesystem tree
* @sc_nblk_inc: Block count of current generation * @sc_nblk_inc: Block count of current generation
* @sc_dirty_files: List of files to be written * @sc_dirty_files: List of files to be written
...@@ -131,7 +130,6 @@ struct nilfs_segsum_pointer { ...@@ -131,7 +130,6 @@ struct nilfs_segsum_pointer {
*/ */
struct nilfs_sc_info { struct nilfs_sc_info {
struct super_block *sc_super; struct super_block *sc_super;
struct nilfs_sb_info *sc_sbi;
struct nilfs_root *sc_root; struct nilfs_root *sc_root;
unsigned long sc_nblk_inc; unsigned long sc_nblk_inc;
...@@ -235,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); ...@@ -235,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t);
extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
void **); void **);
int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root);
struct nilfs_root *root); void nilfs_detach_log_writer(struct super_block *sb);
extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
/* recovery.c */ /* recovery.c */
extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t, extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t,
struct buffer_head **, int); struct buffer_head **, int);
extern int nilfs_search_super_root(struct the_nilfs *, extern int nilfs_search_super_root(struct the_nilfs *,
struct nilfs_recovery_info *); struct nilfs_recovery_info *);
extern int nilfs_salvage_orphan_logs(struct the_nilfs *, int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb,
struct nilfs_sb_info *, struct nilfs_recovery_info *ri);
struct nilfs_recovery_info *);
extern void nilfs_dispose_segment_list(struct list_head *); extern void nilfs_dispose_segment_list(struct list_head *);
#endif /* _NILFS_SEGMENT_H */ #endif /* _NILFS_SEGMENT_H */
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/random.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/writeback.h> #include <linux/writeback.h>
...@@ -72,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep; ...@@ -72,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep;
struct kmem_cache *nilfs_segbuf_cachep; struct kmem_cache *nilfs_segbuf_cachep;
struct kmem_cache *nilfs_btree_path_cache; struct kmem_cache *nilfs_btree_path_cache;
static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); static int nilfs_setup_super(struct super_block *sb, int is_mount);
static int nilfs_remount(struct super_block *sb, int *flags, char *data); static int nilfs_remount(struct super_block *sb, int *flags, char *data);
static void nilfs_set_error(struct nilfs_sb_info *sbi) static void nilfs_set_error(struct super_block *sb)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
nilfs->ns_mount_state |= NILFS_ERROR_FS; nilfs->ns_mount_state |= NILFS_ERROR_FS;
sbp = nilfs_prepare_super(sbi, 0); sbp = nilfs_prepare_super(sb, 0);
if (likely(sbp)) { if (likely(sbp)) {
sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
if (sbp[1]) if (sbp[1])
sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
} }
} }
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
...@@ -109,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) ...@@ -109,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi)
void nilfs_error(struct super_block *sb, const char *function, void nilfs_error(struct super_block *sb, const char *function,
const char *fmt, ...) const char *fmt, ...)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
...@@ -124,15 +123,15 @@ void nilfs_error(struct super_block *sb, const char *function, ...@@ -124,15 +123,15 @@ void nilfs_error(struct super_block *sb, const char *function,
va_end(args); va_end(args);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
nilfs_set_error(sbi); nilfs_set_error(sb);
if (nilfs_test_opt(sbi, ERRORS_RO)) { if (nilfs_test_opt(nilfs, ERRORS_RO)) {
printk(KERN_CRIT "Remounting filesystem read-only\n"); printk(KERN_CRIT "Remounting filesystem read-only\n");
sb->s_flags |= MS_RDONLY; sb->s_flags |= MS_RDONLY;
} }
} }
if (nilfs_test_opt(sbi, ERRORS_PANIC)) if (nilfs_test_opt(nilfs, ERRORS_PANIC))
panic("NILFS (device %s): panic forced after error\n", panic("NILFS (device %s): panic forced after error\n",
sb->s_id); sb->s_id);
} }
...@@ -189,14 +188,14 @@ void nilfs_destroy_inode(struct inode *inode) ...@@ -189,14 +188,14 @@ void nilfs_destroy_inode(struct inode *inode)
call_rcu(&inode->i_rcu, nilfs_i_callback); call_rcu(&inode->i_rcu, nilfs_i_callback);
} }
static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) static int nilfs_sync_super(struct super_block *sb, int flag)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
int err; int err;
retry: retry:
set_buffer_dirty(nilfs->ns_sbh[0]); set_buffer_dirty(nilfs->ns_sbh[0]);
if (nilfs_test_opt(sbi, BARRIER)) { if (nilfs_test_opt(nilfs, BARRIER)) {
err = __sync_dirty_buffer(nilfs->ns_sbh[0], err = __sync_dirty_buffer(nilfs->ns_sbh[0],
WRITE_SYNC | WRITE_FLUSH_FUA); WRITE_SYNC | WRITE_FLUSH_FUA);
} else { } else {
...@@ -263,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, ...@@ -263,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp,
spin_unlock(&nilfs->ns_last_segment_lock); spin_unlock(&nilfs->ns_last_segment_lock);
} }
struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
int flip) int flip)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp = nilfs->ns_sbp; struct nilfs_super_block **sbp = nilfs->ns_sbp;
/* nilfs->ns_sem must be locked by the caller. */ /* nilfs->ns_sem must be locked by the caller. */
...@@ -276,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, ...@@ -276,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
} else { } else {
printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", printk(KERN_CRIT "NILFS: superblock broke on dev %s\n",
sbi->s_super->s_id); sb->s_id);
return NULL; return NULL;
} }
} else if (sbp[1] && } else if (sbp[1] &&
...@@ -290,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, ...@@ -290,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
return sbp; return sbp;
} }
int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) int nilfs_commit_super(struct super_block *sb, int flag)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp = nilfs->ns_sbp; struct nilfs_super_block **sbp = nilfs->ns_sbp;
time_t t; time_t t;
...@@ -312,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) ...@@ -312,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
nilfs->ns_sbsize)); nilfs->ns_sbsize));
} }
clear_nilfs_sb_dirty(nilfs); clear_nilfs_sb_dirty(nilfs);
return nilfs_sync_super(sbi, flag); return nilfs_sync_super(sb, flag);
} }
/** /**
* nilfs_cleanup_super() - write filesystem state for cleanup * nilfs_cleanup_super() - write filesystem state for cleanup
* @sbi: nilfs_sb_info to be unmounted or degraded to read-only * @sb: super block instance to be unmounted or degraded to read-only
* *
* This function restores state flags in the on-disk super block. * This function restores state flags in the on-disk super block.
* This will set "clean" flag (i.e. NILFS_VALID_FS) unless the * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the
* filesystem was not clean previously. * filesystem was not clean previously.
*/ */
int nilfs_cleanup_super(struct nilfs_sb_info *sbi) int nilfs_cleanup_super(struct super_block *sb)
{ {
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
int flag = NILFS_SB_COMMIT; int flag = NILFS_SB_COMMIT;
int ret = -EIO; int ret = -EIO;
sbp = nilfs_prepare_super(sbi, 0); sbp = nilfs_prepare_super(sb, 0);
if (sbp) { if (sbp) {
sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); nilfs_set_log_cursor(sbp[0], nilfs);
if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) {
/* /*
* make the "clean" flag also to the opposite * make the "clean" flag also to the opposite
...@@ -342,21 +342,20 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi) ...@@ -342,21 +342,20 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
sbp[1]->s_state = sbp[0]->s_state; sbp[1]->s_state = sbp[0]->s_state;
flag = NILFS_SB_COMMIT_ALL; flag = NILFS_SB_COMMIT_ALL;
} }
ret = nilfs_commit_super(sbi, flag); ret = nilfs_commit_super(sb, flag);
} }
return ret; return ret;
} }
static void nilfs_put_super(struct super_block *sb) static void nilfs_put_super(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
nilfs_detach_segment_constructor(sbi); nilfs_detach_log_writer(sb);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_cleanup_super(sbi); nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
...@@ -365,15 +364,12 @@ static void nilfs_put_super(struct super_block *sb) ...@@ -365,15 +364,12 @@ static void nilfs_put_super(struct super_block *sb)
iput(nilfs->ns_dat); iput(nilfs->ns_dat);
destroy_nilfs(nilfs); destroy_nilfs(nilfs);
sbi->s_super = NULL;
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
kfree(sbi);
} }
static int nilfs_sync_fs(struct super_block *sb, int wait) static int nilfs_sync_fs(struct super_block *sb, int wait)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
int err = 0; int err = 0;
...@@ -383,10 +379,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) ...@@ -383,10 +379,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
if (nilfs_sb_dirty(nilfs)) { if (nilfs_sb_dirty(nilfs)) {
sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs));
if (likely(sbp)) { if (likely(sbp)) {
nilfs_set_log_cursor(sbp[0], nilfs); nilfs_set_log_cursor(sbp[0], nilfs);
nilfs_commit_super(sbi, NILFS_SB_COMMIT); nilfs_commit_super(sb, NILFS_SB_COMMIT);
} }
} }
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
...@@ -394,10 +390,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) ...@@ -394,10 +390,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
return err; return err;
} }
int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
struct nilfs_root **rootp) struct nilfs_root **rootp)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_root *root; struct nilfs_root *root;
struct nilfs_checkpoint *raw_cp; struct nilfs_checkpoint *raw_cp;
struct buffer_head *bh_cp; struct buffer_head *bh_cp;
...@@ -426,7 +422,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, ...@@ -426,7 +422,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
goto failed; goto failed;
} }
err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size, err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size,
&raw_cp->cp_ifile_inode, &root->ifile); &raw_cp->cp_ifile_inode, &root->ifile);
if (err) if (err)
goto failed_bh; goto failed_bh;
...@@ -450,8 +446,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, ...@@ -450,8 +446,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
static int nilfs_freeze(struct super_block *sb) static int nilfs_freeze(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
int err; int err;
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
...@@ -459,21 +454,20 @@ static int nilfs_freeze(struct super_block *sb) ...@@ -459,21 +454,20 @@ static int nilfs_freeze(struct super_block *sb)
/* Mark super block clean */ /* Mark super block clean */
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
err = nilfs_cleanup_super(sbi); err = nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
return err; return err;
} }
static int nilfs_unfreeze(struct super_block *sb) static int nilfs_unfreeze(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
return 0; return 0;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, false); nilfs_setup_super(sb, false);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
return 0; return 0;
} }
...@@ -530,22 +524,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -530,22 +524,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{ {
struct super_block *sb = vfs->mnt_sb; struct super_block *sb = vfs->mnt_sb;
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root;
if (!nilfs_test_opt(sbi, BARRIER)) if (!nilfs_test_opt(nilfs, BARRIER))
seq_puts(seq, ",nobarrier"); seq_puts(seq, ",nobarrier");
if (root->cno != NILFS_CPTREE_CURRENT_CNO) if (root->cno != NILFS_CPTREE_CURRENT_CNO)
seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno);
if (nilfs_test_opt(sbi, ERRORS_PANIC)) if (nilfs_test_opt(nilfs, ERRORS_PANIC))
seq_puts(seq, ",errors=panic"); seq_puts(seq, ",errors=panic");
if (nilfs_test_opt(sbi, ERRORS_CONT)) if (nilfs_test_opt(nilfs, ERRORS_CONT))
seq_puts(seq, ",errors=continue"); seq_puts(seq, ",errors=continue");
if (nilfs_test_opt(sbi, STRICT_ORDER)) if (nilfs_test_opt(nilfs, STRICT_ORDER))
seq_puts(seq, ",order=strict"); seq_puts(seq, ",order=strict");
if (nilfs_test_opt(sbi, NORECOVERY)) if (nilfs_test_opt(nilfs, NORECOVERY))
seq_puts(seq, ",norecovery"); seq_puts(seq, ",norecovery");
if (nilfs_test_opt(sbi, DISCARD)) if (nilfs_test_opt(nilfs, DISCARD))
seq_puts(seq, ",discard"); seq_puts(seq, ",discard");
return 0; return 0;
...@@ -594,7 +588,7 @@ static match_table_t tokens = { ...@@ -594,7 +588,7 @@ static match_table_t tokens = {
static int parse_options(char *options, struct super_block *sb, int is_remount) static int parse_options(char *options, struct super_block *sb, int is_remount)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
char *p; char *p;
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
...@@ -609,29 +603,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) ...@@ -609,29 +603,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
token = match_token(p, tokens, args); token = match_token(p, tokens, args);
switch (token) { switch (token) {
case Opt_barrier: case Opt_barrier:
nilfs_set_opt(sbi, BARRIER); nilfs_set_opt(nilfs, BARRIER);
break; break;
case Opt_nobarrier: case Opt_nobarrier:
nilfs_clear_opt(sbi, BARRIER); nilfs_clear_opt(nilfs, BARRIER);
break; break;
case Opt_order: case Opt_order:
if (strcmp(args[0].from, "relaxed") == 0) if (strcmp(args[0].from, "relaxed") == 0)
/* Ordered data semantics */ /* Ordered data semantics */
nilfs_clear_opt(sbi, STRICT_ORDER); nilfs_clear_opt(nilfs, STRICT_ORDER);
else if (strcmp(args[0].from, "strict") == 0) else if (strcmp(args[0].from, "strict") == 0)
/* Strict in-order semantics */ /* Strict in-order semantics */
nilfs_set_opt(sbi, STRICT_ORDER); nilfs_set_opt(nilfs, STRICT_ORDER);
else else
return 0; return 0;
break; break;
case Opt_err_panic: case Opt_err_panic:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC); nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC);
break; break;
case Opt_err_ro: case Opt_err_ro:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO); nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO);
break; break;
case Opt_err_cont: case Opt_err_cont:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT);
break; break;
case Opt_snapshot: case Opt_snapshot:
if (is_remount) { if (is_remount) {
...@@ -642,13 +636,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) ...@@ -642,13 +636,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
} }
break; break;
case Opt_norecovery: case Opt_norecovery:
nilfs_set_opt(sbi, NORECOVERY); nilfs_set_opt(nilfs, NORECOVERY);
break; break;
case Opt_discard: case Opt_discard:
nilfs_set_opt(sbi, DISCARD); nilfs_set_opt(nilfs, DISCARD);
break; break;
case Opt_nodiscard: case Opt_nodiscard:
nilfs_clear_opt(sbi, DISCARD); nilfs_clear_opt(nilfs, DISCARD);
break; break;
default: default:
printk(KERN_ERR printk(KERN_ERR
...@@ -660,22 +654,24 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) ...@@ -660,22 +654,24 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
} }
static inline void static inline void
nilfs_set_default_options(struct nilfs_sb_info *sbi, nilfs_set_default_options(struct super_block *sb,
struct nilfs_super_block *sbp) struct nilfs_super_block *sbp)
{ {
sbi->s_mount_opt = struct the_nilfs *nilfs = sb->s_fs_info;
nilfs->ns_mount_opt =
NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER;
} }
static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) static int nilfs_setup_super(struct super_block *sb, int is_mount)
{ {
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp; struct nilfs_super_block **sbp;
int max_mnt_count; int max_mnt_count;
int mnt_count; int mnt_count;
/* nilfs->ns_sem must be locked by the caller. */ /* nilfs->ns_sem must be locked by the caller. */
sbp = nilfs_prepare_super(sbi, 0); sbp = nilfs_prepare_super(sb, 0);
if (!sbp) if (!sbp)
return -EIO; return -EIO;
...@@ -706,7 +702,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) ...@@ -706,7 +702,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
/* synchronize sbp[1] with sbp[0] */ /* synchronize sbp[1] with sbp[0] */
if (sbp[1]) if (sbp[1])
memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
} }
struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
...@@ -727,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, ...@@ -727,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb,
struct nilfs_super_block *sbp, struct nilfs_super_block *sbp,
char *data) char *data)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
sb->s_magic = le16_to_cpu(sbp->s_magic); sb->s_magic = le16_to_cpu(sbp->s_magic);
...@@ -736,12 +732,12 @@ int nilfs_store_magic_and_option(struct super_block *sb, ...@@ -736,12 +732,12 @@ int nilfs_store_magic_and_option(struct super_block *sb,
sb->s_flags |= MS_NOATIME; sb->s_flags |= MS_NOATIME;
#endif #endif
nilfs_set_default_options(sbi, sbp); nilfs_set_default_options(sb, sbp);
sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid);
sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid);
sbi->s_interval = le32_to_cpu(sbp->s_c_interval); nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval);
sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max);
return !parse_options(data, sb, 0) ? -EINVAL : 0 ; return !parse_options(data, sb, 0) ? -EINVAL : 0 ;
} }
...@@ -822,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb, ...@@ -822,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb,
static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
struct dentry **root_dentry) struct dentry **root_dentry)
{ {
struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs; struct the_nilfs *nilfs = s->s_fs_info;
struct nilfs_root *root; struct nilfs_root *root;
int ret; int ret;
...@@ -840,7 +836,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, ...@@ -840,7 +836,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
goto out; goto out;
} }
ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root); ret = nilfs_attach_checkpoint(s, cno, false, &root);
if (ret) { if (ret) {
printk(KERN_ERR "NILFS: error loading snapshot " printk(KERN_ERR "NILFS: error loading snapshot "
"(checkpoint number=%llu).\n", "(checkpoint number=%llu).\n",
...@@ -874,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) ...@@ -874,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry)
int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
{ {
struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_root *root; struct nilfs_root *root;
struct inode *inode; struct inode *inode;
struct dentry *dentry; struct dentry *dentry;
...@@ -887,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) ...@@ -887,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
return true; /* protect recent checkpoints */ return true; /* protect recent checkpoints */
ret = false; ret = false;
root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); root = nilfs_lookup_root(nilfs, cno);
if (root) { if (root) {
inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO); inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
if (inode) { if (inode) {
...@@ -917,43 +913,21 @@ static int ...@@ -917,43 +913,21 @@ static int
nilfs_fill_super(struct super_block *sb, void *data, int silent) nilfs_fill_super(struct super_block *sb, void *data, int silent)
{ {
struct the_nilfs *nilfs; struct the_nilfs *nilfs;
struct nilfs_sb_info *sbi;
struct nilfs_root *fsroot; struct nilfs_root *fsroot;
struct backing_dev_info *bdi; struct backing_dev_info *bdi;
__u64 cno; __u64 cno;
int err; int err;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); nilfs = alloc_nilfs(sb->s_bdev);
if (!sbi) if (!nilfs)
return -ENOMEM; return -ENOMEM;
sb->s_fs_info = sbi; sb->s_fs_info = nilfs;
sbi->s_super = sb;
nilfs = alloc_nilfs(sb->s_bdev);
if (!nilfs) {
err = -ENOMEM;
goto failed_sbi;
}
sbi->s_nilfs = nilfs;
err = init_nilfs(nilfs, sbi, (char *)data); err = init_nilfs(nilfs, sb, (char *)data);
if (err) if (err)
goto failed_nilfs; goto failed_nilfs;
spin_lock_init(&sbi->s_inode_lock);
INIT_LIST_HEAD(&sbi->s_dirty_files);
/*
* Following initialization is overlapped because
* nilfs_sb_info structure has been cleared at the beginning.
* But we reserve them to keep our interest and make ready
* for the future change.
*/
get_random_bytes(&sbi->s_next_generation,
sizeof(sbi->s_next_generation));
spin_lock_init(&sbi->s_next_gen_lock);
sb->s_op = &nilfs_sops; sb->s_op = &nilfs_sops;
sb->s_export_op = &nilfs_export_ops; sb->s_export_op = &nilfs_export_ops;
sb->s_root = NULL; sb->s_root = NULL;
...@@ -962,12 +936,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -962,12 +936,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
sb->s_bdi = bdi ? : &default_backing_dev_info; sb->s_bdi = bdi ? : &default_backing_dev_info;
err = load_nilfs(nilfs, sbi); err = load_nilfs(nilfs, sb);
if (err) if (err)
goto failed_nilfs; goto failed_nilfs;
cno = nilfs_last_cno(nilfs); cno = nilfs_last_cno(nilfs);
err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); err = nilfs_attach_checkpoint(sb, cno, true, &fsroot);
if (err) { if (err) {
printk(KERN_ERR "NILFS: error loading last checkpoint " printk(KERN_ERR "NILFS: error loading last checkpoint "
"(checkpoint number=%llu).\n", (unsigned long long)cno); "(checkpoint number=%llu).\n", (unsigned long long)cno);
...@@ -975,7 +949,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -975,7 +949,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
} }
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
err = nilfs_attach_segment_constructor(sbi, fsroot); err = nilfs_attach_log_writer(sb, fsroot);
if (err) if (err)
goto failed_checkpoint; goto failed_checkpoint;
} }
...@@ -988,14 +962,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -988,14 +962,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, true); nilfs_setup_super(sb, true);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
return 0; return 0;
failed_segctor: failed_segctor:
nilfs_detach_segment_constructor(sbi); nilfs_detach_log_writer(sb);
failed_checkpoint: failed_checkpoint:
nilfs_put_root(fsroot); nilfs_put_root(fsroot);
...@@ -1007,23 +981,18 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1007,23 +981,18 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
failed_nilfs: failed_nilfs:
destroy_nilfs(nilfs); destroy_nilfs(nilfs);
failed_sbi:
sb->s_fs_info = NULL;
kfree(sbi);
return err; return err;
} }
static int nilfs_remount(struct super_block *sb, int *flags, char *data) static int nilfs_remount(struct super_block *sb, int *flags, char *data)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sb->s_fs_info;
struct the_nilfs *nilfs = sbi->s_nilfs;
unsigned long old_sb_flags; unsigned long old_sb_flags;
unsigned long old_mount_opt; unsigned long old_mount_opt;
int err; int err;
old_sb_flags = sb->s_flags; old_sb_flags = sb->s_flags;
old_mount_opt = sbi->s_mount_opt; old_mount_opt = nilfs->ns_mount_opt;
if (!parse_options(data, sb, 1)) { if (!parse_options(data, sb, 1)) {
err = -EINVAL; err = -EINVAL;
...@@ -1043,8 +1012,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1043,8 +1012,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
goto out; goto out;
if (*flags & MS_RDONLY) { if (*flags & MS_RDONLY) {
/* Shutting down the segment constructor */ /* Shutting down log writer */
nilfs_detach_segment_constructor(sbi); nilfs_detach_log_writer(sb);
sb->s_flags |= MS_RDONLY; sb->s_flags |= MS_RDONLY;
/* /*
...@@ -1052,7 +1021,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1052,7 +1021,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
* the RDONLY flag and then mark the partition as valid again. * the RDONLY flag and then mark the partition as valid again.
*/ */
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_cleanup_super(sbi); nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} else { } else {
__u64 features; __u64 features;
...@@ -1079,12 +1048,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1079,12 +1048,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
sb->s_flags &= ~MS_RDONLY; sb->s_flags &= ~MS_RDONLY;
root = NILFS_I(sb->s_root->d_inode)->i_root; root = NILFS_I(sb->s_root->d_inode)->i_root;
err = nilfs_attach_segment_constructor(sbi, root); err = nilfs_attach_log_writer(sb, root);
if (err) if (err)
goto restore_opts; goto restore_opts;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, true); nilfs_setup_super(sb, true);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
out: out:
...@@ -1092,13 +1061,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1092,13 +1061,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
restore_opts: restore_opts:
sb->s_flags = old_sb_flags; sb->s_flags = old_sb_flags;
sbi->s_mount_opt = old_mount_opt; nilfs->ns_mount_opt = old_mount_opt;
return err; return err;
} }
struct nilfs_super_data { struct nilfs_super_data {
struct block_device *bdev; struct block_device *bdev;
struct nilfs_sb_info *sbi;
__u64 cno; __u64 cno;
int flags; int flags;
}; };
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/random.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include "nilfs.h" #include "nilfs.h"
#include "segment.h" #include "segment.h"
...@@ -75,7 +76,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) ...@@ -75,7 +76,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
nilfs->ns_bdev = bdev; nilfs->ns_bdev = bdev;
atomic_set(&nilfs->ns_ndirtyblks, 0); atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem); init_rwsem(&nilfs->ns_sem);
INIT_LIST_HEAD(&nilfs->ns_dirty_files);
INIT_LIST_HEAD(&nilfs->ns_gc_inodes); INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
spin_lock_init(&nilfs->ns_inode_lock);
spin_lock_init(&nilfs->ns_next_gen_lock);
spin_lock_init(&nilfs->ns_last_segment_lock); spin_lock_init(&nilfs->ns_last_segment_lock);
nilfs->ns_cptree = RB_ROOT; nilfs->ns_cptree = RB_ROOT;
spin_lock_init(&nilfs->ns_cptree_lock); spin_lock_init(&nilfs->ns_cptree_lock);
...@@ -197,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, ...@@ -197,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs,
/** /**
* load_nilfs - load and recover the nilfs * load_nilfs - load and recover the nilfs
* @nilfs: the_nilfs structure to be released * @nilfs: the_nilfs structure to be released
* @sbi: nilfs_sb_info used to recover past segment * @sb: super block isntance used to recover past segment
* *
* load_nilfs() searches and load the latest super root, * load_nilfs() searches and load the latest super root,
* attaches the last segment, and does recovery if needed. * attaches the last segment, and does recovery if needed.
* The caller must call this exclusively for simultaneous mounts. * The caller must call this exclusively for simultaneous mounts.
*/ */
int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
{ {
struct nilfs_recovery_info ri; struct nilfs_recovery_info ri;
unsigned int s_flags = sbi->s_super->s_flags; unsigned int s_flags = sb->s_flags;
int really_read_only = bdev_read_only(nilfs->ns_bdev); int really_read_only = bdev_read_only(nilfs->ns_bdev);
int valid_fs = nilfs_valid_fs(nilfs); int valid_fs = nilfs_valid_fs(nilfs);
int err; int err;
...@@ -271,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -271,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
goto scan_error; goto scan_error;
} }
err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root); err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root);
if (unlikely(err)) { if (unlikely(err)) {
printk(KERN_ERR "NILFS: error loading super root.\n"); printk(KERN_ERR "NILFS: error loading super root.\n");
goto failed; goto failed;
...@@ -283,7 +287,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -283,7 +287,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
if (s_flags & MS_RDONLY) { if (s_flags & MS_RDONLY) {
__u64 features; __u64 features;
if (nilfs_test_opt(sbi, NORECOVERY)) { if (nilfs_test_opt(nilfs, NORECOVERY)) {
printk(KERN_INFO "NILFS: norecovery option specified. " printk(KERN_INFO "NILFS: norecovery option specified. "
"skipping roll-forward recovery\n"); "skipping roll-forward recovery\n");
goto skip_recovery; goto skip_recovery;
...@@ -304,21 +308,21 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -304,21 +308,21 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
err = -EROFS; err = -EROFS;
goto failed_unload; goto failed_unload;
} }
sbi->s_super->s_flags &= ~MS_RDONLY; sb->s_flags &= ~MS_RDONLY;
} else if (nilfs_test_opt(sbi, NORECOVERY)) { } else if (nilfs_test_opt(nilfs, NORECOVERY)) {
printk(KERN_ERR "NILFS: recovery cancelled because norecovery " printk(KERN_ERR "NILFS: recovery cancelled because norecovery "
"option was specified for a read/write mount\n"); "option was specified for a read/write mount\n");
err = -EINVAL; err = -EINVAL;
goto failed_unload; goto failed_unload;
} }
err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri); err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
if (err) if (err)
goto failed_unload; goto failed_unload;
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */
err = nilfs_cleanup_super(sbi); err = nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
if (err) { if (err) {
...@@ -330,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -330,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
skip_recovery: skip_recovery:
nilfs_clear_recovery_info(&ri); nilfs_clear_recovery_info(&ri);
sbi->s_super->s_flags = s_flags; sb->s_flags = s_flags;
return 0; return 0;
scan_error: scan_error:
...@@ -344,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) ...@@ -344,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
failed: failed:
nilfs_clear_recovery_info(&ri); nilfs_clear_recovery_info(&ri);
sbi->s_super->s_flags = s_flags; sb->s_flags = s_flags;
return err; return err;
} }
...@@ -475,10 +479,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, ...@@ -475,10 +479,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
return -EIO; return -EIO;
} }
printk(KERN_WARNING printk(KERN_WARNING
"NILFS warning: unable to read primary superblock\n"); "NILFS warning: unable to read primary superblock "
} else if (!sbp[1]) "(blocksize = %d)\n", blocksize);
} else if (!sbp[1]) {
printk(KERN_WARNING printk(KERN_WARNING
"NILFS warning: unable to read secondary superblock\n"); "NILFS warning: unable to read secondary superblock "
"(blocksize = %d)\n", blocksize);
}
/* /*
* Compare two super blocks and set 1 in swp if the secondary * Compare two super blocks and set 1 in swp if the secondary
...@@ -505,7 +512,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, ...@@ -505,7 +512,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
if (!valid[!swp]) if (!valid[!swp])
printk(KERN_WARNING "NILFS warning: broken superblock. " printk(KERN_WARNING "NILFS warning: broken superblock. "
"using spare superblock.\n"); "using spare superblock (blocksize = %d).\n", blocksize);
if (swp) if (swp)
nilfs_swap_super_block(nilfs); nilfs_swap_super_block(nilfs);
...@@ -519,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, ...@@ -519,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
/** /**
* init_nilfs - initialize a NILFS instance. * init_nilfs - initialize a NILFS instance.
* @nilfs: the_nilfs structure * @nilfs: the_nilfs structure
* @sbi: nilfs_sb_info
* @sb: super block * @sb: super block
* @data: mount options * @data: mount options
* *
...@@ -530,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, ...@@ -530,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
* Return Value: On success, 0 is returned. On error, a negative error * Return Value: On success, 0 is returned. On error, a negative error
* code is returned. * code is returned.
*/ */
int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
{ {
struct super_block *sb = sbi->s_super;
struct nilfs_super_block *sbp; struct nilfs_super_block *sbp;
int blocksize; int blocksize;
int err; int err;
...@@ -588,6 +593,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) ...@@ -588,6 +593,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
nilfs->ns_blocksize_bits = sb->s_blocksize_bits; nilfs->ns_blocksize_bits = sb->s_blocksize_bits;
nilfs->ns_blocksize = blocksize; nilfs->ns_blocksize = blocksize;
get_random_bytes(&nilfs->ns_next_generation,
sizeof(nilfs->ns_next_generation));
err = nilfs_store_disk_layout(nilfs, sbp); err = nilfs_store_disk_layout(nilfs, sbp);
if (err) if (err)
goto failed_sbh; goto failed_sbh;
......
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "sb.h"
struct nilfs_sc_info;
/* the_nilfs struct */ /* the_nilfs struct */
enum { enum {
...@@ -65,13 +66,23 @@ enum { ...@@ -65,13 +66,23 @@ enum {
* @ns_last_cno: checkpoint number of the latest segment * @ns_last_cno: checkpoint number of the latest segment
* @ns_prot_seq: least sequence number of segments which must not be reclaimed * @ns_prot_seq: least sequence number of segments which must not be reclaimed
* @ns_prev_seq: base sequence number used to decide if advance log cursor * @ns_prev_seq: base sequence number used to decide if advance log cursor
* @ns_segctor_sem: segment constructor semaphore * @ns_writer: log writer
* @ns_segctor_sem: semaphore protecting log write
* @ns_dat: DAT file inode * @ns_dat: DAT file inode
* @ns_cpfile: checkpoint file inode * @ns_cpfile: checkpoint file inode
* @ns_sufile: segusage file inode * @ns_sufile: segusage file inode
* @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
* @ns_cptree_lock: lock protecting @ns_cptree * @ns_cptree_lock: lock protecting @ns_cptree
* @ns_dirty_files: list of dirty files
* @ns_inode_lock: lock protecting @ns_dirty_files
* @ns_gc_inodes: dummy inodes to keep live blocks * @ns_gc_inodes: dummy inodes to keep live blocks
* @ns_next_generation: next generation number for inodes
* @ns_next_gen_lock: lock protecting @ns_next_generation
* @ns_mount_opt: mount options
* @ns_resuid: uid for reserved blocks
* @ns_resgid: gid for reserved blocks
* @ns_interval: checkpoint creation interval
* @ns_watermark: watermark for the number of dirty buffers
* @ns_blocksize_bits: bit length of block size * @ns_blocksize_bits: bit length of block size
* @ns_blocksize: block size * @ns_blocksize: block size
* @ns_nsegments: number of segments in filesystem * @ns_nsegments: number of segments in filesystem
...@@ -131,6 +142,7 @@ struct the_nilfs { ...@@ -131,6 +142,7 @@ struct the_nilfs {
u64 ns_prot_seq; u64 ns_prot_seq;
u64 ns_prev_seq; u64 ns_prev_seq;
struct nilfs_sc_info *ns_writer;
struct rw_semaphore ns_segctor_sem; struct rw_semaphore ns_segctor_sem;
/* /*
...@@ -145,9 +157,25 @@ struct the_nilfs { ...@@ -145,9 +157,25 @@ struct the_nilfs {
struct rb_root ns_cptree; struct rb_root ns_cptree;
spinlock_t ns_cptree_lock; spinlock_t ns_cptree_lock;
/* Dirty inode list */
struct list_head ns_dirty_files;
spinlock_t ns_inode_lock;
/* GC inode list */ /* GC inode list */
struct list_head ns_gc_inodes; struct list_head ns_gc_inodes;
/* Inode allocator */
u32 ns_next_generation;
spinlock_t ns_next_gen_lock;
/* Mount options */
unsigned long ns_mount_opt;
uid_t ns_resuid;
gid_t ns_resgid;
unsigned long ns_interval;
unsigned long ns_watermark;
/* Disk layout information (static) */ /* Disk layout information (static) */
unsigned int ns_blocksize_bits; unsigned int ns_blocksize_bits;
unsigned int ns_blocksize; unsigned int ns_blocksize;
...@@ -180,6 +208,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued) ...@@ -180,6 +208,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
THE_NILFS_FNS(GC_RUNNING, gc_running) THE_NILFS_FNS(GC_RUNNING, gc_running)
THE_NILFS_FNS(SB_DIRTY, sb_dirty) THE_NILFS_FNS(SB_DIRTY, sb_dirty)
/*
* Mount option operations
*/
#define nilfs_clear_opt(nilfs, opt) \
do { (nilfs)->ns_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
#define nilfs_set_opt(nilfs, opt) \
do { (nilfs)->ns_mount_opt |= NILFS_MOUNT_##opt; } while (0)
#define nilfs_test_opt(nilfs, opt) ((nilfs)->ns_mount_opt & NILFS_MOUNT_##opt)
#define nilfs_write_opt(nilfs, mask, opt) \
do { (nilfs)->ns_mount_opt = \
(((nilfs)->ns_mount_opt & ~NILFS_MOUNT_##mask) | \
NILFS_MOUNT_##opt); \
} while (0)
/** /**
* struct nilfs_root - nilfs root object * struct nilfs_root - nilfs root object
* @cno: checkpoint number * @cno: checkpoint number
...@@ -224,15 +266,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) ...@@ -224,15 +266,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs)
void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
struct the_nilfs *alloc_nilfs(struct block_device *bdev); struct the_nilfs *alloc_nilfs(struct block_device *bdev);
void destroy_nilfs(struct the_nilfs *nilfs); void destroy_nilfs(struct the_nilfs *nilfs);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb);
int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno); struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno);
struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs, struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
__u64 cno); __u64 cno);
void nilfs_put_root(struct nilfs_root *root); void nilfs_put_root(struct nilfs_root *root);
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
int nilfs_near_disk_full(struct the_nilfs *); int nilfs_near_disk_full(struct the_nilfs *);
void nilfs_fall_back_super_block(struct the_nilfs *); void nilfs_fall_back_super_block(struct the_nilfs *);
void nilfs_swap_super_block(struct the_nilfs *); void nilfs_swap_super_block(struct the_nilfs *);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define XENFS_SUPER_MAGIC 0xabba1974 #define XENFS_SUPER_MAGIC 0xabba1974
#define EXT4_SUPER_MAGIC 0xEF53 #define EXT4_SUPER_MAGIC 0xEF53
#define BTRFS_SUPER_MAGIC 0x9123683E #define BTRFS_SUPER_MAGIC 0x9123683E
#define NILFS_SUPER_MAGIC 0x3434
#define HPFS_SUPER_MAGIC 0xf995e849 #define HPFS_SUPER_MAGIC 0xf995e849
#define ISOFS_SUPER_MAGIC 0x9660 #define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6 #define JFFS2_SUPER_MAGIC 0x72b6
......
...@@ -40,26 +40,7 @@ ...@@ -40,26 +40,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/magic.h>
/*
* Inode flags stored in nilfs_inode and on-memory nilfs inode
*
* We define these flags based on ext2-fs because of the
* compatibility reason; to avoid problems in chattr(1)
*/
#define NILFS_SECRM_FL 0x00000001 /* Secure deletion */
#define NILFS_UNRM_FL 0x00000002 /* Undelete */
#define NILFS_SYNC_FL 0x00000008 /* Synchronous updates */
#define NILFS_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define NILFS_APPEND_FL 0x00000020 /* writes to file may only append */
#define NILFS_NODUMP_FL 0x00000040 /* do not dump file */
#define NILFS_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define NILFS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define NILFS_DIRSYNC_FL 0x00010000 /* dirsync behaviour */
#define NILFS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
#define NILFS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
#define NILFS_INODE_BMAP_SIZE 7 #define NILFS_INODE_BMAP_SIZE 7
...@@ -236,8 +217,10 @@ struct nilfs_super_block { ...@@ -236,8 +217,10 @@ struct nilfs_super_block {
* If there is a bit set in the incompatible feature set that the kernel * If there is a bit set in the incompatible feature set that the kernel
* doesn't know about, it should refuse to mount the filesystem. * doesn't know about, it should refuse to mount the filesystem.
*/ */
#define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT 0x00000001ULL
#define NILFS_FEATURE_COMPAT_SUPP 0ULL #define NILFS_FEATURE_COMPAT_SUPP 0ULL
#define NILFS_FEATURE_COMPAT_RO_SUPP 0ULL #define NILFS_FEATURE_COMPAT_RO_SUPP NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT
#define NILFS_FEATURE_INCOMPAT_SUPP 0ULL #define NILFS_FEATURE_INCOMPAT_SUPP 0ULL
/* /*
...@@ -260,7 +243,6 @@ struct nilfs_super_block { ...@@ -260,7 +243,6 @@ struct nilfs_super_block {
#define NILFS_USER_INO 11 /* Fisrt user's file inode number */ #define NILFS_USER_INO 11 /* Fisrt user's file inode number */
#define NILFS_SB_OFFSET_BYTES 1024 /* byte offset of nilfs superblock */ #define NILFS_SB_OFFSET_BYTES 1024 /* byte offset of nilfs superblock */
#define NILFS_SUPER_MAGIC 0x3434 /* NILFS filesystem magic number */
#define NILFS_SEG_MIN_BLOCKS 16 /* Minimum number of blocks in #define NILFS_SEG_MIN_BLOCKS 16 /* Minimum number of blocks in
a full segment */ a full segment */
...@@ -346,17 +328,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen) ...@@ -346,17 +328,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen)
{ {
unsigned len = le16_to_cpu(dlen); unsigned len = le16_to_cpu(dlen);
#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
if (len == NILFS_MAX_REC_LEN) if (len == NILFS_MAX_REC_LEN)
return 1 << 16; return 1 << 16;
#endif
return len; return len;
} }
static inline __le16 nilfs_rec_len_to_disk(unsigned len) static inline __le16 nilfs_rec_len_to_disk(unsigned len)
{ {
#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
if (len == (1 << 16)) if (len == (1 << 16))
return cpu_to_le16(NILFS_MAX_REC_LEN); return cpu_to_le16(NILFS_MAX_REC_LEN);
else if (len > (1 << 16)) else if (len > (1 << 16))
BUG(); BUG();
#endif
return cpu_to_le16(len); return cpu_to_le16(len);
} }
...@@ -525,7 +511,7 @@ struct nilfs_checkpoint { ...@@ -525,7 +511,7 @@ struct nilfs_checkpoint {
__le64 cp_create; __le64 cp_create;
__le64 cp_nblk_inc; __le64 cp_nblk_inc;
__le64 cp_inodes_count; __le64 cp_inodes_count;
__le64 cp_blocks_count; /* Reserved (might be deleted) */ __le64 cp_blocks_count;
/* Do not change the byte offset of ifile inode. /* Do not change the byte offset of ifile inode.
To keep the compatibility of the disk format, To keep the compatibility of the disk format,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment