From 9566a7a851eb7201e3207eab53ee81efd0850fee Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 10 Aug 2010 00:58:41 +0900 Subject: nilfs2: accept future revisions Compatibility of nilfs partitions is now managed with three feature sets. This changes old compatibility check with revision number so that it can accept future revisions. Note that we can stop support of experimental versions of nilfs that doesn't know the feature sets by incrementing NILFS_CURRENT_REV. We don't have to do it soon, but it would be a possible option whenever the need arises. Signed-off-by: Ryusuke Konishi --- include/linux/nilfs2_fs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index f5487b6f91e..b07f5cdff5e 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -229,6 +229,7 @@ struct nilfs_super_block { */ #define NILFS_CURRENT_REV 2 /* current major revision */ #define NILFS_MINOR_REV 0 /* minor revision */ +#define NILFS_MIN_SUPP_REV 2 /* minimum supported revision */ /* * Feature set definitions -- cgit v1.2.3-70-g09d2 From 6c43f41000312fefa482c3bfdd97e7f81d6be0ec Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 20 Aug 2010 20:10:38 +0900 Subject: nilfs2: keep zero value in i_cno except for gc-inodes On-memory inode structures of nilfs have a member "i_cno" which stores a checkpoint number related to the inode. For gc-inodes, this field indicates version of data each gc-inode caches for GC. Log writer temporarily uses "i_cno" to transfer the latest checkpoint number. This stops the latter use and lets only gc-inodes use it. The purpose of this patch is to allow the successive change use "i_cno" for inode lookup. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/segment.c | 29 ++++++++++++++--------------- fs/nilfs2/segment.h | 3 ++- include/linux/nilfs2_fs.h | 8 ++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9fd051a33c4..eee4b223c29 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -366,8 +366,7 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci) if (nilfs_doing_gc()) flags = NILFS_SS_GC; - err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, - sci->sc_sbi->s_nilfs->ns_cno); + err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, sci->sc_cno); if (unlikely(err)) return err; @@ -440,17 +439,26 @@ static void nilfs_segctor_end_finfo(struct nilfs_sc_info *sci, struct nilfs_finfo *finfo; struct nilfs_inode_info *ii; struct nilfs_segment_buffer *segbuf; + __u64 cno; if (sci->sc_blk_cnt == 0) return; ii = NILFS_I(inode); + + if (test_bit(NILFS_I_GCINODE, &ii->i_state)) + cno = ii->i_cno; + else if (NILFS_ROOT_METADATA_FILE(inode->i_ino)) + cno = 0; + else + cno = sci->sc_cno; + finfo = nilfs_segctor_map_segsum_entry(sci, &sci->sc_finfo_ptr, sizeof(*finfo)); finfo->fi_ino = cpu_to_le64(inode->i_ino); finfo->fi_nblocks = cpu_to_le32(sci->sc_blk_cnt); finfo->fi_ndatablk = cpu_to_le32(sci->sc_datablk_cnt); - finfo->fi_cno = cpu_to_le64(ii->i_cno); + finfo->fi_cno = cpu_to_le64(cno); segbuf = sci->sc_curseg; segbuf->sb_sum.sumbytes = sci->sc_binfo_ptr.offset + @@ -1976,7 +1984,6 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, struct nilfs_sb_info *sbi) { struct nilfs_inode_info *ii, *n; - __u64 cno = sbi->s_nilfs->ns_cno; spin_lock(&sbi->s_inode_lock); retry: @@ -2002,7 +2009,6 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, brelse(ibh); goto retry; } - ii->i_cno = cno; clear_bit(NILFS_I_QUEUED, &ii->i_state); set_bit(NILFS_I_BUSY, &ii->i_state); @@ -2011,8 +2017,6 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, } spin_unlock(&sbi->s_inode_lock); - NILFS_I(sbi->s_ifile)->i_cno = cno; - return 0; } @@ -2021,19 +2025,13 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, { struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_inode_info *ii, *n; - __u64 cno = sbi->s_nilfs->ns_cno; spin_lock(&sbi->s_inode_lock); list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || - test_bit(NILFS_I_DIRTY, &ii->i_state)) { - /* The current checkpoint number (=nilfs->ns_cno) is - changed between check-in and check-out only if the - super root is written out. So, we can update i_cno - for the inodes that remain in the dirty list. */ - ii->i_cno = cno; + test_bit(NILFS_I_DIRTY, &ii->i_state)) continue; - } + clear_bit(NILFS_I_BUSY, &ii->i_state); brelse(ii->i_bh); ii->i_bh = NULL; @@ -2054,6 +2052,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) int err; sci->sc_stage.scnt = NILFS_ST_INIT; + sci->sc_cno = nilfs->ns_cno; err = nilfs_segctor_check_in_files(sci, sbi); if (unlikely(err)) diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 17c487bd815..675d932148a 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -107,6 +107,7 @@ struct nilfs_segsum_pointer { * @sc_datablk_cnt: Data block count of a file * @sc_nblk_this_inc: Number of blocks included in the current logical segment * @sc_seg_ctime: Creation time + * @sc_cno: checkpoint number of current log * @sc_flags: Internal flags * @sc_state_lock: spinlock for sc_state and so on * @sc_state: Segctord state flags @@ -156,7 +157,7 @@ struct nilfs_sc_info { unsigned long sc_datablk_cnt; unsigned long sc_nblk_this_inc; time_t sc_seg_ctime; - + __u64 sc_cno; unsigned long sc_flags; spinlock_t sc_state_lock; diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index b07f5cdff5e..bcdb34c68d0 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -270,6 +270,14 @@ struct nilfs_super_block { #define NILFS_MIN_NRSVSEGS 8 /* Minimum number of reserved 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 */ -- cgit v1.2.3-70-g09d2 From 8e656fd518784b49453f60c5f78b78703bc85cb2 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 27 Aug 2010 00:23:02 +0900 Subject: nilfs2: make snapshots in checkpoint tree exportable The previous export operations cannot handle multiple versions of a filesystem if they belong to the same sb instance. This adds a new type of file handle and extends export operations so that they can get the inode specified by a checkpoint number as well as an inode number and a generation number. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/export.h | 17 ++++++ fs/nilfs2/namei.c | 137 +++++++++++++++++++++++++++++++++++++++++------ fs/nilfs2/nilfs.h | 3 -- fs/nilfs2/super.c | 52 +----------------- include/linux/exportfs.h | 13 +++++ 5 files changed, 151 insertions(+), 71 deletions(-) create mode 100644 fs/nilfs2/export.h (limited to 'include') diff --git a/fs/nilfs2/export.h b/fs/nilfs2/export.h new file mode 100644 index 00000000000..a71cc412b65 --- /dev/null +++ b/fs/nilfs2/export.h @@ -0,0 +1,17 @@ +#ifndef NILFS_EXPORT_H +#define NILFS_EXPORT_H + +#include + +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 diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 1110d56a23f..a65f46560fb 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -40,7 +40,11 @@ #include #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) { @@ -77,23 +81,6 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 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, - NILFS_I(child->d_inode)->i_root, ino); - if (IS_ERR(inode)) - return ERR_CAST(inode); - return d_obtain_alias(inode); -} - /* * By the time this is called, we already have created * the directory cache entry for the new file, but it @@ -469,6 +456,115 @@ out: 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 = { .create = nilfs_create, .lookup = nilfs_lookup, @@ -493,3 +589,10 @@ const struct inode_operations nilfs_symlink_inode_operations = { .follow_link = page_follow_link_light, .put_link = page_put_link, }; + +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, +}; diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 21d90c4b4e2..aa7940f7ecf 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -264,9 +264,6 @@ extern int nilfs_set_file_dirty(struct nilfs_sb_info *, struct inode *, extern int nilfs_mark_inode_dirty(struct inode *); extern void nilfs_dirty_inode(struct inode *); -/* namei.c */ -extern struct dentry *nilfs_get_parent(struct dentry *); - /* super.c */ extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *); extern struct inode *nilfs_alloc_inode(struct super_block *); diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a1c0e38a770..adbf5826b83 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -48,10 +48,10 @@ #include #include #include -#include #include #include #include "nilfs.h" +#include "export.h" #include "mdt.h" #include "alloc.h" #include "btree.h" @@ -556,56 +556,6 @@ static const struct super_operations nilfs_sops = { .show_options = nilfs_show_options }; -static struct inode * -nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) -{ - struct inode *inode; - struct nilfs_root *root; - - if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && - ino != NILFS_SKETCH_INO) - return ERR_PTR(-ESTALE); - - root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, - NILFS_CPTREE_CURRENT_CNO); - if (!root) - return ERR_PTR(-ESTALE); - - /* new file handle type is required to export snapshots */ - inode = nilfs_iget(sb, root, ino); - nilfs_put_root(root); - if (IS_ERR(inode)) - return ERR_CAST(inode); - if (generation && inode->i_generation != generation) { - iput(inode); - return ERR_PTR(-ESTALE); - } - - return inode; -} - -static struct dentry * -nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, - int fh_type) -{ - return generic_fh_to_dentry(sb, fid, fh_len, fh_type, - nilfs_nfs_get_inode); -} - -static struct dentry * -nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, - int fh_type) -{ - return generic_fh_to_parent(sb, fid, fh_len, fh_type, - nilfs_nfs_get_inode); -} - -static const struct export_operations nilfs_export_ops = { - .fh_to_dentry = nilfs_fh_to_dentry, - .fh_to_parent = nilfs_fh_to_parent, - .get_parent = nilfs_get_parent, -}; - enum { Opt_err_cont, Opt_err_panic, Opt_err_ro, Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index a9cd507f8cd..28028988c86 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -67,6 +67,19 @@ enum fid_type { * 32 bit parent block number, 32 bit parent generation number */ 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 { -- cgit v1.2.3-70-g09d2 From b453c95eb8d6a3b2348e9c7bc28a7d223cb640e3 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 25 Aug 2010 23:52:46 +0900 Subject: nilfs2: get rid of snapshot mount flag This flag is a fake used to distinguish type of super block instance. And, it got obsolete by the unification of sb. Signed-off-by: Ryusuke Konishi --- include/linux/nilfs2_fs.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index bcdb34c68d0..46604671ccd 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -147,7 +147,6 @@ struct nilfs_super_root { #define NILFS_MOUNT_ERRORS_CONT 0x0010 /* Continue 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_SNAPSHOT 0x0080 /* Snapshot flag */ #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order semantics also for data */ -- cgit v1.2.3-70-g09d2 From c486f3895d6dc751f7c0f04f0fa67390ce4d168e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sun, 3 Oct 2010 17:44:03 +0900 Subject: nilfs2: change license of exported header file This allows other projects to carry copies of the header file related to ABI and disk format (i.e. "nilfs2_fs.h") without it or distributors having to worry about effects on the project's overall license terms. It's also desired for switching the license of nilfs library to LGPL. Jiro SEKIBA pointed out these license issues (Message-ID: <87tylo7msw.wl%jir@sekiba.com>), and he suggested switching license of the library and nilfs2_fs.h to GNU Lesser General Public License. We take in his suggestion to avoid the license issues. Signed-off-by: Ryusuke Konishi Cc: Jiro SEKIBA Cc: linux-nilfs --- include/linux/nilfs2_fs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 46604671ccd..227e49dd572 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h @@ -4,16 +4,16 @@ * 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 + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 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. + * 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 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * -- cgit v1.2.3-70-g09d2