Commit ab34c02a authored by Linus Torvalds's avatar Linus Torvalds

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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (36 commits)
  nilfs2: eliminate sparse warning - "context imbalance"
  nilfs2: eliminate sparse warnings - "symbol not declared"
  nilfs2: get rid of bdi from nilfs object
  nilfs2: change license of exported header file
  nilfs2: add bdev freeze/thaw support
  nilfs2: accept 64-bit checkpoint numbers in cp mount option
  nilfs2: remove own inode allocator and destructor for metadata files
  nilfs2: get rid of back pointer to writable sb instance
  nilfs2: get rid of mi_nilfs back pointer to nilfs object
  nilfs2: see state of root dentry for mount check of snapshots
  nilfs2: use iget for all metadata files
  nilfs2: get rid of GCDAT inode
  nilfs2: add routines to redirect access to buffers of DAT file
  nilfs2: add routines to roll back state of DAT file
  nilfs2: add routines to save and restore bmap state
  nilfs2: do not allocate nilfs_mdt_info structure to gc-inodes
  nilfs2: allow nilfs_clear_inode to clear metadata file inodes
  nilfs2: get rid of snapshot mount flag
  nilfs2: simplify life cycle management of nilfs object
  nilfs2: do not allocate multiple super block instances for a device
  ...
