forked from Minki/linux
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
This commit is contained in:
commit
5bab188a31
@ -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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
"%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 @@
|
|||||||
#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)
|
|||||||
/*
|
/*
|
||||||
* 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 *,
|
|||||||
__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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 @@ got_it:
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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 {
|
|||||||
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 = {
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
*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)
|
|||||||
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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
|
|
||||||
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
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
#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)
|
|||||||
|
|
||||||
#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);
|
|||||||
|
|
||||||
/* 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 *,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
/**
|
/**
|
||||||
* 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,
|
|||||||
* %-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,
|
|||||||
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. "
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
} 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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
} 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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(&sbi->s_inode_lock);
|
spin_unlock(&nilfs->ns_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 @@
|
|||||||
#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 {
|
|||||||
/**
|
/**
|
||||||
* 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 {
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
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 @@
|
|||||||
#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;
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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 = {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@ skip_mount_setup:
|
|||||||
/* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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);
|
err = init_nilfs(nilfs, sb, (char *)data);
|
||||||
if (!nilfs) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto failed_sbi;
|
|
||||||
}
|
|
||||||
sbi->s_nilfs = nilfs;
|
|
||||||
|
|
||||||
err = init_nilfs(nilfs, sbi, (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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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)
|
|||||||
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,
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
/**
|
/**
|
||||||
* 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,
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
* @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 {
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
#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 @@
|
|||||||
|
|
||||||
#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 {
|
|||||||
* 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 {
|
|||||||
#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)
|
|||||||
{
|
{
|
||||||
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 {
|
|||||||
__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,
|
||||||
|
Loading…
Reference in New Issue
Block a user