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,
group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr);
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
else
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_bh->b_page);
kunmap(req->pr_desc_bh->b_page);
......@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr);
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
else
nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_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)
for (j = i, n = 0;
(j < nitems) && nilfs_palloc_group_is_in(inode, group,
entry_nrs[j]);
j++, n++) {
j++) {
nilfs_palloc_group(inode, entry_nrs[j], &group_offset);
if (!nilfs_clear_bit_atomic(
nilfs_mdt_bgl_lock(inode, group),
......@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
"%s: entry number %llu already freed\n",
__func__,
(unsigned long long)entry_nrs[j]);
} else {
n++;
}
}
nilfs_palloc_group_desc_add_entries(inode, group, desc, n);
......
......@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include "nilfs.h"
#include "bmap.h"
#include "sb.h"
#include "btree.h"
#include "direct.h"
#include "btnode.h"
......@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
/*
* 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,
const struct buffer_head *bh)
{
......
......@@ -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_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. */
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)
if (ret < 0)
goto out;
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:
nilfs_btree_free_path(path);
......@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
if (ret < 0)
goto out;
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:
nilfs_btree_free_path(path);
......@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
return ret;
nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
di, ni, bh);
nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
return 0;
}
......
......@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
nilfs_commit_chunk(page, mapping, from, to);
nilfs_put_page(page);
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)
nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, page->mapping, from, to);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
......@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
dir->inode = 0;
nilfs_commit_chunk(page, mapping, from, to);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
/* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */
out:
nilfs_put_page(page);
return err;
......@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = {
.readdir = nilfs_readdir,
.unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = nilfs_ioctl,
.compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */
.fsync = nilfs_sync_file,
......
......@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
if (NILFS_BMAP_USE_VBN(bmap))
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;
}
......@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
if (!ret) {
nilfs_bmap_commit_end_ptr(bmap, &req, dat);
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;
}
......
......@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
struct nilfs_transaction_info ti;
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 */
lock_page(page);
......@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = {
.aio_write = generic_file_aio_write,
.unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = nilfs_ioctl,
.compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */
.mmap = nilfs_file_mmap,
.open = generic_file_open,
......
......@@ -41,6 +41,24 @@ struct nilfs_iget_args {
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)
* @inode - inode struct of the target file
......@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = {
struct inode *nilfs_new_inode(struct inode *dir, int mode)
{
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 nilfs_inode_info *ii;
struct nilfs_root *root;
......@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
/* No lock is needed; iget() ensures it. */
}
ii->i_flags = NILFS_I(dir)->i_flags;
if (S_ISLNK(mode))
ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL);
if (!S_ISDIR(mode))
ii->i_flags &= ~NILFS_DIRSYNC_FL;
ii->i_flags = nilfs_mask_flags(
mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
/* ii->i_file_acl = 0; */
/* ii->i_dir_acl = 0; */
ii->i_dir_start_lookup = 0;
nilfs_set_inode_flags(inode);
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
spin_unlock(&sbi->s_next_gen_lock);
spin_lock(&nilfs->ns_next_gen_lock);
inode->i_generation = nilfs->ns_next_generation++;
spin_unlock(&nilfs->ns_next_gen_lock);
insert_inode_hash(inode);
err = nilfs_init_acl(inode, dir);
......@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode)
inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
S_DIRSYNC);
if (flags & NILFS_SYNC_FL)
if (flags & FS_SYNC_FL)
inode->i_flags |= S_SYNC;
if (flags & NILFS_APPEND_FL)
if (flags & FS_APPEND_FL)
inode->i_flags |= S_APPEND;
if (flags & NILFS_IMMUTABLE_FL)
if (flags & FS_IMMUTABLE_FL)
inode->i_flags |= S_IMMUTABLE;
#ifndef NILFS_ATIME_DISABLE
if (flags & NILFS_NOATIME_FL)
#endif
if (flags & FS_NOATIME_FL)
inode->i_flags |= S_NOATIME;
if (flags & NILFS_DIRSYNC_FL)
if (flags & FS_DIRSYNC_FL)
inode->i_flags |= S_DIRSYNC;
mapping_set_gfp_mask(inode->i_mapping,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
......@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb,
struct nilfs_root *root, unsigned long ino,
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 nilfs_inode *raw_inode;
int err;
......@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode)
struct nilfs_transaction_info ti;
struct super_block *sb = inode->i_sb;
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_data.nrpages)
......@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode)
nilfs_mark_inode_dirty(inode);
end_writeback(inode);
nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
atomic_dec(&ii->i_root->inodes_count);
ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
if (!ret)
atomic_dec(&ii->i_root->inodes_count);
nilfs_clear_inode(inode);
......@@ -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)
{
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);
int err;
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
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,
inode->i_ino, pbh);
if (unlikely(err))
return err;
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
if (ii->i_bh == NULL)
ii->i_bh = *pbh;
else {
......@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
*pbh = ii->i_bh;
get_bh(*pbh);
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
return 0;
}
int nilfs_inode_dirty(struct inode *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;
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) ||
test_bit(NILFS_I_BUSY, &ii->i_state);
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
}
return ret;
}
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 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))
return 0;
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
!test_bit(NILFS_I_BUSY, &ii->i_state)) {
/* Because this routine may race with nilfs_dispose_list(),
......@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) {
/* This will happen when somebody is freeing
this inode. */
nilfs_warning(sbi->s_super, __func__,
nilfs_warning(inode->i_sb, __func__,
"cannot get inode (ino=%lu)\n",
inode->i_ino);
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
return -EINVAL; /* NILFS_I_DIRTY may remain for
freeing inode */
}
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);
}
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
return 0;
}
......
......@@ -26,7 +26,9 @@
#include <linux/capability.h> /* capable() */
#include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
#include <linux/vmalloc.h>
#include <linux/compat.h> /* compat_ptr() */
#include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */
#include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h>
#include "nilfs.h"
#include "segment.h"
......@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
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,
unsigned int cmd, void __user *argp)
{
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct inode *cpfile = nilfs->ns_cpfile;
struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_transaction_info ti;
struct nilfs_cpmode cpmode;
int ret;
......@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
nilfs_transaction_begin(inode->i_sb, &ti, 0);
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))
nilfs_transaction_abort(inode->i_sb);
else
......@@ -137,7 +202,7 @@ static int
nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
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;
__u64 cno;
int ret;
......@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
goto out;
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))
nilfs_transaction_abort(inode->i_sb);
else
......@@ -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,
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;
int ret;
......@@ -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,
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;
int ret;
......@@ -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,
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;
int ret;
......@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
struct nilfs_argv *argv, void *buf)
{
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 nilfs_vdesc *vdesc;
struct buffer_head *bh, *n;
......@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
ret = PTR_ERR(kbufs[4]);
goto out;
}
nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
nilfs = inode->i_sb->s_fs_info;
for (n = 0; n < 4; n++) {
ret = -EINVAL;
......@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
return ret;
if (argp != NULL) {
nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
nilfs = inode->i_sb->s_fs_info;
down_read(&nilfs->ns_segctor_sem);
cno = nilfs->ns_cno - 1;
up_read(&nilfs->ns_segctor_sem);
......@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
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;
int ret;
......@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
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:
return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
case NILFS_IOCTL_DELETE_CHECKPOINT:
......@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
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)
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 */
......
......@@ -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)
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)
return ERR_PTR(-ESTALE);
......
......@@ -30,7 +30,6 @@
#include <linux/blkdev.h>
#include <linux/nilfs2_fs.h>
#include "the_nilfs.h"
#include "sb.h"
#include "bmap.h"
/*
......@@ -122,7 +121,7 @@ enum {
#define NILFS_SYS_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) \
((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)
#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 */
extern int nilfs_add_link(struct dentry *, struct inode *);
extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
......@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int);
/* ioctl.c */
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 *,
void **);
/* 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 void nilfs_free_inode(struct inode *);
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 *,
struct nilfs_super_block *);
extern void nilfs_set_log_cursor(struct nilfs_super_block *,
struct the_nilfs *);
extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
int flip);
extern int nilfs_commit_super(struct nilfs_sb_info *, int);
extern int nilfs_cleanup_super(struct nilfs_sb_info *);
int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
int flip);
int nilfs_commit_super(struct super_block *sb, int flag);
int nilfs_cleanup_super(struct super_block *sb);
int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
struct nilfs_root **root);
int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
......
......@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
}
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 list_head *head = &ri->ri_used_segments;
......@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(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 list_head *head,
unsigned long *nr_salvaged_blocks)
......@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
int err = 0, err2 = 0;
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)) {
err = PTR_ERR(inode);
inode = NULL;
......@@ -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
* checkpoint
* @nilfs: nilfs object
* @sbi: nilfs_sb_info
* @sb: super block instance
* @ri: pointer to a nilfs_recovery_info
*/
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_recovery_info *ri)
{
......@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
goto failed;
if (flags & NILFS_SS_LOGEND) {
err = nilfs_recover_dsync_blocks(
nilfs, sbi, root, &dsync_blocks,
nilfs, sb, root, &dsync_blocks,
&nsalvaged_blocks);
if (unlikely(err))
goto failed;
......@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
if (nsalvaged_blocks) {
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;
}
out:
......@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
printk(KERN_ERR
"NILFS (device %s): Error roll-forwarding "
"(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;
}
......@@ -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: nilfs object
* @sbi: nilfs_sb_info
* @sb: super block instance
* @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
......@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
* %-ENOMEM - Insufficient memory available.
*/
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_root *root;
......@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 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)) {
printk(KERN_ERR
"NILFS: error loading the latest checkpoint.\n");
return err;
}
err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
err = nilfs_do_roll_forward(nilfs, sb, root, ri);
if (unlikely(err))
goto failed;
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)) {
printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n");
goto failed;
}
err = nilfs_attach_segment_constructor(sbi, root);
err = nilfs_attach_log_writer(sb, root);
if (unlikely(err))
goto failed;
set_nilfs_discontinued(nilfs);
err = nilfs_construct_segment(sbi->s_super);
nilfs_detach_segment_constructor(sbi);
err = nilfs_construct_segment(sb);
nilfs_detach_log_writer(sb);
if (unlikely(err)) {
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 {
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_immediate_flush(struct nilfs_sc_info *);
static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *,
int);
static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
#define nilfs_cnt32_gt(a, b) \
(typecheck(__u32, a) && typecheck(__u32, b) && \
......@@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb,
struct nilfs_transaction_info *ti,
int vacancy_check)
{
struct nilfs_sb_info *sbi;
struct the_nilfs *nilfs;
int ret = nilfs_prepare_segment_lock(ti);
......@@ -193,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb,
vfs_check_frozen(sb, SB_FREEZE_WRITE);
sbi = NILFS_SB(sb);
nilfs = sbi->s_nilfs;
nilfs = sb->s_fs_info;
down_read(&nilfs->ns_segctor_sem);
if (vacancy_check && nilfs_near_disk_full(nilfs)) {
up_read(&nilfs->ns_segctor_sem);
......@@ -225,8 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb,
int nilfs_transaction_commit(struct super_block *sb)
{
struct nilfs_transaction_info *ti = current->journal_info;
struct nilfs_sb_info *sbi;
struct nilfs_sc_info *sci;
struct the_nilfs *nilfs = sb->s_fs_info;
int err = 0;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
......@@ -235,16 +231,15 @@ int nilfs_transaction_commit(struct super_block *sb)
ti->ti_count--;
return 0;
}
sbi = NILFS_SB(sb);
sci = NILFS_SC(sbi);
if (sci != NULL) {
if (nilfs->ns_writer) {
struct nilfs_sc_info *sci = nilfs->ns_writer;
if (ti->ti_flags & NILFS_TI_COMMIT)
nilfs_segctor_start_timer(sci);
if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) >
sci->sc_watermark)
if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)
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;
if (ti->ti_flags & NILFS_TI_SYNC)
......@@ -257,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb)
void nilfs_transaction_abort(struct super_block *sb)
{
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);
if (ti->ti_count > 0) {
ti->ti_count--;
return;
}
up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem);
up_read(&nilfs->ns_segctor_sem);
current->journal_info = ti->ti_save;
if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
......@@ -272,9 +268,8 @@ void nilfs_transaction_abort(struct super_block *sb)
void nilfs_relax_pressure_in_lock(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
if (!sci || !sci->sc_flush_request)
return;
......@@ -294,11 +289,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)
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,
int gcflag)
{
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);
ti->ti_flags = NILFS_TI_WRITER;
......@@ -309,30 +306,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
current->journal_info = ti;
for (;;) {
down_write(&sbi->s_nilfs->ns_segctor_sem);
if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags))
down_write(&nilfs->ns_segctor_sem);
if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))
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();
}
if (gcflag)
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 the_nilfs *nilfs = sb->s_fs_info;
BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
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;
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,
......@@ -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 nilfs_inode_info *ii, *n;
......@@ -722,7 +720,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
unsigned nv = 0;
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_del_init(&ii->i_dirty);
if (force) {
......@@ -733,14 +731,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
} else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) {
set_bit(NILFS_I_QUEUED, &ii->i_state);
list_add_tail(&ii->i_dirty,
&sbi->s_dirty_files);
&nilfs->ns_dirty_files);
continue;
}
ivec[nv++] = ii;
if (nv == SC_N_INODEVEC)
break;
}
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
for (pii = ivec; nv > 0; pii++, nv--)
iput(&(*pii)->vfs_inode);
......@@ -773,24 +771,23 @@ static int nilfs_segctor_clean(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;
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);
spin_lock(&sbi->s_inode_lock);
if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci))
spin_lock(&nilfs->ns_inode_lock);
if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci))
ret++;
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
return ret;
}
static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
{
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
nilfs_mdt_clear_dirty(sci->sc_root->ifile);
nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
......@@ -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)
{
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 nilfs_checkpoint *raw_cp;
int err;
......@@ -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)
{
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct buffer_head *bh_cp;
struct nilfs_checkpoint *raw_cp;
int err;
......@@ -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)
{
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct list_head *head;
struct nilfs_inode_info *ii;
size_t ndone;
......@@ -1859,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
{
struct nilfs_segment_buffer *segbuf;
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;
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)
return ret;
}
static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
struct nilfs_sb_info *sbi)
static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
struct the_nilfs *nilfs)
{
struct nilfs_inode_info *ii, *n;
struct inode *ifile = sci->sc_root->ifile;
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
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) {
struct buffer_head *ibh;
int err;
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
err = nilfs_ifile_get_inode_block(
ifile, ii->vfs_inode.i_ino, &ibh);
if (unlikely(err)) {
nilfs_warning(sbi->s_super, __func__,
nilfs_warning(sci->sc_super, __func__,
"failed to get inode block.\n");
return err;
}
nilfs_mdt_mark_buffer_dirty(ibh);
nilfs_mdt_mark_dirty(ifile);
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
if (likely(!ii->i_bh))
ii->i_bh = ibh;
else
......@@ -1999,18 +1994,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
list_del(&ii->i_dirty);
list_add_tail(&ii->i_dirty, &sci->sc_dirty_files);
}
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
return 0;
}
static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
struct nilfs_sb_info *sbi)
static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
struct the_nilfs *nilfs)
{
struct nilfs_transaction_info *ti = current->journal_info;
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) {
if (!test_and_clear_bit(NILFS_I_UPDATED, &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,
list_del(&ii->i_dirty);
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,
*/
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 = sbi->s_nilfs;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct page *failed_page;
int err;
sci->sc_stage.scnt = NILFS_ST_INIT;
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))
goto out;
......@@ -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);
out:
nilfs_segctor_check_out_files(sci, sbi);
nilfs_segctor_drop_written_files(sci, nilfs);
return err;
failed_to_write:
......@@ -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)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
if (!sci || nilfs_doing_construction())
return;
......@@ -2259,8 +2253,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
*/
int nilfs_construct_segment(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_transaction_info *ti;
int err;
......@@ -2297,8 +2291,8 @@ int nilfs_construct_segment(struct super_block *sb)
int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
loff_t start, loff_t end)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_inode_info *ii;
struct nilfs_transaction_info ti;
int err = 0;
......@@ -2306,33 +2300,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
if (!sci)
return -EROFS;
nilfs_transaction_lock(sbi, &ti, 0);
nilfs_transaction_lock(sb, &ti, 0);
ii = NILFS_I(inode);
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) ||
nilfs_discontinued(sbi->s_nilfs)) {
nilfs_transaction_unlock(sbi);
nilfs_discontinued(nilfs)) {
nilfs_transaction_unlock(sb);
err = nilfs_segctor_sync(sci);
return err;
}
spin_lock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
!test_bit(NILFS_I_BUSY, &ii->i_state)) {
spin_unlock(&sbi->s_inode_lock);
nilfs_transaction_unlock(sbi);
spin_unlock(&nilfs->ns_inode_lock);
nilfs_transaction_unlock(sb);
return 0;
}
spin_unlock(&sbi->s_inode_lock);
spin_unlock(&nilfs->ns_inode_lock);
sci->sc_dsync_inode = ii;
sci->sc_dsync_start = start;
sci->sc_dsync_end = end;
err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
nilfs_transaction_unlock(sbi);
nilfs_transaction_unlock(sb);
return 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)
{
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
struct nilfs_super_block **sbp;
int err = 0;
......@@ -2407,11 +2400,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
nilfs_discontinued(nilfs)) {
down_write(&nilfs->ns_sem);
err = -EIO;
sbp = nilfs_prepare_super(sbi,
sbp = nilfs_prepare_super(sci->sc_super,
nilfs_sb_will_flip(nilfs));
if (likely(sbp)) {
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);
}
......@@ -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,
void **kbufs)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_transaction_info ti;
int err;
if (unlikely(!sci))
return -EROFS;
nilfs_transaction_lock(sbi, &ti, 1);
nilfs_transaction_lock(sb, &ti, 1);
err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
if (unlikely(err))
......@@ -2480,14 +2473,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
set_current_state(TASK_INTERRUPTIBLE);
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,
sci->sc_nfreesegs);
if (ret) {
printk(KERN_WARNING
"NILFS warning: error %d on discard request, "
"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,
sci->sc_freesegs = NULL;
sci->sc_nfreesegs = 0;
nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
nilfs_transaction_unlock(sbi);
nilfs_transaction_unlock(sb);
return err;
}
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;
nilfs_transaction_lock(sbi, &ti, 0);
nilfs_transaction_lock(sci->sc_super, &ti, 0);
nilfs_segctor_construct(sci, 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))
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)
......@@ -2561,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)
static int nilfs_segctor_thread(void *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;
sci->sc_timer.data = (unsigned long)current;
......@@ -2672,17 +2664,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)
/*
* 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 the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci;
sci = kzalloc(sizeof(*sci), GFP_KERNEL);
if (!sci)
return NULL;
sci->sc_sbi = sbi;
sci->sc_super = sbi->s_super;
sci->sc_super = sb;
nilfs_get_root(root);
sci->sc_root = root;
......@@ -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_watermark = NILFS_SC_DEFAULT_WATERMARK;
if (sbi->s_interval)
sci->sc_interval = sbi->s_interval;
if (sbi->s_watermark)
sci->sc_watermark = sbi->s_watermark;
if (nilfs->ns_interval)
sci->sc_interval = nilfs->ns_interval;
if (nilfs->ns_watermark)
sci->sc_watermark = nilfs->ns_watermark;
return 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.
But some tasks remain. */
do {
struct nilfs_sb_info *sbi = sci->sc_sbi;
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);
nilfs_transaction_unlock(sbi);
nilfs_transaction_unlock(sci->sc_super);
} while (ret && retrycount-- > 0);
}
......@@ -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)
{
struct nilfs_sb_info *sbi = sci->sc_sbi;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int flag;
up_write(&sbi->s_nilfs->ns_segctor_sem);
up_write(&nilfs->ns_segctor_sem);
spin_lock(&sci->sc_state_lock);
nilfs_segctor_kill_thread(sci);
......@@ -2753,9 +2744,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
WARN_ON(!list_empty(&sci->sc_copied_buffers));
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");
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));
......@@ -2763,79 +2754,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
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);
kfree(sci);
}
/**
* nilfs_attach_segment_constructor - attach a segment constructor
* @sbi: nilfs_sb_info
* nilfs_attach_log_writer - attach log writer
* @sb: super block instance
* @root: root object of the current filesystem tree
*
* nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info,
* initializes it, and starts the segment constructor.
* This allocates a log writer object, initializes it, and starts the
* log writer.
*
* Return Value: On success, 0 is returned. On error, one of the following
* negative error code is returned.
*
* %-ENOMEM - Insufficient memory available.
*/
int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
struct nilfs_root *root)
int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)
{
struct the_nilfs *nilfs = sb->s_fs_info;
int err;
if (NILFS_SC(sbi)) {
if (nilfs->ns_writer) {
/*
* This happens if the filesystem was remounted
* read/write after nilfs_error degenerated it into a
* read-only mount.
*/
nilfs_detach_segment_constructor(sbi);
nilfs_detach_log_writer(sb);
}
sbi->s_sc_info = nilfs_segctor_new(sbi, root);
if (!sbi->s_sc_info)
nilfs->ns_writer = nilfs_segctor_new(sb, root);
if (!nilfs->ns_writer)
return -ENOMEM;
err = nilfs_segctor_start_thread(NILFS_SC(sbi));
err = nilfs_segctor_start_thread(nilfs->ns_writer);
if (err) {
kfree(sbi->s_sc_info);
sbi->s_sc_info = NULL;
kfree(nilfs->ns_writer);
nilfs->ns_writer = NULL;
}
return err;
}
/**
* nilfs_detach_segment_constructor - destroy the segment constructor
* @sbi: nilfs_sb_info
* nilfs_detach_log_writer - destroy log writer
* @sb: super block instance
*
* nilfs_detach_segment_constructor() kills the segment constructor daemon,
* frees the struct nilfs_sc_info, and destroy the dirty file list.
* This kills log writer daemon, frees the log writer object, and
* 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);
down_write(&nilfs->ns_segctor_sem);
if (NILFS_SC(sbi)) {
nilfs_segctor_destroy(NILFS_SC(sbi));
sbi->s_sc_info = NULL;
if (nilfs->ns_writer) {
nilfs_segctor_destroy(nilfs->ns_writer);
nilfs->ns_writer = NULL;
}
/* Force to free the list of dirty files */
spin_lock(&sbi->s_inode_lock);
if (!list_empty(&sbi->s_dirty_files)) {
list_splice_init(&sbi->s_dirty_files, &garbage_list);
nilfs_warning(sbi->s_super, __func__,
"Non empty dirty list after the last "
"segment construction\n");
}
spin_unlock(&sbi->s_inode_lock);
spin_lock(&nilfs->ns_inode_lock);
if (!list_empty(&nilfs->ns_dirty_files)) {
list_splice_init(&nilfs->ns_dirty_files, &garbage_list);
nilfs_warning(sb, __func__,
"Hit dirty file after stopped log writer\n");
}
spin_unlock(&nilfs->ns_inode_lock);
up_write(&nilfs->ns_segctor_sem);
nilfs_dispose_list(sbi, &garbage_list, 1);
nilfs_dispose_list(nilfs, &garbage_list, 1);
}
......@@ -27,7 +27,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h>
#include "sb.h"
#include "nilfs.h"
struct nilfs_root;
......@@ -88,7 +88,6 @@ struct nilfs_segsum_pointer {
/**
* struct nilfs_sc_info - Segment constructor information
* @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_nblk_inc: Block count of current generation
* @sc_dirty_files: List of files to be written
......@@ -131,7 +130,6 @@ struct nilfs_segsum_pointer {
*/
struct nilfs_sc_info {
struct super_block *sc_super;
struct nilfs_sb_info *sc_sbi;
struct nilfs_root *sc_root;
unsigned long sc_nblk_inc;
......@@ -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 *,
void **);
int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
struct nilfs_root *root);
extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root);
void nilfs_detach_log_writer(struct super_block *sb);
/* recovery.c */
extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t,
struct buffer_head **, int);
extern int nilfs_search_super_root(struct the_nilfs *,
struct nilfs_recovery_info *);
extern int nilfs_salvage_orphan_logs(struct the_nilfs *,
struct nilfs_sb_info *,
struct nilfs_recovery_info *);
int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb,
struct nilfs_recovery_info *ri);
extern void nilfs_dispose_segment_list(struct list_head *);
#endif /* _NILFS_SEGMENT_H */
......@@ -43,7 +43,6 @@
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/parser.h>
#include <linux/random.h>
#include <linux/crc32.h>
#include <linux/vfs.h>
#include <linux/writeback.h>
......@@ -72,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep;
struct kmem_cache *nilfs_segbuf_cachep;
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 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;
down_write(&nilfs->ns_sem);
if (!(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)) {
sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
if (sbp[1])
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);
......@@ -109,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi)
void nilfs_error(struct super_block *sb, const char *function,
const char *fmt, ...)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sb->s_fs_info;
struct va_format vaf;
va_list args;
......@@ -124,15 +123,15 @@ void nilfs_error(struct super_block *sb, const char *function,
va_end(args);
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");
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",
sb->s_id);
}
......@@ -189,14 +188,14 @@ void nilfs_destroy_inode(struct inode *inode)
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;
retry:
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],
WRITE_SYNC | WRITE_FLUSH_FUA);
} else {
......@@ -263,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp,
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)
{
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp = nilfs->ns_sbp;
/* 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,
memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
} else {
printk(KERN_CRIT "NILFS: superblock broke on dev %s\n",
sbi->s_super->s_id);
sb->s_id);
return NULL;
}
} else if (sbp[1] &&
......@@ -290,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
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;
time_t t;
......@@ -312,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
nilfs->ns_sbsize));
}
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
* @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 will set "clean" flag (i.e. NILFS_VALID_FS) unless the
* 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;
int flag = NILFS_SB_COMMIT;
int ret = -EIO;
sbp = nilfs_prepare_super(sbi, 0);
sbp = nilfs_prepare_super(sb, 0);
if (sbp) {
sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state);
nilfs_set_log_cursor(sbp[0], sbi->s_nilfs);
sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
nilfs_set_log_cursor(sbp[0], nilfs);
if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) {
/*
* make the "clean" flag also to the opposite
......@@ -342,21 +342,20 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
sbp[1]->s_state = sbp[0]->s_state;
flag = NILFS_SB_COMMIT_ALL;
}
ret = nilfs_commit_super(sbi, flag);
ret = nilfs_commit_super(sb, flag);
}
return ret;
}
static void nilfs_put_super(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
nilfs_detach_segment_constructor(sbi);
nilfs_detach_log_writer(sb);
if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem);
nilfs_cleanup_super(sbi);
nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem);
}
......@@ -365,15 +364,12 @@ static void nilfs_put_super(struct super_block *sb)
iput(nilfs->ns_dat);
destroy_nilfs(nilfs);
sbi->s_super = NULL;
sb->s_fs_info = NULL;
kfree(sbi);
}
static int nilfs_sync_fs(struct super_block *sb, int wait)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp;
int err = 0;
......@@ -383,10 +379,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
down_write(&nilfs->ns_sem);
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)) {
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);
......@@ -394,10 +390,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
return err;
}
int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
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_checkpoint *raw_cp;
struct buffer_head *bh_cp;
......@@ -426,7 +422,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
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);
if (err)
goto failed_bh;
......@@ -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)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
int err;
if (sb->s_flags & MS_RDONLY)
......@@ -459,21 +454,20 @@ static int nilfs_freeze(struct super_block *sb)
/* Mark super block clean */
down_write(&nilfs->ns_sem);
err = nilfs_cleanup_super(sbi);
err = nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem);
return err;
}
static int nilfs_unfreeze(struct super_block *sb)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
if (sb->s_flags & MS_RDONLY)
return 0;
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, false);
nilfs_setup_super(sb, false);
up_write(&nilfs->ns_sem);
return 0;
}
......@@ -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)
{
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;
if (!nilfs_test_opt(sbi, BARRIER))
if (!nilfs_test_opt(nilfs, BARRIER))
seq_puts(seq, ",nobarrier");
if (root->cno != NILFS_CPTREE_CURRENT_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");
if (nilfs_test_opt(sbi, ERRORS_CONT))
if (nilfs_test_opt(nilfs, ERRORS_CONT))
seq_puts(seq, ",errors=continue");
if (nilfs_test_opt(sbi, STRICT_ORDER))
if (nilfs_test_opt(nilfs, STRICT_ORDER))
seq_puts(seq, ",order=strict");
if (nilfs_test_opt(sbi, NORECOVERY))
if (nilfs_test_opt(nilfs, NORECOVERY))
seq_puts(seq, ",norecovery");
if (nilfs_test_opt(sbi, DISCARD))
if (nilfs_test_opt(nilfs, DISCARD))
seq_puts(seq, ",discard");
return 0;
......@@ -594,7 +588,7 @@ static match_table_t tokens = {
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;
substring_t args[MAX_OPT_ARGS];
......@@ -609,29 +603,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
token = match_token(p, tokens, args);
switch (token) {
case Opt_barrier:
nilfs_set_opt(sbi, BARRIER);
nilfs_set_opt(nilfs, BARRIER);
break;
case Opt_nobarrier:
nilfs_clear_opt(sbi, BARRIER);
nilfs_clear_opt(nilfs, BARRIER);
break;
case Opt_order:
if (strcmp(args[0].from, "relaxed") == 0)
/* Ordered data semantics */
nilfs_clear_opt(sbi, STRICT_ORDER);
nilfs_clear_opt(nilfs, STRICT_ORDER);
else if (strcmp(args[0].from, "strict") == 0)
/* Strict in-order semantics */
nilfs_set_opt(sbi, STRICT_ORDER);
nilfs_set_opt(nilfs, STRICT_ORDER);
else
return 0;
break;
case Opt_err_panic:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC);
nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC);
break;
case Opt_err_ro:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO);
nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO);
break;
case Opt_err_cont:
nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT);
nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT);
break;
case Opt_snapshot:
if (is_remount) {
......@@ -642,13 +636,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
}
break;
case Opt_norecovery:
nilfs_set_opt(sbi, NORECOVERY);
nilfs_set_opt(nilfs, NORECOVERY);
break;
case Opt_discard:
nilfs_set_opt(sbi, DISCARD);
nilfs_set_opt(nilfs, DISCARD);
break;
case Opt_nodiscard:
nilfs_clear_opt(sbi, DISCARD);
nilfs_clear_opt(nilfs, DISCARD);
break;
default:
printk(KERN_ERR
......@@ -660,22 +654,24 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
}
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)
{
sbi->s_mount_opt =
struct the_nilfs *nilfs = sb->s_fs_info;
nilfs->ns_mount_opt =
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;
int max_mnt_count;
int mnt_count;
/* nilfs->ns_sem must be locked by the caller. */
sbp = nilfs_prepare_super(sbi, 0);
sbp = nilfs_prepare_super(sb, 0);
if (!sbp)
return -EIO;
......@@ -706,7 +702,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
/* synchronize sbp[1] with sbp[0] */
if (sbp[1])
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,
......@@ -727,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb,
struct nilfs_super_block *sbp,
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);
......@@ -736,12 +732,12 @@ int nilfs_store_magic_and_option(struct super_block *sb,
sb->s_flags |= MS_NOATIME;
#endif
nilfs_set_default_options(sbi, sbp);
nilfs_set_default_options(sb, sbp);
sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid);
sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid);
sbi->s_interval = le32_to_cpu(sbp->s_c_interval);
sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max);
nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid);
nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid);
nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval);
nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max);
return !parse_options(data, sb, 0) ? -EINVAL : 0 ;
}
......@@ -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,
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;
int ret;
......@@ -840,7 +836,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
goto out;
}
ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root);
ret = nilfs_attach_checkpoint(s, cno, false, &root);
if (ret) {
printk(KERN_ERR "NILFS: error loading snapshot "
"(checkpoint number=%llu).\n",
......@@ -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)
{
struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_root *root;
struct inode *inode;
struct dentry *dentry;
......@@ -887,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
return true; /* protect recent checkpoints */
ret = false;
root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
root = nilfs_lookup_root(nilfs, cno);
if (root) {
inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
if (inode) {
......@@ -917,43 +913,21 @@ static int
nilfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct the_nilfs *nilfs;
struct nilfs_sb_info *sbi;
struct nilfs_root *fsroot;
struct backing_dev_info *bdi;
__u64 cno;
int err;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
nilfs = alloc_nilfs(sb->s_bdev);
if (!nilfs)
return -ENOMEM;
sb->s_fs_info = sbi;
sbi->s_super = sb;
nilfs = alloc_nilfs(sb->s_bdev);
if (!nilfs) {
err = -ENOMEM;
goto failed_sbi;
}
sbi->s_nilfs = nilfs;
sb->s_fs_info = nilfs;
err = init_nilfs(nilfs, sbi, (char *)data);
err = init_nilfs(nilfs, sb, (char *)data);
if (err)
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_export_op = &nilfs_export_ops;
sb->s_root = NULL;
......@@ -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;
sb->s_bdi = bdi ? : &default_backing_dev_info;
err = load_nilfs(nilfs, sbi);
err = load_nilfs(nilfs, sb);
if (err)
goto failed_nilfs;
cno = nilfs_last_cno(nilfs);
err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot);
err = nilfs_attach_checkpoint(sb, cno, true, &fsroot);
if (err) {
printk(KERN_ERR "NILFS: error loading last checkpoint "
"(checkpoint number=%llu).\n", (unsigned long long)cno);
......@@ -975,7 +949,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
}
if (!(sb->s_flags & MS_RDONLY)) {
err = nilfs_attach_segment_constructor(sbi, fsroot);
err = nilfs_attach_log_writer(sb, fsroot);
if (err)
goto failed_checkpoint;
}
......@@ -988,14 +962,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
if (!(sb->s_flags & MS_RDONLY)) {
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, true);
nilfs_setup_super(sb, true);
up_write(&nilfs->ns_sem);
}
return 0;
failed_segctor:
nilfs_detach_segment_constructor(sbi);
nilfs_detach_log_writer(sb);
failed_checkpoint:
nilfs_put_root(fsroot);
......@@ -1007,23 +981,18 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
failed_nilfs:
destroy_nilfs(nilfs);
failed_sbi:
sb->s_fs_info = NULL;
kfree(sbi);
return err;
}
static int nilfs_remount(struct super_block *sb, int *flags, char *data)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
struct the_nilfs *nilfs = sb->s_fs_info;
unsigned long old_sb_flags;
unsigned long old_mount_opt;
int err;
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)) {
err = -EINVAL;
......@@ -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))
goto out;
if (*flags & MS_RDONLY) {
/* Shutting down the segment constructor */
nilfs_detach_segment_constructor(sbi);
/* Shutting down log writer */
nilfs_detach_log_writer(sb);
sb->s_flags |= MS_RDONLY;
/*
......@@ -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.
*/
down_write(&nilfs->ns_sem);
nilfs_cleanup_super(sbi);
nilfs_cleanup_super(sb);
up_write(&nilfs->ns_sem);
} else {
__u64 features;
......@@ -1079,12 +1048,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
sb->s_flags &= ~MS_RDONLY;
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)
goto restore_opts;
down_write(&nilfs->ns_sem);
nilfs_setup_super(sbi, true);
nilfs_setup_super(sb, true);
up_write(&nilfs->ns_sem);
}
out:
......@@ -1092,13 +1061,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
restore_opts:
sb->s_flags = old_sb_flags;
sbi->s_mount_opt = old_mount_opt;
nilfs->ns_mount_opt = old_mount_opt;
return err;
}
struct nilfs_super_data {
struct block_device *bdev;
struct nilfs_sb_info *sbi;
__u64 cno;
int flags;
};
......
......@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <linux/random.h>
#include <linux/crc32.h>
#include "nilfs.h"
#include "segment.h"
......@@ -75,7 +76,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
nilfs->ns_bdev = bdev;
atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem);
INIT_LIST_HEAD(&nilfs->ns_dirty_files);
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);
nilfs->ns_cptree = RB_ROOT;
spin_lock_init(&nilfs->ns_cptree_lock);
......@@ -197,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs,
/**
* load_nilfs - load and recover the nilfs
* @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,
* attaches the last segment, and does recovery if needed.
* 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;
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 valid_fs = nilfs_valid_fs(nilfs);
int err;
......@@ -271,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
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)) {
printk(KERN_ERR "NILFS: error loading super root.\n");
goto failed;
......@@ -283,7 +287,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
if (s_flags & MS_RDONLY) {
__u64 features;
if (nilfs_test_opt(sbi, NORECOVERY)) {
if (nilfs_test_opt(nilfs, NORECOVERY)) {
printk(KERN_INFO "NILFS: norecovery option specified. "
"skipping roll-forward recovery\n");
goto skip_recovery;
......@@ -304,21 +308,21 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
err = -EROFS;
goto failed_unload;
}
sbi->s_super->s_flags &= ~MS_RDONLY;
} else if (nilfs_test_opt(sbi, NORECOVERY)) {
sb->s_flags &= ~MS_RDONLY;
} else if (nilfs_test_opt(nilfs, NORECOVERY)) {
printk(KERN_ERR "NILFS: recovery cancelled because norecovery "
"option was specified for a read/write mount\n");
err = -EINVAL;
goto failed_unload;
}
err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri);
err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
if (err)
goto failed_unload;
down_write(&nilfs->ns_sem);
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);
if (err) {
......@@ -330,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
skip_recovery:
nilfs_clear_recovery_info(&ri);
sbi->s_super->s_flags = s_flags;
sb->s_flags = s_flags;
return 0;
scan_error:
......@@ -344,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
failed:
nilfs_clear_recovery_info(&ri);
sbi->s_super->s_flags = s_flags;
sb->s_flags = s_flags;
return err;
}
......@@ -475,10 +479,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
return -EIO;
}
printk(KERN_WARNING
"NILFS warning: unable to read primary superblock\n");
} else if (!sbp[1])
"NILFS warning: unable to read primary superblock "
"(blocksize = %d)\n", blocksize);
} else if (!sbp[1]) {
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
......@@ -505,7 +512,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
if (!valid[!swp])
printk(KERN_WARNING "NILFS warning: broken superblock. "
"using spare superblock.\n");
"using spare superblock (blocksize = %d).\n", blocksize);
if (swp)
nilfs_swap_super_block(nilfs);
......@@ -519,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
/**
* init_nilfs - initialize a NILFS instance.
* @nilfs: the_nilfs structure
* @sbi: nilfs_sb_info
* @sb: super block
* @data: mount options
*
......@@ -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
* 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;
int blocksize;
int err;
......@@ -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 = blocksize;
get_random_bytes(&nilfs->ns_next_generation,
sizeof(nilfs->ns_next_generation));
err = nilfs_store_disk_layout(nilfs, sbp);
if (err)
goto failed_sbh;
......
......@@ -31,7 +31,8 @@
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <linux/slab.h>
#include "sb.h"
struct nilfs_sc_info;
/* the_nilfs struct */
enum {
......@@ -65,13 +66,23 @@ enum {
* @ns_last_cno: checkpoint number of the latest segment
* @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_segctor_sem: segment constructor semaphore
* @ns_writer: log writer
* @ns_segctor_sem: semaphore protecting log write
* @ns_dat: DAT file inode
* @ns_cpfile: checkpoint file inode
* @ns_sufile: segusage file inode
* @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
* @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_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: block size
* @ns_nsegments: number of segments in filesystem
......@@ -131,6 +142,7 @@ struct the_nilfs {
u64 ns_prot_seq;
u64 ns_prev_seq;
struct nilfs_sc_info *ns_writer;
struct rw_semaphore ns_segctor_sem;
/*
......@@ -145,9 +157,25 @@ struct the_nilfs {
struct rb_root ns_cptree;
spinlock_t ns_cptree_lock;
/* Dirty inode list */
struct list_head ns_dirty_files;
spinlock_t ns_inode_lock;
/* GC inode list */
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) */
unsigned int ns_blocksize_bits;
unsigned int ns_blocksize;
......@@ -180,6 +208,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
THE_NILFS_FNS(GC_RUNNING, gc_running)
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
* @cno: checkpoint number
......@@ -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);
struct the_nilfs *alloc_nilfs(struct block_device *bdev);
void destroy_nilfs(struct the_nilfs *nilfs);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data);
int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb);
int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_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_find_or_create_root(struct the_nilfs *nilfs,
__u64 cno);
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 *);
void nilfs_fall_back_super_block(struct the_nilfs *);
void nilfs_swap_super_block(struct the_nilfs *);
......
......@@ -23,6 +23,7 @@
#define XENFS_SUPER_MAGIC 0xabba1974
#define EXT4_SUPER_MAGIC 0xEF53
#define BTRFS_SUPER_MAGIC 0x9123683E
#define NILFS_SUPER_MAGIC 0x3434
#define HPFS_SUPER_MAGIC 0xf995e849
#define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6
......
......@@ -40,26 +40,7 @@
#include <linux/types.h>
#include <linux/ioctl.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 */
#include <linux/magic.h>
#define NILFS_INODE_BMAP_SIZE 7
......@@ -236,8 +217,10 @@ struct nilfs_super_block {
* 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.
*/
#define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT 0x00000001ULL
#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
/*
......@@ -260,7 +243,6 @@ struct nilfs_super_block {
#define NILFS_USER_INO 11 /* Fisrt user's file inode number */
#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
a full segment */
......@@ -346,17 +328,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen)
{
unsigned len = le16_to_cpu(dlen);
#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
if (len == NILFS_MAX_REC_LEN)
return 1 << 16;
#endif
return len;
}
static inline __le16 nilfs_rec_len_to_disk(unsigned len)
{
#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
if (len == (1 << 16))
return cpu_to_le16(NILFS_MAX_REC_LEN);
else if (len > (1 << 16))
BUG();
#endif
return cpu_to_le16(len);
}
......@@ -525,7 +511,7 @@ struct nilfs_checkpoint {
__le64 cp_create;
__le64 cp_nblk_inc;
__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.
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