parents 7f388396 6b81e14e
...@@ -2,4 +2,4 @@ obj-$(CONFIG_NILFS2_FS) += nilfs2.o ...@@ -2,4 +2,4 @@ obj-$(CONFIG_NILFS2_FS) += nilfs2.o
nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \
btnode.o bmap.o btree.o direct.o dat.o recovery.o \ btnode.o bmap.o btree.o direct.o dat.o recovery.o \
the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \
ifile.o alloc.o gcinode.o ioctl.o gcdat.o ifile.o alloc.o gcinode.o ioctl.o
...@@ -533,18 +533,20 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap) ...@@ -533,18 +533,20 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
nilfs_btree_init_gc(bmap); nilfs_btree_init_gc(bmap);
} }
void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) void nilfs_bmap_save(const struct nilfs_bmap *bmap,
struct nilfs_bmap_store *store)
{ {
memcpy(gcbmap, bmap, sizeof(*bmap)); memcpy(store->data, bmap->b_u.u_data, sizeof(store->data));
init_rwsem(&gcbmap->b_sem); store->last_allocated_key = bmap->b_last_allocated_key;
lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); store->last_allocated_ptr = bmap->b_last_allocated_ptr;
gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; store->state = bmap->b_state;
} }
void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) void nilfs_bmap_restore(struct nilfs_bmap *bmap,
const struct nilfs_bmap_store *store)
{ {
memcpy(bmap, gcbmap, sizeof(*bmap)); memcpy(bmap->b_u.u_data, store->data, sizeof(store->data));
init_rwsem(&bmap->b_sem); bmap->b_last_allocated_key = store->last_allocated_key;
lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); bmap->b_last_allocated_ptr = store->last_allocated_ptr;
bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; bmap->b_state = store->state;
} }
...@@ -135,6 +135,12 @@ struct nilfs_bmap { ...@@ -135,6 +135,12 @@ struct nilfs_bmap {
/* state */ /* state */
#define NILFS_BMAP_DIRTY 0x00000001 #define NILFS_BMAP_DIRTY 0x00000001
struct nilfs_bmap_store {
__le64 data[NILFS_BMAP_SIZE / sizeof(__le64)];
__u64 last_allocated_key;
__u64 last_allocated_ptr;
int state;
};
int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
...@@ -153,9 +159,9 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *, __u64, int, __u64 *); ...@@ -153,9 +159,9 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *, __u64, int, __u64 *);
int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int); int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int);
void nilfs_bmap_init_gc(struct nilfs_bmap *); void nilfs_bmap_init_gc(struct nilfs_bmap *);
void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
void nilfs_bmap_save(const struct nilfs_bmap *, struct nilfs_bmap_store *);
void nilfs_bmap_restore(struct nilfs_bmap *, const struct nilfs_bmap_store *);
static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key, static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key,
__u64 *ptr) __u64 *ptr)
......
...@@ -37,15 +37,7 @@ ...@@ -37,15 +37,7 @@
void nilfs_btnode_cache_init_once(struct address_space *btnc) void nilfs_btnode_cache_init_once(struct address_space *btnc)
{ {
memset(btnc, 0, sizeof(*btnc)); nilfs_mapping_init_once(btnc);
INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC);
spin_lock_init(&btnc->tree_lock);
INIT_LIST_HEAD(&btnc->private_list);
spin_lock_init(&btnc->private_lock);
spin_lock_init(&btnc->i_mmap_lock);
INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap);
INIT_LIST_HEAD(&btnc->i_mmap_nonlinear);
} }
static const struct address_space_operations def_btnode_aops = { static const struct address_space_operations def_btnode_aops = {
...@@ -55,12 +47,7 @@ static const struct address_space_operations def_btnode_aops = { ...@@ -55,12 +47,7 @@ static const struct address_space_operations def_btnode_aops = {
void nilfs_btnode_cache_init(struct address_space *btnc, void nilfs_btnode_cache_init(struct address_space *btnc,
struct backing_dev_info *bdi) struct backing_dev_info *bdi)
{ {
btnc->host = NULL; /* can safely set to host inode ? */ nilfs_mapping_init(btnc, bdi, &def_btnode_aops);
btnc->flags = 0;
mapping_set_gfp_mask(btnc, GFP_NOFS);
btnc->assoc_mapping = NULL;
btnc->backing_dev_info = bdi;
btnc->a_ops = &def_btnode_aops;
} }
void nilfs_btnode_cache_clear(struct address_space *btnc) void nilfs_btnode_cache_clear(struct address_space *btnc)
......
...@@ -863,26 +863,19 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) ...@@ -863,26 +863,19 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno)
*/ */
int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode)
{ {
struct the_nilfs *nilfs;
int ret; int ret;
nilfs = NILFS_MDT(cpfile)->mi_nilfs;
switch (mode) { switch (mode) {
case NILFS_CHECKPOINT: case NILFS_CHECKPOINT:
/* if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno))
* Check for protecting existing snapshot mounts: /*
* ns_mount_mutex is used to make this operation atomic and * Current implementation does not have to protect
* exclusive with a new mount job. Though it doesn't cover * plain read-only mounts since they are exclusive
* umount, it's enough for the purpose. * with a read/write mount and are protected from the
*/ * cleaner.
if (nilfs_checkpoint_is_mounted(nilfs, cno, 1)) { */
/* Current implementation does not have to protect
plain read-only mounts since they are exclusive
with a read/write mount and are protected from the
cleaner. */
ret = -EBUSY; ret = -EBUSY;
} else else
ret = nilfs_cpfile_clear_snapshot(cpfile, cno); ret = nilfs_cpfile_clear_snapshot(cpfile, cno);
return ret; return ret;
case NILFS_SNAPSHOT: case NILFS_SNAPSHOT:
...@@ -933,27 +926,40 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) ...@@ -933,27 +926,40 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat)
} }
/** /**
* nilfs_cpfile_read - read cpfile inode * nilfs_cpfile_read - read or get cpfile inode
* @cpfile: cpfile inode * @sb: super block instance
* @raw_inode: on-disk cpfile inode
*/
int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode)
{
return nilfs_read_inode_common(cpfile, raw_inode);
}
/**
* nilfs_cpfile_new - create cpfile
* @nilfs: nilfs object
* @cpsize: size of a checkpoint entry * @cpsize: size of a checkpoint entry
* @raw_inode: on-disk cpfile inode
* @inodep: buffer to store the inode
*/ */
struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize) int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
struct nilfs_inode *raw_inode, struct inode **inodep)
{ {
struct inode *cpfile; struct inode *cpfile;
int err;
cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
if (unlikely(!cpfile))
return -ENOMEM;
if (!(cpfile->i_state & I_NEW))
goto out;
err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0);
if (err)
goto failed;
cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO, 0); nilfs_mdt_set_entry_size(cpfile, cpsize,
if (cpfile) sizeof(struct nilfs_cpfile_header));
nilfs_mdt_set_entry_size(cpfile, cpsize,
sizeof(struct nilfs_cpfile_header)); err = nilfs_read_inode_common(cpfile, raw_inode);
return cpfile; if (err)
goto failed;
unlock_new_inode(cpfile);
out:
*inodep = cpfile;
return 0;
failed:
iget_failed(cpfile);
return err;
} }
...@@ -40,7 +40,7 @@ int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); ...@@ -40,7 +40,7 @@ int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *);
ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned, ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned,
size_t); size_t);
int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode); int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize); struct nilfs_inode *raw_inode, struct inode **inodep);
#endif /* _NILFS_CPFILE_H */ #endif /* _NILFS_CPFILE_H */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
struct nilfs_dat_info { struct nilfs_dat_info {
struct nilfs_mdt_info mi; struct nilfs_mdt_info mi;
struct nilfs_palloc_cache palloc_cache; struct nilfs_palloc_cache palloc_cache;
struct nilfs_shadow_map shadow;
}; };
static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
...@@ -102,7 +103,8 @@ void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req) ...@@ -102,7 +103,8 @@ void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
nilfs_palloc_abort_alloc_entry(dat, req); nilfs_palloc_abort_alloc_entry(dat, req);
} }
void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req) static void nilfs_dat_commit_free(struct inode *dat,
struct nilfs_palloc_req *req)
{ {
struct nilfs_dat_entry *entry; struct nilfs_dat_entry *entry;
void *kaddr; void *kaddr;
...@@ -327,6 +329,23 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) ...@@ -327,6 +329,23 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
if (ret < 0) if (ret < 0)
return ret; return ret;
/*
* The given disk block number (blocknr) is not yet written to
* the device at this point.
*
* To prevent nilfs_dat_translate() from returning the
* uncommited block number, this makes a copy of the entry
* buffer and redirects nilfs_dat_translate() to the copy.
*/
if (!buffer_nilfs_redirected(entry_bh)) {
ret = nilfs_mdt_freeze_buffer(dat, entry_bh);
if (ret) {
brelse(entry_bh);
return ret;
}
}
kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
...@@ -371,7 +390,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) ...@@ -371,7 +390,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
*/ */
int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
{ {
struct buffer_head *entry_bh; struct buffer_head *entry_bh, *bh;
struct nilfs_dat_entry *entry; struct nilfs_dat_entry *entry;
sector_t blocknr; sector_t blocknr;
void *kaddr; void *kaddr;
...@@ -381,6 +400,15 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) ...@@ -381,6 +400,15 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) {
bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh);
if (bh) {
WARN_ON(!buffer_uptodate(bh));
brelse(entry_bh);
entry_bh = bh;
}
}
kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
blocknr = le64_to_cpu(entry->de_blocknr); blocknr = le64_to_cpu(entry->de_blocknr);
...@@ -436,38 +464,48 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz, ...@@ -436,38 +464,48 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
} }
/** /**
* nilfs_dat_read - read dat inode * nilfs_dat_read - read or get dat inode
* @dat: dat inode * @sb: super block instance
* @raw_inode: on-disk dat inode
*/
int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode)
{
return nilfs_read_inode_common(dat, raw_inode);
}
/**
* nilfs_dat_new - create dat file
* @nilfs: nilfs object
* @entry_size: size of a dat entry * @entry_size: size of a dat entry
* @raw_inode: on-disk dat inode
* @inodep: buffer to store the inode
*/ */
struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size) int nilfs_dat_read(struct super_block *sb, size_t entry_size,
struct nilfs_inode *raw_inode, struct inode **inodep)
{ {
static struct lock_class_key dat_lock_key; static struct lock_class_key dat_lock_key;
struct inode *dat; struct inode *dat;
struct nilfs_dat_info *di; struct nilfs_dat_info *di;
int err; int err;
dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di)); dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
if (dat) { if (unlikely(!dat))
err = nilfs_palloc_init_blockgroup(dat, entry_size); return -ENOMEM;
if (unlikely(err)) { if (!(dat->i_state & I_NEW))
nilfs_mdt_destroy(dat); goto out;
return NULL;
}
di = NILFS_DAT_I(dat); err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); if (err)
nilfs_palloc_setup_cache(dat, &di->palloc_cache); goto failed;
}
return dat; err = nilfs_palloc_init_blockgroup(dat, entry_size);
if (err)
goto failed;
di = NILFS_DAT_I(dat);
lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
nilfs_palloc_setup_cache(dat, &di->palloc_cache);
nilfs_mdt_setup_shadow_map(dat, &di->shadow);
err = nilfs_read_inode_common(dat, raw_inode);
if (err)
goto failed;
unlock_new_inode(dat);
out:
*inodep = dat;
return 0;
failed:
iget_failed(dat);
return err;
} }
...@@ -53,7 +53,7 @@ int nilfs_dat_freev(struct inode *, __u64 *, size_t); ...@@ -53,7 +53,7 @@ int nilfs_dat_freev(struct inode *, __u64 *, size_t);
int nilfs_dat_move(struct inode *, __u64, sector_t); int nilfs_dat_move(struct inode *, __u64, sector_t);
ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t); ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t);
int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode); int nilfs_dat_read(struct super_block *sb, size_t entry_size,
struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size); struct nilfs_inode *raw_inode, struct inode **inodep);
#endif /* _NILFS_DAT_H */ #endif /* _NILFS_DAT_H */
#ifndef NILFS_EXPORT_H
#define NILFS_EXPORT_H
#include <linux/exportfs.h>
extern const struct export_operations nilfs_export_ops;
struct nilfs_fid {
u64 cno;
u64 ino;
u32 gen;
u32 parent_gen;
u64 parent_ino;
} __attribute__ ((packed));
#endif
/*
* gcdat.c - NILFS shadow DAT inode for GC
*
* 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 Seiji Kihara <kihara@osrg.net>, Amagai Yoshiji <amagai@osrg.net>,
* and Ryusuke Konishi <ryusuke@osrg.net>.
*
*/
#include <linux/buffer_head.h>
#include "nilfs.h"
#include "page.h"
#include "mdt.h"
int nilfs_init_gcdat_inode(struct the_nilfs *nilfs)
{
struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
int err;
gcdat->i_state = 0;
gcdat->i_blocks = dat->i_blocks;
gii->i_flags = dii->i_flags;
gii->i_state = dii->i_state | (1 << NILFS_I_GCDAT);
gii->i_cno = 0;
nilfs_bmap_init_gcdat(gii->i_bmap, dii->i_bmap);
err = nilfs_copy_dirty_pages(gcdat->i_mapping, dat->i_mapping);
if (unlikely(err))
return err;
return nilfs_copy_dirty_pages(&gii->i_btnode_cache,
&dii->i_btnode_cache);
}
void nilfs_commit_gcdat_inode(struct the_nilfs *nilfs)
{
struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
struct address_space *mapping = dat->i_mapping;
struct address_space *gmapping = gcdat->i_mapping;
down_write(&NILFS_MDT(dat)->mi_sem);
dat->i_blocks = gcdat->i_blocks;
dii->i_flags = gii->i_flags;
dii->i_state = gii->i_state & ~(1 << NILFS_I_GCDAT);
nilfs_bmap_commit_gcdat(gii->i_bmap, dii->i_bmap);
nilfs_palloc_clear_cache(dat);
nilfs_palloc_clear_cache(gcdat);
nilfs_clear_dirty_pages(mapping);
nilfs_copy_back_pages(mapping, gmapping);
/* note: mdt dirty flags should be cleared by segctor. */
nilfs_clear_dirty_pages(&dii->i_btnode_cache);
nilfs_copy_back_pages(&dii->i_btnode_cache, &gii->i_btnode_cache);
up_write(&NILFS_MDT(dat)->mi_sem);
}
void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs)
{
struct inode *gcdat = nilfs->ns_gc_dat;
struct nilfs_inode_info *gii = NILFS_I(gcdat);
gcdat->i_state = I_FREEING | I_CLEAR;
gii->i_flags = 0;
nilfs_palloc_clear_cache(gcdat);
truncate_inode_pages(gcdat->i_mapping, 0);
truncate_inode_pages(&gii->i_btnode_cache, 0);
}
...@@ -28,13 +28,6 @@ ...@@ -28,13 +28,6 @@
* gcinodes), and this file provides lookup function of the dummy * gcinodes), and this file provides lookup function of the dummy
* inodes and their buffer read function. * inodes and their buffer read function.
* *
* Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it
* has to treat blocks that belong to a same file but have different
* checkpoint numbers. To avoid interference among generations, dummy
* inodes are managed separately from actual inodes, and their lookup
* function (nilfs_gc_iget) is designed to be specified with a
* checkpoint number argument as well as an inode number.
*
* Buffers and pages held by the dummy inodes will be released each * Buffers and pages held by the dummy inodes will be released each
* time after they are copied to a new log. Dirty blocks made on the * time after they are copied to a new log. Dirty blocks made on the
* current generation and the blocks to be moved by GC never overlap * current generation and the blocks to be moved by GC never overlap
...@@ -175,125 +168,46 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) ...@@ -175,125 +168,46 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
} }
nilfs_btnode_mark_dirty(bh); nilfs_btnode_mark_dirty(bh);
} else { } else {
nilfs_mdt_mark_buffer_dirty(bh); nilfs_mark_buffer_dirty(bh);
} }
return 0; return 0;
} }
/* int nilfs_init_gcinode(struct inode *inode)
* nilfs_init_gccache() - allocate and initialize gc_inode hash table
* @nilfs - the_nilfs
*
* Return Value: On success, 0.
* On error, a negative error code is returned.
*/
int nilfs_init_gccache(struct the_nilfs *nilfs)
{ {
int loop; struct nilfs_inode_info *ii = NILFS_I(inode);
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
BUG_ON(nilfs->ns_gc_inodes_h);
INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
nilfs->ns_gc_inodes_h =
kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE,
GFP_NOFS);
if (nilfs->ns_gc_inodes_h == NULL)
return -ENOMEM;
for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++)
INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]);
return 0;
}
/*
* nilfs_destroy_gccache() - free gc_inode hash table
* @nilfs - the nilfs
*/
void nilfs_destroy_gccache(struct the_nilfs *nilfs)
{
if (nilfs->ns_gc_inodes_h) {
nilfs_remove_all_gcinode(nilfs);
kfree(nilfs->ns_gc_inodes_h);
nilfs->ns_gc_inodes_h = NULL;
}
}
static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino,
__u64 cno)
{
struct inode *inode;
struct nilfs_inode_info *ii;
inode = nilfs_mdt_new_common(nilfs, NULL, ino, GFP_NOFS, 0);
if (!inode)
return NULL;
inode->i_op = NULL; inode->i_mode = S_IFREG;
inode->i_fop = NULL; mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
inode->i_mapping->a_ops = &def_gcinode_aops; inode->i_mapping->a_ops = &def_gcinode_aops;
inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi;
ii = NILFS_I(inode);
ii->i_cno = cno;
ii->i_flags = 0; ii->i_flags = 0;
ii->i_state = 1 << NILFS_I_GCINODE;
ii->i_bh = NULL;
nilfs_bmap_init_gc(ii->i_bmap); nilfs_bmap_init_gc(ii->i_bmap);
return inode; /*
} * Add the inode to GC inode list. Garbage Collection
* is serialized and no two processes manipulate the
static unsigned long ihash(ino_t ino, __u64 cno) * list simultaneously.
{ */
return hash_long((unsigned long)((ino << 2) + cno), igrab(inode);
NILFS_GCINODE_HASH_BITS); list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
}
/*
* nilfs_gc_iget() - find or create gc inode with specified (ino,cno)
*/
struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno)
{
struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno);
struct hlist_node *node;
struct inode *inode;
hlist_for_each_entry(inode, node, head, i_hash) {
if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno)
return inode;
}
inode = alloc_gcinode(nilfs, ino, cno); return 0;
if (likely(inode)) {
hlist_add_head(&inode->i_hash, head);
list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
}
return inode;
}
/*
* nilfs_clear_gcinode() - clear and free a gc inode
*/
void nilfs_clear_gcinode(struct inode *inode)
{
nilfs_mdt_destroy(inode);
} }
/* /**
* nilfs_remove_all_gcinode() - remove all inodes from the_nilfs * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes
*/ */
void nilfs_remove_all_gcinode(struct the_nilfs *nilfs) void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)
{ {
struct hlist_head *head = nilfs->ns_gc_inodes_h; struct list_head *head = &nilfs->ns_gc_inodes;
struct hlist_node *node, *n; struct nilfs_inode_info *ii;
struct inode *inode;
int loop;
for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) { while (!list_empty(head)) {
hlist_for_each_entry_safe(inode, node, n, head, i_hash) { ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
hlist_del_init(&inode->i_hash); list_del_init(&ii->i_dirty);
list_del_init(&NILFS_I(inode)->i_dirty); iput(&ii->vfs_inode);
nilfs_clear_gcinode(inode); /* might sleep */
}
} }
} }
...@@ -161,25 +161,46 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, ...@@ -161,25 +161,46 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino,
} }
/** /**
* nilfs_ifile_new - create inode file * nilfs_ifile_read - read or get ifile inode
* @sbi: nilfs_sb_info struct * @sb: super block instance
* @root: root object
* @inode_size: size of an inode * @inode_size: size of an inode
* @raw_inode: on-disk ifile inode
* @inodep: buffer to store the inode
*/ */
struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size) int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
size_t inode_size, struct nilfs_inode *raw_inode,
struct inode **inodep)
{ {
struct inode *ifile; struct inode *ifile;
int err; int err;
ifile = nilfs_mdt_new(sbi->s_nilfs, sbi->s_super, NILFS_IFILE_INO, ifile = nilfs_iget_locked(sb, root, NILFS_IFILE_INO);
sizeof(struct nilfs_ifile_info)); if (unlikely(!ifile))
if (ifile) { return -ENOMEM;
err = nilfs_palloc_init_blockgroup(ifile, inode_size); if (!(ifile->i_state & I_NEW))
if (unlikely(err)) { goto out;
nilfs_mdt_destroy(ifile);
return NULL; err = nilfs_mdt_init(ifile, NILFS_MDT_GFP,
} sizeof(struct nilfs_ifile_info));
nilfs_palloc_setup_cache(ifile, if (err)
&NILFS_IFILE_I(ifile)->palloc_cache); goto failed;
}
return ifile; err = nilfs_palloc_init_blockgroup(ifile, inode_size);
if (err)
goto failed;
nilfs_palloc_setup_cache(ifile, &NILFS_IFILE_I(ifile)->palloc_cache);
err = nilfs_read_inode_common(ifile, raw_inode);
if (err)
goto failed;
unlock_new_inode(ifile);
out:
*inodep = ifile;
return 0;
failed:
iget_failed(ifile);
return err;
} }
...@@ -49,6 +49,8 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **); ...@@ -49,6 +49,8 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **);
int nilfs_ifile_delete_inode(struct inode *, ino_t); int nilfs_ifile_delete_inode(struct inode *, ino_t);
int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **);
struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size); int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
size_t inode_size, struct nilfs_inode *raw_inode,
struct inode **inodep);
#endif /* _NILFS_IFILE_H */ #endif /* _NILFS_IFILE_H */
This diff is collapsed.
...@@ -117,7 +117,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, ...@@ -117,7 +117,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
if (copy_from_user(&cpmode, argp, sizeof(cpmode))) if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
goto out; goto out;
mutex_lock(&nilfs->ns_mount_mutex); down_read(&inode->i_sb->s_umount);
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(
...@@ -127,7 +127,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, ...@@ -127,7 +127,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
else else
nilfs_transaction_commit(inode->i_sb); /* never fails */ nilfs_transaction_commit(inode->i_sb); /* never fails */
mutex_unlock(&nilfs->ns_mount_mutex); up_read(&inode->i_sb->s_umount);
out: out:
mnt_drop_write(filp->f_path.mnt); mnt_drop_write(filp->f_path.mnt);
return ret; return ret;
...@@ -333,7 +333,7 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, ...@@ -333,7 +333,7 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode,
return 0; return 0;
} }
static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, 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;
...@@ -348,7 +348,7 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, ...@@ -348,7 +348,7 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
for (i = 0, vdesc = buf; i < nmembs; ) { for (i = 0, vdesc = buf; i < nmembs; ) {
ino = vdesc->vd_ino; ino = vdesc->vd_ino;
cno = vdesc->vd_cno; cno = vdesc->vd_cno;
inode = nilfs_gc_iget(nilfs, ino, cno); inode = nilfs_iget_for_gc(sb, ino, cno);
if (unlikely(inode == NULL)) { if (unlikely(inode == NULL)) {
ret = -ENOMEM; ret = -ENOMEM;
goto failed; goto failed;
...@@ -356,11 +356,15 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, ...@@ -356,11 +356,15 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
do { do {
ret = nilfs_ioctl_move_inode_block(inode, vdesc, ret = nilfs_ioctl_move_inode_block(inode, vdesc,
&buffers); &buffers);
if (unlikely(ret < 0)) if (unlikely(ret < 0)) {
iput(inode);
goto failed; goto failed;
}
vdesc++; vdesc++;
} while (++i < nmembs && } while (++i < nmembs &&
vdesc->vd_ino == ino && vdesc->vd_cno == cno); vdesc->vd_ino == ino && vdesc->vd_cno == cno);
iput(inode); /* The inode still remains in GC inode list */
} }
list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
...@@ -566,7 +570,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ...@@ -566,7 +570,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
} }
/* /*
* nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
* which will operates an inode list without blocking. * which will operates an inode list without blocking.
* To protect the list from concurrent operations, * To protect the list from concurrent operations,
* nilfs_ioctl_move_blocks should be atomic operation. * nilfs_ioctl_move_blocks should be atomic operation.
...@@ -576,15 +580,16 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ...@@ -576,15 +580,16 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
goto out_free; goto out_free;
} }
ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
if (ret < 0) if (ret < 0)
printk(KERN_ERR "NILFS: GC failed during preparation: " printk(KERN_ERR "NILFS: GC failed during preparation: "
"cannot read source blocks: err=%d\n", ret); "cannot read source blocks: err=%d\n", ret);
else else
ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
if (ret < 0) nilfs_remove_all_gcinodes(nilfs);
nilfs_remove_all_gcinode(nilfs);
clear_nilfs_gc_running(nilfs); clear_nilfs_gc_running(nilfs);
out_free: out_free:
......
This diff is collapsed.
...@@ -28,26 +28,33 @@ ...@@ -28,26 +28,33 @@
#include "nilfs.h" #include "nilfs.h"
#include "page.h" #include "page.h"
struct nilfs_shadow_map {
struct nilfs_bmap_store bmap_store;
struct address_space frozen_data;
struct address_space frozen_btnodes;
struct list_head frozen_buffers;
};
/** /**
* struct nilfs_mdt_info - on-memory private data of meta data files * struct nilfs_mdt_info - on-memory private data of meta data files
* @mi_nilfs: back pointer to the_nilfs struct
* @mi_sem: reader/writer semaphore for meta data operations * @mi_sem: reader/writer semaphore for meta data operations
* @mi_bgl: per-blockgroup locking * @mi_bgl: per-blockgroup locking
* @mi_entry_size: size of an entry * @mi_entry_size: size of an entry
* @mi_first_entry_offset: offset to the first entry * @mi_first_entry_offset: offset to the first entry
* @mi_entries_per_block: number of entries in a block * @mi_entries_per_block: number of entries in a block
* @mi_palloc_cache: persistent object allocator cache * @mi_palloc_cache: persistent object allocator cache
* @mi_shadow: shadow of bmap and page caches
* @mi_blocks_per_group: number of blocks in a group * @mi_blocks_per_group: number of blocks in a group
* @mi_blocks_per_desc_block: number of blocks per descriptor block * @mi_blocks_per_desc_block: number of blocks per descriptor block
*/ */
struct nilfs_mdt_info { struct nilfs_mdt_info {
struct the_nilfs *mi_nilfs;
struct rw_semaphore mi_sem; struct rw_semaphore mi_sem;
struct blockgroup_lock *mi_bgl; struct blockgroup_lock *mi_bgl;
unsigned mi_entry_size; unsigned mi_entry_size;
unsigned mi_first_entry_offset; unsigned mi_first_entry_offset;
unsigned long mi_entries_per_block; unsigned long mi_entries_per_block;
struct nilfs_palloc_cache *mi_palloc_cache; struct nilfs_palloc_cache *mi_palloc_cache;
struct nilfs_shadow_map *mi_shadow;
unsigned long mi_blocks_per_group; unsigned long mi_blocks_per_group;
unsigned long mi_blocks_per_desc_block; unsigned long mi_blocks_per_desc_block;
}; };
...@@ -59,9 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode) ...@@ -59,9 +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)
{ {
struct super_block *sb = inode->i_sb; return NILFS_SB(inode->i_sb)->s_nilfs;
return sb ? NILFS_SB(sb)->s_nilfs : NILFS_MDT(inode)->mi_nilfs;
} }
/* Default GFP flags using highmem */ /* Default GFP flags using highmem */
...@@ -76,14 +81,17 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long); ...@@ -76,14 +81,17 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long);
int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);
int nilfs_mdt_fetch_dirty(struct inode *); int nilfs_mdt_fetch_dirty(struct inode *);
struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t, int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz);
size_t);
struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *,
ino_t, gfp_t, size_t);
void nilfs_mdt_destroy(struct inode *);
void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned); void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned);
void nilfs_mdt_set_shadow(struct inode *, struct inode *);
int nilfs_mdt_setup_shadow_map(struct inode *inode,
struct nilfs_shadow_map *shadow);
int nilfs_mdt_save_to_shadow_map(struct inode *inode);
void nilfs_mdt_restore_from_shadow_map(struct inode *inode);
void nilfs_mdt_clear_shadow_map(struct inode *inode);
int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh);
struct buffer_head *nilfs_mdt_get_frozen_buffer(struct inode *inode,
struct buffer_head *bh);
#define nilfs_mdt_mark_buffer_dirty(bh) nilfs_mark_buffer_dirty(bh) #define nilfs_mdt_mark_buffer_dirty(bh) nilfs_mark_buffer_dirty(bh)
...@@ -100,7 +108,7 @@ static inline void nilfs_mdt_clear_dirty(struct inode *inode) ...@@ -100,7 +108,7 @@ static inline void nilfs_mdt_clear_dirty(struct inode *inode)
static inline __u64 nilfs_mdt_cno(struct inode *inode) static inline __u64 nilfs_mdt_cno(struct inode *inode)
{ {
return NILFS_MDT(inode)->mi_nilfs->ns_cno; return NILFS_I_NILFS(inode)->ns_cno;
} }
#define nilfs_mdt_bgl_lock(inode, bg) \ #define nilfs_mdt_bgl_lock(inode, bg) \
......
...@@ -40,7 +40,11 @@ ...@@ -40,7 +40,11 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include "nilfs.h" #include "nilfs.h"
#include "export.h"
#define NILFS_FID_SIZE_NON_CONNECTABLE \
(offsetof(struct nilfs_fid, parent_gen) / 4)
#define NILFS_FID_SIZE_CONNECTABLE (sizeof(struct nilfs_fid) / 4)
static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
{ {
...@@ -70,29 +74,13 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ...@@ -70,29 +74,13 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
ino = nilfs_inode_by_name(dir, &dentry->d_name); ino = nilfs_inode_by_name(dir, &dentry->d_name);
inode = NULL; inode = NULL;
if (ino) { if (ino) {
inode = nilfs_iget(dir->i_sb, ino); inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino);
if (IS_ERR(inode)) if (IS_ERR(inode))
return ERR_CAST(inode); return ERR_CAST(inode);
} }
return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry);
} }
struct dentry *nilfs_get_parent(struct dentry *child)
{
unsigned long ino;
struct inode *inode;
struct qstr dotdot = {.name = "..", .len = 2};
ino = nilfs_inode_by_name(child->d_inode, &dotdot);
if (!ino)
return ERR_PTR(-ENOENT);
inode = nilfs_iget(child->d_inode->i_sb, ino);
if (IS_ERR(inode))
return ERR_CAST(inode);
return d_obtain_alias(inode);
}
/* /*
* By the time this is called, we already have created * By the time this is called, we already have created
* the directory cache entry for the new file, but it * the directory cache entry for the new file, but it
...@@ -468,6 +456,115 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -468,6 +456,115 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return err; return err;
} }
/*
* Export operations
*/
static struct dentry *nilfs_get_parent(struct dentry *child)
{
unsigned long ino;
struct inode *inode;
struct qstr dotdot = {.name = "..", .len = 2};
struct nilfs_root *root;
ino = nilfs_inode_by_name(child->d_inode, &dotdot);
if (!ino)
return ERR_PTR(-ENOENT);
root = NILFS_I(child->d_inode)->i_root;
inode = nilfs_iget(child->d_inode->i_sb, root, ino);
if (IS_ERR(inode))
return ERR_CAST(inode);
return d_obtain_alias(inode);
}
static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
u64 ino, u32 gen)
{
struct nilfs_root *root;
struct inode *inode;
if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
return ERR_PTR(-ESTALE);
root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
if (!root)
return ERR_PTR(-ESTALE);
inode = nilfs_iget(sb, root, ino);
nilfs_put_root(root);
if (IS_ERR(inode))
return ERR_CAST(inode);
if (gen && inode->i_generation != gen) {
iput(inode);
return ERR_PTR(-ESTALE);
}
return d_obtain_alias(inode);
}
static struct dentry *nilfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
int fh_len, int fh_type)
{
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
if ((fh_len != NILFS_FID_SIZE_NON_CONNECTABLE &&
fh_len != NILFS_FID_SIZE_CONNECTABLE) ||
(fh_type != FILEID_NILFS_WITH_PARENT &&
fh_type != FILEID_NILFS_WITHOUT_PARENT))
return NULL;
return nilfs_get_dentry(sb, fid->cno, fid->ino, fid->gen);
}
static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh,
int fh_len, int fh_type)
{
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
if (fh_len != NILFS_FID_SIZE_CONNECTABLE ||
fh_type != FILEID_NILFS_WITH_PARENT)
return NULL;
return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen);
}
static int nilfs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
int connectable)
{
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
struct inode *inode = dentry->d_inode;
struct nilfs_root *root = NILFS_I(inode)->i_root;
int type;
if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE ||
(connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE))
return 255;
fid->cno = root->cno;
fid->ino = inode->i_ino;
fid->gen = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
fid->parent_ino = parent->i_ino;
fid->parent_gen = parent->i_generation;
spin_unlock(&dentry->d_lock);
type = FILEID_NILFS_WITH_PARENT;
*lenp = NILFS_FID_SIZE_CONNECTABLE;
} else {
type = FILEID_NILFS_WITHOUT_PARENT;
*lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
}
return type;
}
const struct inode_operations nilfs_dir_inode_operations = { const struct inode_operations nilfs_dir_inode_operations = {
.create = nilfs_create, .create = nilfs_create,
.lookup = nilfs_lookup, .lookup = nilfs_lookup,
...@@ -491,4 +588,12 @@ const struct inode_operations nilfs_symlink_inode_operations = { ...@@ -491,4 +588,12 @@ const struct inode_operations nilfs_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = page_follow_link_light, .follow_link = page_follow_link_light,
.put_link = page_put_link, .put_link = page_put_link,
.permission = nilfs_permission,
};
const struct export_operations nilfs_export_ops = {
.encode_fh = nilfs_encode_fh,
.fh_to_dentry = nilfs_fh_to_dentry,
.fh_to_parent = nilfs_fh_to_parent,
.get_parent = nilfs_get_parent,
}; };
...@@ -59,6 +59,7 @@ struct nilfs_inode_info { ...@@ -59,6 +59,7 @@ struct nilfs_inode_info {
#endif #endif
struct buffer_head *i_bh; /* i_bh contains a new or dirty struct buffer_head *i_bh; /* i_bh contains a new or dirty
disk inode */ disk inode */
struct nilfs_root *i_root;
struct inode vfs_inode; struct inode vfs_inode;
}; };
...@@ -100,7 +101,6 @@ enum { ...@@ -100,7 +101,6 @@ enum {
NILFS_I_INODE_DIRTY, /* write_inode is requested */ NILFS_I_INODE_DIRTY, /* write_inode is requested */
NILFS_I_BMAP, /* has bmap and btnode_cache */ NILFS_I_BMAP, /* has bmap and btnode_cache */
NILFS_I_GCINODE, /* inode for GC, on memory only */ NILFS_I_GCINODE, /* inode for GC, on memory only */
NILFS_I_GCDAT, /* shadow DAT, on memory only */
}; };
/* /*
...@@ -192,7 +192,7 @@ static inline int nilfs_doing_construction(void) ...@@ -192,7 +192,7 @@ static inline int nilfs_doing_construction(void)
static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs)
{ {
return nilfs_doing_gc() ? nilfs->ns_gc_dat : nilfs->ns_dat; return nilfs->ns_dat;
} }
/* /*
...@@ -200,12 +200,9 @@ static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) ...@@ -200,12 +200,9 @@ static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs)
*/ */
#ifdef CONFIG_NILFS_POSIX_ACL #ifdef CONFIG_NILFS_POSIX_ACL
#error "NILFS: not yet supported POSIX ACL" #error "NILFS: not yet supported POSIX ACL"
extern int nilfs_permission(struct inode *, int, struct nameidata *);
extern int nilfs_acl_chmod(struct inode *); extern int nilfs_acl_chmod(struct inode *);
extern int nilfs_init_acl(struct inode *, struct inode *); extern int nilfs_init_acl(struct inode *, struct inode *);
#else #else
#define nilfs_permission NULL
static inline int nilfs_acl_chmod(struct inode *inode) static inline int nilfs_acl_chmod(struct inode *inode)
{ {
return 0; return 0;
...@@ -247,11 +244,19 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); ...@@ -247,11 +244,19 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern void nilfs_set_inode_flags(struct inode *); extern void nilfs_set_inode_flags(struct inode *);
extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *);
extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int);
extern struct inode *nilfs_iget(struct super_block *, unsigned long); struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
unsigned long ino);
struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
unsigned long ino);
struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
unsigned long ino);
extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
unsigned long ino, __u64 cno);
extern void nilfs_update_inode(struct inode *, struct buffer_head *); extern void nilfs_update_inode(struct inode *, struct buffer_head *);
extern void nilfs_truncate(struct inode *); extern void nilfs_truncate(struct inode *);
extern void nilfs_evict_inode(struct inode *); extern void nilfs_evict_inode(struct inode *);
extern int nilfs_setattr(struct dentry *, struct iattr *); extern int nilfs_setattr(struct dentry *, struct iattr *);
int nilfs_permission(struct inode *inode, int mask);
extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *, extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *,
struct buffer_head **); struct buffer_head **);
extern int nilfs_inode_dirty(struct inode *); extern int nilfs_inode_dirty(struct inode *);
...@@ -260,11 +265,7 @@ extern int nilfs_set_file_dirty(struct nilfs_sb_info *, struct inode *, ...@@ -260,11 +265,7 @@ extern int nilfs_set_file_dirty(struct nilfs_sb_info *, struct inode *,
extern int nilfs_mark_inode_dirty(struct inode *); extern int nilfs_mark_inode_dirty(struct inode *);
extern void nilfs_dirty_inode(struct inode *); extern void nilfs_dirty_inode(struct inode *);
/* namei.c */
extern struct dentry *nilfs_get_parent(struct dentry *);
/* super.c */ /* super.c */
extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *);
extern struct inode *nilfs_alloc_inode(struct super_block *); extern struct inode *nilfs_alloc_inode(struct super_block *);
extern void nilfs_destroy_inode(struct inode *); extern void nilfs_destroy_inode(struct inode *);
extern void nilfs_error(struct super_block *, const char *, const char *, ...) extern void nilfs_error(struct super_block *, const char *, const char *, ...)
...@@ -283,8 +284,9 @@ extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, ...@@ -283,8 +284,9 @@ extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
int flip); int flip);
extern int nilfs_commit_super(struct nilfs_sb_info *, int); extern int nilfs_commit_super(struct nilfs_sb_info *, int);
extern int nilfs_cleanup_super(struct nilfs_sb_info *); extern int nilfs_cleanup_super(struct nilfs_sb_info *);
extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); struct nilfs_root **root);
int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
/* gcinode.c */ /* gcinode.c */
int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64,
...@@ -292,16 +294,8 @@ int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, ...@@ -292,16 +294,8 @@ int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64,
int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64, int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64,
struct buffer_head **); struct buffer_head **);
int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *);
int nilfs_init_gccache(struct the_nilfs *); int nilfs_init_gcinode(struct inode *inode);
void nilfs_destroy_gccache(struct the_nilfs *); void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs);
void nilfs_clear_gcinode(struct inode *);
struct inode *nilfs_gc_iget(struct the_nilfs *, ino_t, __u64);
void nilfs_remove_all_gcinode(struct the_nilfs *);
/* gcdat.c */
int nilfs_init_gcdat_inode(struct the_nilfs *);
void nilfs_commit_gcdat_inode(struct the_nilfs *);
void nilfs_clear_gcdat_inode(struct the_nilfs *);
/* /*
* Inodes and files operations * Inodes and files operations
......
...@@ -79,8 +79,8 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, ...@@ -79,8 +79,8 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
{ {
int blkbits = inode->i_blkbits; int blkbits = inode->i_blkbits;
pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits); pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits);
struct page *page, *opage; struct page *page;
struct buffer_head *bh, *obh; struct buffer_head *bh;
page = grab_cache_page(mapping, index); page = grab_cache_page(mapping, index);
if (unlikely(!page)) if (unlikely(!page))
...@@ -92,30 +92,6 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, ...@@ -92,30 +92,6 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
page_cache_release(page); page_cache_release(page);
return NULL; return NULL;
} }
if (!buffer_uptodate(bh) && mapping->assoc_mapping != NULL) {
/*
* Shadow page cache uses assoc_mapping to point its original
* page cache. The following code tries the original cache
* if the given cache is a shadow and it didn't hit.
*/
opage = find_lock_page(mapping->assoc_mapping, index);
if (!opage)
return bh;
obh = __nilfs_get_page_block(opage, blkoff, index, blkbits,
b_state);
if (buffer_uptodate(obh)) {
nilfs_copy_buffer(bh, obh);
if (buffer_dirty(obh)) {
nilfs_mark_buffer_dirty(bh);
if (!buffer_nilfs_node(bh) && NILFS_MDT(inode))
nilfs_mdt_mark_dirty(inode);
}
}
brelse(obh);
unlock_page(opage);
page_cache_release(opage);
}
return bh; return bh;
} }
...@@ -131,6 +107,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) ...@@ -131,6 +107,7 @@ void nilfs_forget_buffer(struct buffer_head *bh)
lock_buffer(bh); lock_buffer(bh);
clear_buffer_nilfs_volatile(bh); clear_buffer_nilfs_volatile(bh);
clear_buffer_nilfs_checked(bh); clear_buffer_nilfs_checked(bh);
clear_buffer_nilfs_redirected(bh);
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
if (nilfs_page_buffers_clean(page)) if (nilfs_page_buffers_clean(page))
__nilfs_clear_page_dirty(page); __nilfs_clear_page_dirty(page);
...@@ -483,6 +460,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) ...@@ -483,6 +460,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping)
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
clear_buffer_nilfs_volatile(bh); clear_buffer_nilfs_volatile(bh);
clear_buffer_nilfs_checked(bh); clear_buffer_nilfs_checked(bh);
clear_buffer_nilfs_redirected(bh);
clear_buffer_uptodate(bh); clear_buffer_uptodate(bh);
clear_buffer_mapped(bh); clear_buffer_mapped(bh);
unlock_buffer(bh); unlock_buffer(bh);
...@@ -513,6 +491,31 @@ unsigned nilfs_page_count_clean_buffers(struct page *page, ...@@ -513,6 +491,31 @@ unsigned nilfs_page_count_clean_buffers(struct page *page,
} }
return nc; return nc;
} }
void nilfs_mapping_init_once(struct address_space *mapping)
{
memset(mapping, 0, sizeof(*mapping));
INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
spin_lock_init(&mapping->tree_lock);
INIT_LIST_HEAD(&mapping->private_list);
spin_lock_init(&mapping->private_lock);
spin_lock_init(&mapping->i_mmap_lock);
INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
}
void nilfs_mapping_init(struct address_space *mapping,
struct backing_dev_info *bdi,
const struct address_space_operations *aops)
{
mapping->host = NULL;
mapping->flags = 0;
mapping_set_gfp_mask(mapping, GFP_NOFS);
mapping->assoc_mapping = NULL;
mapping->backing_dev_info = bdi;
mapping->a_ops = aops;
}
/* /*
* NILFS2 needs clear_page_dirty() in the following two cases: * NILFS2 needs clear_page_dirty() in the following two cases:
......
...@@ -35,12 +35,14 @@ enum { ...@@ -35,12 +35,14 @@ enum {
BH_NILFS_Node, BH_NILFS_Node,
BH_NILFS_Volatile, BH_NILFS_Volatile,
BH_NILFS_Checked, BH_NILFS_Checked,
BH_NILFS_Redirected,
}; };
BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */
BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */
BUFFER_FNS(NILFS_Volatile, nilfs_volatile) BUFFER_FNS(NILFS_Volatile, nilfs_volatile)
BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */
BUFFER_FNS(NILFS_Redirected, nilfs_redirected) /* redirected to a copy */
void nilfs_mark_buffer_dirty(struct buffer_head *bh); void nilfs_mark_buffer_dirty(struct buffer_head *bh);
...@@ -59,6 +61,10 @@ void nilfs_free_private_page(struct page *); ...@@ -59,6 +61,10 @@ void nilfs_free_private_page(struct page *);
int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
void nilfs_copy_back_pages(struct address_space *, struct address_space *); void nilfs_copy_back_pages(struct address_space *, struct address_space *);
void nilfs_clear_dirty_pages(struct address_space *); void nilfs_clear_dirty_pages(struct address_space *);
void nilfs_mapping_init_once(struct address_space *mapping);
void nilfs_mapping_init(struct address_space *mapping,
struct backing_dev_info *bdi,
const struct address_space_operations *aops);
unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned);
#define NILFS_PAGE_BUG(page, m, a...) \ #define NILFS_PAGE_BUG(page, m, a...) \
......
...@@ -440,7 +440,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, ...@@ -440,7 +440,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
segnum[2] = ri->ri_segnum; segnum[2] = ri->ri_segnum;
segnum[3] = ri->ri_nextnum; segnum[3] = ri->ri_nextnum;
nilfs_attach_writer(nilfs, sbi);
/* /*
* Releasing the next segment of the latest super root. * Releasing the next segment of the latest super root.
* The next segment is invalidated by this recovery. * The next segment is invalidated by this recovery.
...@@ -480,7 +479,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, ...@@ -480,7 +479,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
failed: failed:
/* No need to recover sufile because it will be destroyed on error */ /* No need to recover sufile because it will be destroyed on error */
nilfs_detach_writer(nilfs, sbi);
return err; return err;
} }
...@@ -504,6 +502,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, ...@@ -504,6 +502,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 nilfs_sb_info *sbi,
struct nilfs_root *root,
struct list_head *head, struct list_head *head,
unsigned long *nr_salvaged_blocks) unsigned long *nr_salvaged_blocks)
{ {
...@@ -515,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, ...@@ -515,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, rb->ino); inode = nilfs_iget(sbi->s_super, root, rb->ino);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
inode = NULL; inode = NULL;
...@@ -578,6 +577,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, ...@@ -578,6 +577,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
*/ */
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 nilfs_sb_info *sbi,
struct nilfs_root *root,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
struct buffer_head *bh_sum = NULL; struct buffer_head *bh_sum = NULL;
...@@ -597,7 +597,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -597,7 +597,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
}; };
int state = RF_INIT_ST; int state = RF_INIT_ST;
nilfs_attach_writer(nilfs, sbi);
pseg_start = ri->ri_lsegs_start; pseg_start = ri->ri_lsegs_start;
seg_seq = ri->ri_lsegs_start_seq; seg_seq = ri->ri_lsegs_start_seq;
segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
...@@ -649,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -649,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, &dsync_blocks, nilfs, sbi, root, &dsync_blocks,
&nsalvaged_blocks); &nsalvaged_blocks);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
...@@ -688,7 +687,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, ...@@ -688,7 +687,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
out: out:
brelse(bh_sum); brelse(bh_sum);
dispose_recovery_list(&dsync_blocks); dispose_recovery_list(&dsync_blocks);
nilfs_detach_writer(nilfs, sbi);
return err; return err;
confused: confused:
...@@ -746,19 +744,20 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, ...@@ -746,19 +744,20 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi, struct nilfs_sb_info *sbi,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
struct nilfs_root *root;
int err; int err;
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); err = nilfs_attach_checkpoint(sbi, 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, ri); err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
...@@ -770,7 +769,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, ...@@ -770,7 +769,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
goto failed; goto failed;
} }
err = nilfs_attach_segment_constructor(sbi); err = nilfs_attach_segment_constructor(sbi, root);
if (unlikely(err)) if (unlikely(err))
goto failed; goto failed;
...@@ -788,7 +787,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, ...@@ -788,7 +787,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
} }
failed: failed:
nilfs_detach_checkpoint(sbi); nilfs_put_root(root);
return err; return err;
} }
......
...@@ -42,11 +42,6 @@ struct nilfs_sc_info; ...@@ -42,11 +42,6 @@ struct nilfs_sc_info;
* NILFS super-block data in memory * NILFS super-block data in memory
*/ */
struct nilfs_sb_info { struct nilfs_sb_info {
/* Snapshot status */
__u64 s_snapshot_cno; /* Checkpoint number */
atomic_t s_inodes_count;
atomic_t s_blocks_count; /* Reserved (might be deleted) */
/* Mount options */ /* Mount options */
unsigned long s_mount_opt; unsigned long s_mount_opt;
uid_t s_resuid; uid_t s_resuid;
...@@ -59,8 +54,6 @@ struct nilfs_sb_info { ...@@ -59,8 +54,6 @@ struct nilfs_sb_info {
/* Fundamental members */ /* Fundamental members */
struct super_block *s_super; /* reverse pointer to super_block */ struct super_block *s_super; /* reverse pointer to super_block */
struct the_nilfs *s_nilfs; struct the_nilfs *s_nilfs;
struct list_head s_list; /* list head for nilfs->ns_supers */
atomic_t s_count; /* reference count */
/* Segment constructor */ /* Segment constructor */
struct list_head s_dirty_files; /* dirty files list */ struct list_head s_dirty_files; /* dirty files list */
...@@ -68,9 +61,6 @@ struct nilfs_sb_info { ...@@ -68,9 +61,6 @@ struct nilfs_sb_info {
spinlock_t s_inode_lock; /* Lock for the nilfs inode. spinlock_t s_inode_lock; /* Lock for the nilfs inode.
It covers s_dirty_files list */ It covers s_dirty_files list */
/* Metadata files */
struct inode *s_ifile; /* index file inode */
/* Inode allocator */ /* Inode allocator */
spinlock_t s_next_gen_lock; spinlock_t s_next_gen_lock;
u32 s_next_generation; u32 s_next_generation;
......
...@@ -371,7 +371,8 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, ...@@ -371,7 +371,8 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf,
struct bio *bio = wi->bio; struct bio *bio = wi->bio;
int err; int err;
if (segbuf->sb_nbio > 0 && bdi_write_congested(wi->nilfs->ns_bdi)) { if (segbuf->sb_nbio > 0 &&
bdi_write_congested(segbuf->sb_super->s_bdi)) {
wait_for_completion(&segbuf->sb_bio_event); wait_for_completion(&segbuf->sb_bio_event);
segbuf->sb_nbio--; segbuf->sb_nbio--;
if (unlikely(atomic_read(&segbuf->sb_err))) { if (unlikely(atomic_read(&segbuf->sb_err))) {
......
This diff is collapsed.
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "sb.h" #include "sb.h"
struct nilfs_root;
/** /**
* struct nilfs_recovery_info - Recovery information * struct nilfs_recovery_info - Recovery information
* @ri_need_recovery: Recovery status * @ri_need_recovery: Recovery status
...@@ -87,6 +89,7 @@ struct nilfs_segsum_pointer { ...@@ -87,6 +89,7 @@ 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_sbi: Back pointer to nilfs_sb_info struct
* @sc_root: root object of the current filesystem tree
* @sc_nblk_inc: Block count of current generation * @sc_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
* @sc_gc_inodes: List of GC inodes having blocks to be written * @sc_gc_inodes: List of GC inodes having blocks to be written
...@@ -107,6 +110,7 @@ struct nilfs_segsum_pointer { ...@@ -107,6 +110,7 @@ struct nilfs_segsum_pointer {
* @sc_datablk_cnt: Data block count of a file * @sc_datablk_cnt: Data block count of a file
* @sc_nblk_this_inc: Number of blocks included in the current logical segment * @sc_nblk_this_inc: Number of blocks included in the current logical segment
* @sc_seg_ctime: Creation time * @sc_seg_ctime: Creation time
* @sc_cno: checkpoint number of current log
* @sc_flags: Internal flags * @sc_flags: Internal flags
* @sc_state_lock: spinlock for sc_state and so on * @sc_state_lock: spinlock for sc_state and so on
* @sc_state: Segctord state flags * @sc_state: Segctord state flags
...@@ -128,6 +132,7 @@ struct nilfs_segsum_pointer { ...@@ -128,6 +132,7 @@ 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_sb_info *sc_sbi;
struct nilfs_root *sc_root;
unsigned long sc_nblk_inc; unsigned long sc_nblk_inc;
...@@ -156,7 +161,7 @@ struct nilfs_sc_info { ...@@ -156,7 +161,7 @@ struct nilfs_sc_info {
unsigned long sc_datablk_cnt; unsigned long sc_datablk_cnt;
unsigned long sc_nblk_this_inc; unsigned long sc_nblk_this_inc;
time_t sc_seg_ctime; time_t sc_seg_ctime;
__u64 sc_cno;
unsigned long sc_flags; unsigned long sc_flags;
spinlock_t sc_state_lock; spinlock_t sc_state_lock;
...@@ -230,7 +235,8 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); ...@@ -230,7 +235,8 @@ 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 **);
extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
struct nilfs_root *root);
extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
/* recovery.c */ /* recovery.c */
......
...@@ -505,7 +505,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) ...@@ -505,7 +505,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
{ {
struct buffer_head *header_bh; struct buffer_head *header_bh;
struct nilfs_sufile_header *header; struct nilfs_sufile_header *header;
struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; struct the_nilfs *nilfs = NILFS_I_NILFS(sufile);
void *kaddr; void *kaddr;
int ret; int ret;
...@@ -583,7 +583,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, ...@@ -583,7 +583,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
struct nilfs_segment_usage *su; struct nilfs_segment_usage *su;
struct nilfs_suinfo *si = buf; struct nilfs_suinfo *si = buf;
size_t susz = NILFS_MDT(sufile)->mi_entry_size; size_t susz = NILFS_MDT(sufile)->mi_entry_size;
struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; struct the_nilfs *nilfs = NILFS_I_NILFS(sufile);
void *kaddr; void *kaddr;
unsigned long nsegs, segusages_per_block; unsigned long nsegs, segusages_per_block;
ssize_t n; ssize_t n;
...@@ -635,46 +635,55 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, ...@@ -635,46 +635,55 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
} }
/** /**
* nilfs_sufile_read - read sufile inode * nilfs_sufile_read - read or get sufile inode
* @sufile: sufile inode * @sb: super block instance
* @susize: size of a segment usage entry
* @raw_inode: on-disk sufile inode * @raw_inode: on-disk sufile inode
* @inodep: buffer to store the inode
*/ */
int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode) int nilfs_sufile_read(struct super_block *sb, size_t susize,
struct nilfs_inode *raw_inode, struct inode **inodep)
{ {
struct nilfs_sufile_info *sui = NILFS_SUI(sufile); struct inode *sufile;
struct nilfs_sufile_info *sui;
struct buffer_head *header_bh; struct buffer_head *header_bh;
struct nilfs_sufile_header *header; struct nilfs_sufile_header *header;
void *kaddr; void *kaddr;
int ret; int err;
ret = nilfs_read_inode_common(sufile, raw_inode); sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
if (ret < 0) if (unlikely(!sufile))
return ret; return -ENOMEM;
if (!(sufile->i_state & I_NEW))
goto out;
ret = nilfs_sufile_get_header_block(sufile, &header_bh); err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui));
if (!ret) { if (err)
kaddr = kmap_atomic(header_bh->b_page, KM_USER0); goto failed;
header = kaddr + bh_offset(header_bh);
sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
kunmap_atomic(kaddr, KM_USER0);
brelse(header_bh);
}
return ret;
}
/** nilfs_mdt_set_entry_size(sufile, susize,
* nilfs_sufile_new - create sufile sizeof(struct nilfs_sufile_header));
* @nilfs: nilfs object
* @susize: size of a segment usage entry err = nilfs_read_inode_common(sufile, raw_inode);
*/ if (err)
struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize) goto failed;
{
struct inode *sufile; err = nilfs_sufile_get_header_block(sufile, &header_bh);
if (err)
goto failed;
sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO, sui = NILFS_SUI(sufile);
sizeof(struct nilfs_sufile_info)); kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
if (sufile) header = kaddr + bh_offset(header_bh);
nilfs_mdt_set_entry_size(sufile, susize, sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
sizeof(struct nilfs_sufile_header)); kunmap_atomic(kaddr, KM_USER0);
return sufile; brelse(header_bh);
unlock_new_inode(sufile);
out:
*inodep = sufile;
return 0;
failed:
iget_failed(sufile);
return err;
} }
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile)
{ {
return NILFS_MDT(sufile)->mi_nilfs->ns_nsegments; return NILFS_I_NILFS(sufile)->ns_nsegments;
} }
unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile); unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile);
...@@ -61,8 +61,8 @@ void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *, ...@@ -61,8 +61,8 @@ void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
struct buffer_head *); struct buffer_head *);
int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode); int nilfs_sufile_read(struct super_block *sb, size_t susize,
struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize); struct nilfs_inode *raw_inode, struct inode **inodep);
/** /**
* nilfs_sufile_scrap - make a segment garbage * nilfs_sufile_scrap - make a segment garbage
......
This diff is collapsed.
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/rbtree.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
...@@ -45,22 +46,13 @@ enum { ...@@ -45,22 +46,13 @@ enum {
/** /**
* struct the_nilfs - struct to supervise multiple nilfs mount points * struct the_nilfs - struct to supervise multiple nilfs mount points
* @ns_flags: flags * @ns_flags: flags
* @ns_count: reference count
* @ns_list: list head for nilfs_list
* @ns_bdev: block device * @ns_bdev: block device
* @ns_bdi: backing dev info
* @ns_writer: back pointer to writable nilfs_sb_info
* @ns_sem: semaphore for shared states * @ns_sem: semaphore for shared states
* @ns_super_sem: semaphore for global operations across super block instances
* @ns_mount_mutex: mutex protecting mount process of nilfs
* @ns_writer_sem: semaphore protecting ns_writer attach/detach
* @ns_current: back pointer to current mount
* @ns_sbh: buffer heads of on-disk super blocks * @ns_sbh: buffer heads of on-disk super blocks
* @ns_sbp: pointers to super block data * @ns_sbp: pointers to super block data
* @ns_sbwtime: previous write time of super block * @ns_sbwtime: previous write time of super block
* @ns_sbwcount: write count of super block * @ns_sbwcount: write count of super block
* @ns_sbsize: size of valid data in super block * @ns_sbsize: size of valid data in super block
* @ns_supers: list of nilfs super block structs
* @ns_seg_seq: segment sequence counter * @ns_seg_seq: segment sequence counter
* @ns_segnum: index number of the latest full segment. * @ns_segnum: index number of the latest full segment.
* @ns_nextnum: index number of the full segment index to be used next * @ns_nextnum: index number of the full segment index to be used next
...@@ -79,9 +71,9 @@ enum { ...@@ -79,9 +71,9 @@ enum {
* @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_gc_dat: shadow inode of the DAT file inode for GC * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
* @ns_cptree_lock: lock protecting @ns_cptree
* @ns_gc_inodes: dummy inodes to keep live blocks * @ns_gc_inodes: dummy inodes to keep live blocks
* @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks
* @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
...@@ -95,22 +87,9 @@ enum { ...@@ -95,22 +87,9 @@ enum {
*/ */
struct the_nilfs { struct the_nilfs {
unsigned long ns_flags; unsigned long ns_flags;
atomic_t ns_count;
struct list_head ns_list;
struct block_device *ns_bdev; struct block_device *ns_bdev;
struct backing_dev_info *ns_bdi;
struct nilfs_sb_info *ns_writer;
struct rw_semaphore ns_sem; struct rw_semaphore ns_sem;
struct rw_semaphore ns_super_sem;
struct mutex ns_mount_mutex;
struct rw_semaphore ns_writer_sem;
/*
* components protected by ns_super_sem
*/
struct nilfs_sb_info *ns_current;
struct list_head ns_supers;
/* /*
* used for * used for
...@@ -163,11 +142,13 @@ struct the_nilfs { ...@@ -163,11 +142,13 @@ struct the_nilfs {
struct inode *ns_dat; struct inode *ns_dat;
struct inode *ns_cpfile; struct inode *ns_cpfile;
struct inode *ns_sufile; struct inode *ns_sufile;
struct inode *ns_gc_dat;
/* GC inode list and hash table head */ /* Checkpoint tree */
struct rb_root ns_cptree;
spinlock_t ns_cptree_lock;
/* GC inode list */
struct list_head ns_gc_inodes; struct list_head ns_gc_inodes;
struct hlist_head *ns_gc_inodes_h;
/* Disk layout information (static) */ /* Disk layout information (static) */
unsigned int ns_blocksize_bits; unsigned int ns_blocksize_bits;
...@@ -182,9 +163,6 @@ struct the_nilfs { ...@@ -182,9 +163,6 @@ struct the_nilfs {
u32 ns_crc_seed; u32 ns_crc_seed;
}; };
#define NILFS_GCINODE_HASH_BITS 8
#define NILFS_GCINODE_HASH_SIZE (1<<NILFS_GCINODE_HASH_BITS)
#define THE_NILFS_FNS(bit, name) \ #define THE_NILFS_FNS(bit, name) \
static inline void set_nilfs_##name(struct the_nilfs *nilfs) \ static inline void set_nilfs_##name(struct the_nilfs *nilfs) \
{ \ { \
...@@ -205,6 +183,32 @@ THE_NILFS_FNS(DISCONTINUED, discontinued) ...@@ -205,6 +183,32 @@ 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)
/**
* struct nilfs_root - nilfs root object
* @cno: checkpoint number
* @rb_node: red-black tree node
* @count: refcount of this structure
* @nilfs: nilfs object
* @ifile: inode file
* @root: root inode
* @inodes_count: number of inodes
* @blocks_count: number of blocks (Reserved)
*/
struct nilfs_root {
__u64 cno;
struct rb_node rb_node;
atomic_t count;
struct the_nilfs *nilfs;
struct inode *ifile;
atomic_t inodes_count;
atomic_t blocks_count;
};
/* Special checkpoint number */
#define NILFS_CPTREE_CURRENT_CNO 0
/* Minimum interval of periodical update of superblocks (in seconds) */ /* Minimum interval of periodical update of superblocks (in seconds) */
#define NILFS_SB_FREQ 10 #define NILFS_SB_FREQ 10
...@@ -221,46 +225,25 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) ...@@ -221,46 +225,25 @@ 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 *find_or_create_nilfs(struct block_device *); struct the_nilfs *alloc_nilfs(struct block_device *bdev);
void put_nilfs(struct the_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 *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
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_find_or_create_root(struct the_nilfs *nilfs,
__u64 cno);
void nilfs_put_root(struct nilfs_root *root);
struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
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 *);
static inline void get_nilfs(struct the_nilfs *nilfs) static inline void nilfs_get_root(struct nilfs_root *root)
{
/* Caller must have at least one reference of the_nilfs. */
atomic_inc(&nilfs->ns_count);
}
static inline void
nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{
down_write(&nilfs->ns_writer_sem);
nilfs->ns_writer = sbi;
up_write(&nilfs->ns_writer_sem);
}
static inline void
nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{
down_write(&nilfs->ns_writer_sem);
if (sbi == nilfs->ns_writer)
nilfs->ns_writer = NULL;
up_write(&nilfs->ns_writer_sem);
}
static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
{ {
if (atomic_dec_and_test(&sbi->s_count)) atomic_inc(&root->count);
kfree(sbi);
} }
static inline int nilfs_valid_fs(struct the_nilfs *nilfs) static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
......
...@@ -67,6 +67,19 @@ enum fid_type { ...@@ -67,6 +67,19 @@ enum fid_type {
* 32 bit parent block number, 32 bit parent generation number * 32 bit parent block number, 32 bit parent generation number
*/ */
FILEID_UDF_WITH_PARENT = 0x52, FILEID_UDF_WITH_PARENT = 0x52,
/*
* 64 bit checkpoint number, 64 bit inode number,
* 32 bit generation number.
*/
FILEID_NILFS_WITHOUT_PARENT = 0x61,
/*
* 64 bit checkpoint number, 64 bit inode number,
* 32 bit generation number, 32 bit parent generation.
* 64 bit parent inode number.
*/
FILEID_NILFS_WITH_PARENT = 0x62,
}; };
struct fid { struct fid {
......
...@@ -4,16 +4,16 @@ ...@@ -4,16 +4,16 @@
* Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU Lesser General Public License as published
* the Free Software Foundation; either version 2 of the License, or * by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* *
...@@ -147,7 +147,6 @@ struct nilfs_super_root { ...@@ -147,7 +147,6 @@ struct nilfs_super_root {
#define NILFS_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ #define NILFS_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define NILFS_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ #define NILFS_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define NILFS_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ #define NILFS_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define NILFS_MOUNT_SNAPSHOT 0x0080 /* Snapshot flag */
#define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */
#define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order
semantics also for data */ semantics also for data */
...@@ -229,6 +228,7 @@ struct nilfs_super_block { ...@@ -229,6 +228,7 @@ struct nilfs_super_block {
*/ */
#define NILFS_CURRENT_REV 2 /* current major revision */ #define NILFS_CURRENT_REV 2 /* current major revision */
#define NILFS_MINOR_REV 0 /* minor revision */ #define NILFS_MINOR_REV 0 /* minor revision */
#define NILFS_MIN_SUPP_REV 2 /* minimum supported revision */
/* /*
* Feature set definitions * Feature set definitions
...@@ -269,6 +269,14 @@ struct nilfs_super_block { ...@@ -269,6 +269,14 @@ struct nilfs_super_block {
#define NILFS_MIN_NRSVSEGS 8 /* Minimum number of reserved #define NILFS_MIN_NRSVSEGS 8 /* Minimum number of reserved
segments */ segments */
/*
* We call DAT, cpfile, and sufile root metadata files. Inodes of
* these files are written in super root block instead of ifile, and
* garbage collector doesn't keep any past versions of these files.
*/
#define NILFS_ROOT_METADATA_FILE(ino) \
((ino) >= NILFS_DAT_INO && (ino) <= NILFS_SUFILE_INO)
/* /*
* bytes offset of secondary super block * bytes offset of secondary super block
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment