summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 22:33:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 22:33:38 -0700
commit5bab188a316718a26346cdb25c4cc6b319f8f907 (patch)
tree0316a8294b9709a55b0c5b2f1c1c0d3793d35c01 /fs
parenta8c91da549f625d0600d5bd7e1831066b55edf0d (diff)
parent4d3cf1bc557dc8b88e1cabf1980b3baa3380a641 (diff)
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
Diffstat (limited to 'fs')
-rw-r--r--fs/nilfs2/alloc.c12
-rw-r--r--fs/nilfs2/bmap.c12
-rw-r--r--fs/nilfs2/bmap.h3
-rw-r--r--fs/nilfs2/btree.c6
-rw-r--r--fs/nilfs2/dir.c5
-rw-r--r--fs/nilfs2/direct.c4
-rw-r--r--fs/nilfs2/file.c4
-rw-r--r--fs/nilfs2/inode.c83
-rw-r--r--fs/nilfs2/ioctl.c115
-rw-r--r--fs/nilfs2/mdt.h2
-rw-r--r--fs/nilfs2/namei.c2
-rw-r--r--fs/nilfs2/nilfs.h33
-rw-r--r--fs/nilfs2/recovery.c32
-rw-r--r--fs/nilfs2/sb.h85
-rw-r--r--fs/nilfs2/segment.c258
-rw-r--r--fs/nilfs2/segment.h14
-rw-r--r--fs/nilfs2/super.c214
-rw-r--r--fs/nilfs2/the_nilfs.c44
-rw-r--r--fs/nilfs2/the_nilfs.h51
19 files changed, 503 insertions, 476 deletions
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
index d7fd696e595c..0a0a66d98cce 100644
--- a/fs/nilfs2/alloc.c
+++ b/fs/nilfs2/alloc.c
@@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr);
-
- nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+ else
+ nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_bh->b_page);
kunmap(req->pr_desc_bh->b_page);
@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
group_offset, bitmap))
printk(KERN_WARNING "%s: entry number %llu already freed\n",
__func__, (unsigned long long)req->pr_entry_nr);
-
- nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+ else
+ nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
kunmap(req->pr_bitmap_bh->b_page);
kunmap(req->pr_desc_bh->b_page);
@@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
for (j = i, n = 0;
(j < nitems) && nilfs_palloc_group_is_in(inode, group,
entry_nrs[j]);
- j++, n++) {
+ j++) {
nilfs_palloc_group(inode, entry_nrs[j], &group_offset);
if (!nilfs_clear_bit_atomic(
nilfs_mdt_bgl_lock(inode, group),
@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
"%s: entry number %llu already freed\n",
__func__,
(unsigned long long)entry_nrs[j]);
+ } else {
+ n++;
}
}
nilfs_palloc_group_desc_add_entries(inode, group, desc, n);
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index 3ee67c67cc52..4723f04e9b12 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include "nilfs.h"
#include "bmap.h"
-#include "sb.h"
#include "btree.h"
#include "direct.h"
#include "btnode.h"
@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
/*
* Internal use only
*/
-
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
-{
- inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
-{
- inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
const struct buffer_head *bh)
{
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h
index bde1c0aa2e15..40d9f453d31c 100644
--- a/fs/nilfs2/bmap.h
+++ b/fs/nilfs2/bmap.h
@@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
-
/* Assume that bmap semaphore is locked. */
static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 300c2bc00c3f..d451ae0e0bf3 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
if (ret < 0)
goto out;
nilfs_btree_commit_insert(btree, path, level, key, ptr);
- nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+ nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
out:
nilfs_btree_free_path(path);
@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
if (ret < 0)
goto out;
nilfs_btree_commit_delete(btree, path, level, dat);
- nilfs_bmap_sub_blocks(btree, stats.bs_nblocks);
+ nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
out:
nilfs_btree_free_path(path);
@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
return ret;
nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
di, ni, bh);
- nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+ nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
return 0;
}
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 9d45773b79e6..3a1923943b14 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
nilfs_commit_chunk(page, mapping, from, to);
nilfs_put_page(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
}
/*
@@ -531,7 +530,6 @@ got_it:
nilfs_set_de_type(de, inode);
nilfs_commit_chunk(page, page->mapping, from, to);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
nilfs_mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
dir->inode = 0;
nilfs_commit_chunk(page, mapping, from, to);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-/* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */
out:
nilfs_put_page(page);
return err;
@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = {
.readdir = nilfs_readdir,
.unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = nilfs_ioctl,
+ .compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */
.fsync = nilfs_sync_file,
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
index 324d80c57518..82f4865e86dd 100644
--- a/fs/nilfs2/direct.c
+++ b/fs/nilfs2/direct.c
@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
if (NILFS_BMAP_USE_VBN(bmap))
nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
- nilfs_bmap_add_blocks(bmap, 1);
+ nilfs_inode_add_blocks(bmap->b_inode, 1);
}
return ret;
}
@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
if (!ret) {
nilfs_bmap_commit_end_ptr(bmap, &req, dat);
nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
- nilfs_bmap_sub_blocks(bmap, 1);
+ nilfs_inode_sub_blocks(bmap->b_inode, 1);
}
return ret;
}
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 2f560c9fb808..93589fccdd97 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
struct nilfs_transaction_info ti;
int ret;
- if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs)))
+ if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
return VM_FAULT_SIGBUS; /* -ENOSPC */
lock_page(page);
@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = {
.aio_write = generic_file_aio_write,
.unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = nilfs_ioctl,
+ .compat_ioctl = nilfs_compat_ioctl,
#endif /* CONFIG_COMPAT */
.mmap = nilfs_file_mmap,
.open = generic_file_open,
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 2fd440d8d6b8..d5625be236a8 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -41,6 +41,24 @@ struct nilfs_iget_args {
int for_gc;
};
+void nilfs_inode_add_blocks(struct inode *inode, int n)
+{
+ struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+ inode_add_bytes(inode, (1 << inode->i_blkbits) * n);
+ if (root)
+ atomic_add(n, &root->blocks_count);
+}
+
+void nilfs_inode_sub_blocks(struct inode *inode, int n)
+{
+ struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+ inode_sub_bytes(inode, (1 << inode->i_blkbits) * n);
+ if (root)
+ atomic_sub(n, &root->blocks_count);
+}
+
/**
* nilfs_get_block() - get a file block on the filesystem (callback function)
* @inode - inode struct of the target file
@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = {
struct inode *nilfs_new_inode(struct inode *dir, int mode)
{
struct super_block *sb = dir->i_sb;
- struct nilfs_sb_info *sbi = NILFS_SB(sb);
+ struct the_nilfs *nilfs = sb->s_fs_info;
struct inode *inode;
struct nilfs_inode_info *ii;
struct nilfs_root *root;
@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
/* No lock is needed; iget() ensures it. */
}
- ii->i_flags = NILFS_I(dir)->i_flags;
- if (S_ISLNK(mode))
- ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL);
- if (!S_ISDIR(mode))
- ii->i_flags &= ~NILFS_DIRSYNC_FL;
+ ii->i_flags = nilfs_mask_flags(
+ mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
/* ii->i_file_acl = 0; */
/* ii->i_dir_acl = 0; */
ii->i_dir_start_lookup = 0;
nilfs_set_inode_flags(inode);
- spin_lock(&sbi->s_next_gen_lock);
- inode->i_generation = sbi->s_next_generation++;
- spin_unlock(&sbi->s_next_gen_lock);
+ spin_lock(&nilfs->ns_next_gen_lock);
+ inode->i_generation = nilfs->ns_next_generation++;
+ spin_unlock(&nilfs->ns_next_gen_lock);
insert_inode_hash(inode);
err = nilfs_init_acl(inode, dir);
@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode)
inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
S_DIRSYNC);
- if (flags & NILFS_SYNC_FL)
+ if (flags & FS_SYNC_FL)
inode->i_flags |= S_SYNC;
- if (flags & NILFS_APPEND_FL)
+ if (flags & FS_APPEND_FL)
inode->i_flags |= S_APPEND;
- if (flags & NILFS_IMMUTABLE_FL)
+ if (flags & FS_IMMUTABLE_FL)
inode->i_flags |= S_IMMUTABLE;
-#ifndef NILFS_ATIME_DISABLE
- if (flags & NILFS_NOATIME_FL)
-#endif
+ if (flags & FS_NOATIME_FL)
inode->i_flags |= S_NOATIME;
- if (flags & NILFS_DIRSYNC_FL)
+ if (flags & FS_DIRSYNC_FL)
inode->i_flags |= S_DIRSYNC;
mapping_set_gfp_mask(inode->i_mapping,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb,
struct nilfs_root *root, unsigned long ino,
struct inode *inode)
{
- struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+ struct the_nilfs *nilfs = sb->s_fs_info;
struct buffer_head *bh;
struct nilfs_inode *raw_inode;
int err;
@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode)
struct nilfs_transaction_info ti;
struct super_block *sb = inode->i_sb;
struct nilfs_inode_info *ii = NILFS_I(inode);
+ int ret;
if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
if (inode->i_data.nrpages)
@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode)
nilfs_mark_inode_dirty(inode);
end_writeback(inode);
- nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
- atomic_dec(&ii->i_root->inodes_count);
+ ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
+ if (!ret)
+ atomic_dec(&ii->i_root->inodes_count);
nilfs_clear_inode(inode);
@@ -792,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
{
- struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_inode_info *ii = NILFS_I(inode);
int err;
- spin_lock(&sbi->s_inode_lock);
+ spin_lock(&nilfs->ns_inode_lock);
if (ii->i_bh == NULL) {
- spin_unlock(&sbi->s_inode_lock);
+ spin_unlock(&nilfs->ns_inode_lock);
err = nilfs_ifile_get_inode_block(ii->i_root->ifile,
inode->i_ino, pbh);
if (unlikely(err))
return err;
- spin_lock(&sbi->s_inode_lock);
+ spin_lock(&nilfs->ns_inode_lock);
if (ii->i_bh == NULL)
ii->i_bh = *pbh;
else {
@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
*pbh = ii->i_bh;
get_bh(*pbh);
- spin_unlock(&sbi->s_inode_lock);
+ spin_unlock(&nilfs->ns_inode_lock);
return 0;
}
int nilfs_inode_dirty(struct inode *inode)
{
struct nilfs_inode_info *ii = NILFS_I(inode);
- struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
int ret = 0;
if (!list_empty(&ii->i_dirty)) {
- spin_lock(&sbi->s_inode_lock);
+ spin_lock(&nilfs->ns_inode_lock);
ret = test_bit(NILFS_I_DIRTY, &ii->i_state) ||
test_bit(NILFS_I_BUSY, &ii->i_state);
- spin_unlock(&sbi->s_inode_lock);
+ spin_unlock(&nilfs->ns_inode_lock);
}
return ret;
}
int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
{
- struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
struct nilfs_inode_info *ii = NILFS_I(inode);
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
- atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks);
+ atomic_add(nr_dirty, &nilfs->ns_ndirtyblks);
if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state))
return 0;
- spin_lock(&sbi->s_inode_lock);
+ spin_lock(&nilfs->ns_inode_lock);
if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
!test_bit(NILFS_I_BUSY, &ii->i_state)) {
/* Because this routine may race with nilfs_dispose_list(),
@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) {
/* This will happen when somebody is freeing
this inode. */
- nilfs_warning(sbi->s_super, __func__,
+ nilfs_warning(inode->i_sb, __func__,
"cannot get inode (ino=%lu)\n",
inode->i_ino);
- spin_unlock(&sbi->s_inode_lock);
+ spin_unlock(&nilfs->ns_inode_lock);
return -EINVAL; /* NILFS_I_DIRTY may remain for
freeing inode */
}
list_del(&ii->i_dirty);
- list_add_tail(&ii->i_dirty, &sbi->s_dirty_files);
+ list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files);
set_bit(NILFS_I_QUEUED, &ii->i_state);
}
- spin_unlock(&sbi->s_inode_lock);
+ spin_unlock(&nilfs->ns_inode_lock);
return 0;
}
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 496738963fdb..95c04c2f2b3e 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -26,7 +26,9 @@
#include <linux/capability.h> /* capable() */
#include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
#include <linux/vmalloc.h>
+#include <linux/compat.h> /* compat_ptr() */
#include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */
+#include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h>
#include "nilfs.h"
#include "segment.h"
@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
return ret;
}
+static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
+{
+ unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
+
+ return put_user(flags, (int __user *)argp);
+}
+
+static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
+ void __user *argp)
+{
+ struct nilfs_transaction_info ti;
+ unsigned int flags, oldflags;
+ int ret;
+
+ if (!is_owner_or_cap(inode))
+ return -EACCES;
+
+ if (get_user(flags, (int __user *)argp))
+ return -EFAULT;
+
+ ret = mnt_want_write(filp->f_path.mnt);
+ if (ret)
+ return ret;
+
+ flags = nilfs_mask_flags(inode->i_mode, flags);
+
+ mutex_lock(&inode->i_mutex);
+
+ oldflags = NILFS_I(inode)->i_flags;
+
+ /*
+ * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
+ * relevant capability.
+ */
+ ret = -EPERM;
+ if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
+ !capable(CAP_LINUX_IMMUTABLE))
+ goto out;
+
+ ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
+ if (ret)
+ goto out;
+
+ NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
+ (flags & FS_FL_USER_MODIFIABLE);
+
+ nilfs_set_inode_flags(inode);
+ inode->i_ctime = CURRENT_TIME;
+ if (IS_SYNC(inode))
+ nilfs_set_transaction_flag(NILFS_TI_SYNC);
+
+ nilfs_mark_inode_dirty(inode);
+ ret = nilfs_transaction_commit(inode->i_sb);
+out:
+ mutex_unlock(&inode->i_mutex);
+ mnt_drop_write(filp->f_path.mnt);
+ return ret;
+}
+
+static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
+{
+ return put_user(inode->i_generation, (int __user *)argp);
+}
+
static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
- struct inode *cpfile = nilfs->ns_cpfile;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_transaction_info ti;
struct nilfs_cpmode cpmode;
int ret;
@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_change_cpmode(
- cpfile, cpmode.cm_cno, cpmode.cm_mode);
+ nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
if (unlikely(ret < 0))
nilfs_transaction_abort(inode->i_sb);
else
@@ -137,7 +202,7 @@ static int
nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
- struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_transaction_info ti;
__u64 cno;
int ret;
@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
goto out;
nilfs_transaction_begin(inode->i_sb, &ti, 0);
- ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
+ ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
if (unlikely(ret < 0))
nilfs_transaction_abort(inode->i_sb);
else
@@ -180,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_cpstat cpstat;
int ret;
@@ -211,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_sustat sustat;
int ret;
@@ -267,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_argv argv;
int ret;
@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
struct nilfs_argv *argv, void *buf)
{
size_t nmembs = argv->v_nmembs;
- struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+ struct the_nilfs *nilfs = sb->s_fs_info;
struct inode *inode;
struct nilfs_vdesc *vdesc;
struct buffer_head *bh, *n;
@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
ret = PTR_ERR(kbufs[4]);
goto out;
}
- nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ nilfs = inode->i_sb->s_fs_info;
for (n = 0; n < 4; n++) {
ret = -EINVAL;
@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
return ret;
if (argp != NULL) {
- nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ nilfs = inode->i_sb->s_fs_info;
down_read(&nilfs->ns_segctor_sem);
cno = nilfs->ns_cno - 1;
up_read(&nilfs->ns_segctor_sem);
@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
void *, size_t, size_t))
{
- struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+ struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
struct nilfs_argv argv;
int ret;
@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
switch (cmd) {
+ case FS_IOC_GETFLAGS:
+ return nilfs_ioctl_getflags(inode, argp);
+ case FS_IOC_SETFLAGS:
+ return nilfs_ioctl_setflags(inode, filp, argp);
+ case FS_IOC_GETVERSION:
+ return nilfs_ioctl_getversion(inode, argp);
case NILFS_IOCTL_CHANGE_CPMODE:
return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
case NILFS_IOCTL_DELETE_CHECKPOINT:
@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -ENOTTY;
}
}
+
+#ifdef CONFIG_COMPAT
+long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case FS_IOC32_GETFLAGS:
+ cmd = FS_IOC_GETFLAGS;
+ break;
+ case FS_IOC32_SETFLAGS:
+ cmd = FS_IOC_SETFLAGS;
+ break;
+ case FS_IOC32_GETVERSION:
+ cmd = FS_IOC_GETVERSION;
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h
index b13734bf3521..ed68563ec708 100644
--- a/fs/nilfs2/mdt.h
+++ b/fs/nilfs2/mdt.h
@@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode)
static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode)
{
- return NILFS_SB(inode->i_sb)->s_nilfs;
+ return inode->i_sb->s_fs_info;
}
/* Default GFP flags using highmem */
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 161791d26458..546849b3e88f 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
return ERR_PTR(-ESTALE);
- root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+ root = nilfs_lookup_root(sb->s_fs_info, cno);
if (!root)
return ERR_PTR(-ESTALE);
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 777e8fd04304..856e8e4e0b74 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -30,7 +30,6 @@
#include <linux/blkdev.h>
#include <linux/nilfs2_fs.h>
#include "the_nilfs.h"
-#include "sb.h"
#include "bmap.h"
/*
@@ -122,7 +121,7 @@ enum {
#define NILFS_SYS_INO_BITS \
((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS)
-#define NILFS_FIRST_INO(sb) (NILFS_SB(sb)->s_nilfs->ns_first_ino)
+#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
#define NILFS_MDT_INODE(sb, ino) \
((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino))))
@@ -212,6 +211,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
#define NILFS_ATIME_DISABLE
+/* Flags that should be inherited by new inodes from their parent. */
+#define NILFS_FL_INHERITED \
+ (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL | \
+ FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\
+ FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL)
+
+/* Mask out flags that are inappropriate for the given type of inode. */
+static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags)
+{
+ if (S_ISDIR(mode))
+ return flags;
+ else if (S_ISREG(mode))
+ return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL);
+ else
+ return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
+}
+
/* dir.c */
extern int nilfs_add_link(struct dentry *, struct inode *);
extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int);
/* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long);
+long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
void **);
/* inode.c */
+void nilfs_inode_add_blocks(struct inode *inode, int n);
+void nilfs_inode_sub_blocks(struct inode *inode, int n);
extern struct inode *nilfs_new_inode(struct inode *, int);
extern void nilfs_free_inode(struct inode *);
extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
@@ -275,11 +294,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *,
struct nilfs_super_block *);
extern void nilfs_set_log_cursor(struct nilfs_super_block *,
struct the_nilfs *);
-extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
- int flip);
-extern int nilfs_commit_super(struct nilfs_sb_info *, int);
-extern int nilfs_cleanup_super(struct nilfs_sb_info *);
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
+ int flip);
+int nilfs_commit_super(struct super_block *sb, int flag);
+int nilfs_cleanup_super(struct super_block *sb);
+int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
struct nilfs_root **root);
int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 3dfcd3b7d389..ba4a64518f38 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
}
static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
- struct nilfs_sb_info *sbi,
+ struct super_block *sb,
struct nilfs_recovery_info *ri)
{
struct list_head *head = &ri->ri_used_segments;
@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
}
static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
- struct nilfs_sb_info *sbi,
+ struct super_block *sb,
struct nilfs_root *root,
struct list_head *head,
unsigned long *nr_salvaged_blocks)
@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
int err = 0, err2 = 0;
list_for_each_entry_safe(rb, n, head, list) {
- inode = nilfs_iget(sbi->s_super, root, rb->ino);
+ inode = nilfs_iget(sb, root, rb->ino);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
@@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
* nilfs_do_roll_forward - salvage logical segments newer than the latest
* checkpoint
* @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
* @ri: pointer to a nilfs_recovery_info
*/
static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
- struct nilfs_sb_info *sbi,
+ struct super_block *sb,
struct nilfs_root *root,
struct nilfs_recovery_info *ri)
{
@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
goto failed;
if (flags & NILFS_SS_LOGEND) {
err = nilfs_recover_dsync_blocks(
- nilfs, sbi, root, &dsync_blocks,
+ nilfs, sb, root, &dsync_blocks,
&nsalvaged_blocks);
if (unlikely(err))
goto failed;
@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
if (nsalvaged_blocks) {
printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
- sbi->s_super->s_id, nsalvaged_blocks);
+ sb->s_id, nsalvaged_blocks);
ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
}
out:
@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
printk(KERN_ERR
"NILFS (device %s): Error roll-forwarding "
"(err=%d, pseg block=%llu). ",
- sbi->s_super->s_id, err, (unsigned long long)pseg_start);
+ sb->s_id, err, (unsigned long long)pseg_start);
goto out;
}
@@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
/**
* nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
* @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
* @ri: pointer to a nilfs_recovery_info struct to store search results.
*
* Return Value: On success, 0 is returned. On error, one of the following
@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
* %-ENOMEM - Insufficient memory available.
*/
int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
- struct nilfs_sb_info *sbi,
+ struct super_block *sb,
struct nilfs_recovery_info *ri)
{
struct nilfs_root *root;
@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
return 0;
- err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root);
+ err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
if (unlikely(err)) {
printk(KERN_ERR
"NILFS: error loading the latest checkpoint.\n");
return err;
}
- err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
+ err = nilfs_do_roll_forward(nilfs, sb, root, ri);
if (unlikely(err))
goto failed;
if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
- err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri);
+ err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
if (unlikely(err)) {
printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n");
goto failed;
}
- err = nilfs_attach_segment_constructor(sbi, root);
+ err = nilfs_attach_log_writer(sb, root);
if (unlikely(err))
goto failed;
set_nilfs_discontinued(nilfs);
- err = nilfs_construct_segment(sbi->s_super);
- nilfs_detach_segment_constructor(sbi);
+ err = nilfs_construct_segment(sb);
+ nilfs_detach_log_writer(sb);
if (unlikely(err)) {
printk(KERN_ERR "NILFS: Oops! recovery failed. "
diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h
deleted file mode 100644
index 7a17715f215f..000000000000