Commit 071cb4b8 authored by Ryusuke Konishi's avatar Ryusuke Konishi

nilfs2: eliminate removal list of segments

This will clean up the removal list of segments and the related
functions from segment.c and ioctl.c, which have hurt code
readability.

This elimination is applied by using nilfs_sufile_updatev() previously
introduced in the patch ("nilfs2: add sufile function that can modify
multiple segment usages").
Signed-off-by: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
parent dda54f4b
...@@ -435,24 +435,6 @@ static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, ...@@ -435,24 +435,6 @@ static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
return nmembs; return nmembs;
} }
static int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
struct nilfs_argv *argv, void *buf)
{
size_t nmembs = argv->v_nmembs;
struct nilfs_sb_info *sbi = nilfs->ns_writer;
int ret;
if (unlikely(!sbi)) {
/* never happens because called for a writable mount */
WARN_ON(1);
return -EROFS;
}
ret = nilfs_segctor_add_segments_to_be_freed(
NILFS_SC(sbi), buf, nmembs);
return (ret < 0) ? ret : nmembs;
}
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
struct nilfs_argv *argv, void **kbufs) struct nilfs_argv *argv, void **kbufs)
{ {
...@@ -491,14 +473,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, ...@@ -491,14 +473,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
msg = "cannot mark copying blocks dirty"; msg = "cannot mark copying blocks dirty";
goto failed; goto failed;
} }
ret = nilfs_ioctl_free_segments(nilfs, &argv[4], kbufs[4]);
if (ret < 0) {
/*
* can safely abort because this operation is atomic.
*/
msg = "cannot set segments to be freed";
goto failed;
}
return 0; return 0;
failed: failed:
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/crc32.h> #include <linux/crc32.h>
#include "page.h" #include "page.h"
#include "segbuf.h" #include "segbuf.h"
#include "seglist.h"
static struct kmem_cache *nilfs_segbuf_cachep; static struct kmem_cache *nilfs_segbuf_cachep;
......
...@@ -32,11 +32,6 @@ ...@@ -32,11 +32,6 @@
struct nilfs_segment_entry { struct nilfs_segment_entry {
__u64 segnum; __u64 segnum;
#define NILFS_SLH_FREED 0x0001 /* The segment was freed provisonally.
It must be cancelled if
construction aborted */
unsigned flags;
struct list_head list; struct list_head list;
struct buffer_head *bh_su; struct buffer_head *bh_su;
struct nilfs_segment_usage *raw_su; struct nilfs_segment_usage *raw_su;
...@@ -52,7 +47,6 @@ nilfs_alloc_segment_entry(__u64 segnum) ...@@ -52,7 +47,6 @@ nilfs_alloc_segment_entry(__u64 segnum)
if (likely(ent)) { if (likely(ent)) {
ent->segnum = segnum; ent->segnum = segnum;
ent->flags = 0;
ent->bh_su = NULL; ent->bh_su = NULL;
ent->raw_su = NULL; ent->raw_su = NULL;
INIT_LIST_HEAD(&ent->list); INIT_LIST_HEAD(&ent->list);
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include "sufile.h" #include "sufile.h"
#include "cpfile.h" #include "cpfile.h"
#include "ifile.h" #include "ifile.h"
#include "seglist.h"
#include "segbuf.h" #include "segbuf.h"
...@@ -79,7 +78,8 @@ enum { ...@@ -79,7 +78,8 @@ enum {
/* State flags of collection */ /* State flags of collection */
#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */ #define NILFS_CF_NODE 0x0001 /* Collecting node blocks */
#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */ #define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */
#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED) #define NILFS_CF_SUFREED 0x0004 /* segment usages has been freed */
#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED | NILFS_CF_SUFREED)
/* Operations depending on the construction mode and file type */ /* Operations depending on the construction mode and file type */
struct nilfs_sc_operations { struct nilfs_sc_operations {
...@@ -810,7 +810,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) ...@@ -810,7 +810,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
{ {
return list_empty(&sci->sc_dirty_files) && return list_empty(&sci->sc_dirty_files) &&
!test_bit(NILFS_SC_DIRTY, &sci->sc_flags) && !test_bit(NILFS_SC_DIRTY, &sci->sc_flags) &&
list_empty(&sci->sc_cleaning_segments) && sci->sc_nfreesegs == 0 &&
(!nilfs_doing_gc() || list_empty(&sci->sc_gc_inodes)); (!nilfs_doing_gc() || list_empty(&sci->sc_gc_inodes));
} }
...@@ -1005,44 +1005,6 @@ static void nilfs_drop_collected_inodes(struct list_head *head) ...@@ -1005,44 +1005,6 @@ static void nilfs_drop_collected_inodes(struct list_head *head)
} }
} }
static void nilfs_segctor_cancel_free_segments(struct nilfs_sc_info *sci,
struct inode *sufile)
{
struct list_head *head = &sci->sc_cleaning_segments;
struct nilfs_segment_entry *ent;
int err;
list_for_each_entry(ent, head, list) {
if (!(ent->flags & NILFS_SLH_FREED))
break;
err = nilfs_sufile_cancel_free(sufile, ent->segnum);
WARN_ON(err); /* do not happen */
ent->flags &= ~NILFS_SLH_FREED;
}
}
static int nilfs_segctor_prepare_free_segments(struct nilfs_sc_info *sci,
struct inode *sufile)
{
struct list_head *head = &sci->sc_cleaning_segments;
struct nilfs_segment_entry *ent;
int err;
list_for_each_entry(ent, head, list) {
err = nilfs_sufile_free(sufile, ent->segnum);
if (unlikely(err))
return err;
ent->flags |= NILFS_SLH_FREED;
}
return 0;
}
static void nilfs_segctor_commit_free_segments(struct nilfs_sc_info *sci)
{
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
}
static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci, static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci,
struct inode *inode, struct inode *inode,
struct list_head *listp, struct list_head *listp,
...@@ -1161,6 +1123,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) ...@@ -1161,6 +1123,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sbi->s_nilfs;
struct list_head *head; struct list_head *head;
struct nilfs_inode_info *ii; struct nilfs_inode_info *ii;
size_t ndone;
int err = 0; int err = 0;
switch (sci->sc_stage.scnt) { switch (sci->sc_stage.scnt) {
...@@ -1250,10 +1213,16 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) ...@@ -1250,10 +1213,16 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
break; break;
sci->sc_stage.scnt++; /* Fall through */ sci->sc_stage.scnt++; /* Fall through */
case NILFS_ST_SUFILE: case NILFS_ST_SUFILE:
err = nilfs_segctor_prepare_free_segments(sci, err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs,
nilfs->ns_sufile); sci->sc_nfreesegs, &ndone);
if (unlikely(err)) if (unlikely(err)) {
nilfs_sufile_cancel_freev(nilfs->ns_sufile,
sci->sc_freesegs, ndone,
NULL);
break; break;
}
sci->sc_stage.flags |= NILFS_CF_SUFREED;
err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile, err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile,
&nilfs_sc_file_ops); &nilfs_sc_file_ops);
if (unlikely(err)) if (unlikely(err))
...@@ -1486,7 +1455,15 @@ static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci, ...@@ -1486,7 +1455,15 @@ static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci,
{ {
if (unlikely(err)) { if (unlikely(err)) {
nilfs_segctor_free_incomplete_segments(sci, nilfs); nilfs_segctor_free_incomplete_segments(sci, nilfs);
nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile); if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
int ret;
ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
sci->sc_freesegs,
sci->sc_nfreesegs,
NULL);
WARN_ON(ret); /* do not happen */
}
} }
nilfs_segctor_clear_segment_buffers(sci); nilfs_segctor_clear_segment_buffers(sci);
} }
...@@ -1585,7 +1562,13 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, ...@@ -1585,7 +1562,13 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE) if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE)
break; break;
nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile); if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
sci->sc_freesegs,
sci->sc_nfreesegs,
NULL);
WARN_ON(err); /* do not happen */
}
nilfs_segctor_clear_segment_buffers(sci); nilfs_segctor_clear_segment_buffers(sci);
err = nilfs_segctor_extend_segments(sci, nilfs, nadd); err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
...@@ -2224,10 +2207,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) ...@@ -2224,10 +2207,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
nilfs_segctor_complete_write(sci); nilfs_segctor_complete_write(sci);
/* Commit segments */ /* Commit segments */
if (has_sr) { if (has_sr)
nilfs_segctor_commit_free_segments(sci);
nilfs_segctor_clear_metadata_dirty(sci); nilfs_segctor_clear_metadata_dirty(sci);
}
nilfs_segctor_end_construction(sci, nilfs, 0); nilfs_segctor_end_construction(sci, nilfs, 0);
...@@ -2301,48 +2282,6 @@ void nilfs_flush_segment(struct super_block *sb, ino_t ino) ...@@ -2301,48 +2282,6 @@ void nilfs_flush_segment(struct super_block *sb, ino_t ino)
/* assign bit 0 to data files */ /* assign bit 0 to data files */
} }
int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *sci,
__u64 *segnum, size_t nsegs)
{
struct nilfs_segment_entry *ent;
struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
struct inode *sufile = nilfs->ns_sufile;
LIST_HEAD(list);
__u64 *pnum;
size_t i;
int err;
for (pnum = segnum, i = 0; i < nsegs; pnum++, i++) {
ent = nilfs_alloc_segment_entry(*pnum);
if (unlikely(!ent)) {
err = -ENOMEM;
goto failed;
}
list_add_tail(&ent->list, &list);
err = nilfs_open_segment_entry(ent, sufile);
if (unlikely(err))
goto failed;
if (unlikely(!nilfs_segment_usage_dirty(ent->raw_su)))
printk(KERN_WARNING "NILFS: unused segment is "
"requested to be cleaned (segnum=%llu)\n",
(unsigned long long)ent->segnum);
nilfs_close_segment_entry(ent, sufile);
}
list_splice(&list, sci->sc_cleaning_segments.prev);
return 0;
failed:
nilfs_dispose_segment_list(&list);
return err;
}
void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *sci)
{
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
}
struct nilfs_segctor_wait_request { struct nilfs_segctor_wait_request {
wait_queue_t wq; wait_queue_t wq;
__u32 seq; __u32 seq;
...@@ -2607,10 +2546,13 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, ...@@ -2607,10 +2546,13 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
err = nilfs_init_gcdat_inode(nilfs); err = nilfs_init_gcdat_inode(nilfs);
if (unlikely(err)) if (unlikely(err))
goto out_unlock; goto out_unlock;
err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs); err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err)) if (unlikely(err))
goto out_unlock; goto out_unlock;
sci->sc_freesegs = kbufs[4];
sci->sc_nfreesegs = argv[4].v_nmembs;
list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev); list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev);
for (;;) { for (;;) {
...@@ -2629,6 +2571,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, ...@@ -2629,6 +2571,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
} }
out_unlock: out_unlock:
sci->sc_freesegs = NULL;
sci->sc_nfreesegs = 0;
nilfs_clear_gcdat_inode(nilfs); nilfs_clear_gcdat_inode(nilfs);
nilfs_transaction_unlock(sbi); nilfs_transaction_unlock(sbi);
return err; return err;
...@@ -2835,7 +2779,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) ...@@ -2835,7 +2779,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi)
INIT_LIST_HEAD(&sci->sc_dirty_files); INIT_LIST_HEAD(&sci->sc_dirty_files);
INIT_LIST_HEAD(&sci->sc_segbufs); INIT_LIST_HEAD(&sci->sc_segbufs);
INIT_LIST_HEAD(&sci->sc_gc_inodes); INIT_LIST_HEAD(&sci->sc_gc_inodes);
INIT_LIST_HEAD(&sci->sc_cleaning_segments);
INIT_LIST_HEAD(&sci->sc_copied_buffers); INIT_LIST_HEAD(&sci->sc_copied_buffers);
sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
...@@ -2901,9 +2844,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) ...@@ -2901,9 +2844,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1);
} }
if (!list_empty(&sci->sc_cleaning_segments))
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
WARN_ON(!list_empty(&sci->sc_segbufs)); WARN_ON(!list_empty(&sci->sc_segbufs));
down_write(&sbi->s_nilfs->ns_segctor_sem); down_write(&sbi->s_nilfs->ns_segctor_sem);
......
...@@ -90,8 +90,9 @@ struct nilfs_segsum_pointer { ...@@ -90,8 +90,9 @@ struct nilfs_segsum_pointer {
* @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
* @sc_cleaning_segments: List of segments to be freed through construction
* @sc_copied_buffers: List of copied buffers (buffer heads) to freeze data * @sc_copied_buffers: List of copied buffers (buffer heads) to freeze data
* @sc_freesegs: array of segment numbers to be freed
* @sc_nfreesegs: number of segments on @sc_freesegs
* @sc_dsync_inode: inode whose data pages are written for a sync operation * @sc_dsync_inode: inode whose data pages are written for a sync operation
* @sc_dsync_start: start byte offset of data pages * @sc_dsync_start: start byte offset of data pages
* @sc_dsync_end: end byte offset of data pages (inclusive) * @sc_dsync_end: end byte offset of data pages (inclusive)
...@@ -131,9 +132,11 @@ struct nilfs_sc_info { ...@@ -131,9 +132,11 @@ struct nilfs_sc_info {
struct list_head sc_dirty_files; struct list_head sc_dirty_files;
struct list_head sc_gc_inodes; struct list_head sc_gc_inodes;
struct list_head sc_cleaning_segments;
struct list_head sc_copied_buffers; struct list_head sc_copied_buffers;
__u64 *sc_freesegs;
size_t sc_nfreesegs;
struct nilfs_inode_info *sc_dsync_inode; struct nilfs_inode_info *sc_dsync_inode;
loff_t sc_dsync_start; loff_t sc_dsync_start;
loff_t sc_dsync_end; loff_t sc_dsync_end;
...@@ -225,10 +228,6 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); ...@@ -225,10 +228,6 @@ 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_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
__u64 *, size_t);
extern void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *);
extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *);
extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
......
...@@ -54,35 +54,15 @@ int nilfs_sufile_update(struct inode *, __u64, int, ...@@ -54,35 +54,15 @@ int nilfs_sufile_update(struct inode *, __u64, int,
void (*dofunc)(struct inode *, __u64, void (*dofunc)(struct inode *, __u64,
struct buffer_head *, struct buffer_head *,
struct buffer_head *)); struct buffer_head *));
void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
struct buffer_head *);
void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *, void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *,
struct buffer_head *); struct buffer_head *);
void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *, void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *,
struct buffer_head *); struct buffer_head *);
void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
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 *);
/**
* nilfs_sufile_cancel_free -
* @sufile: inode of segment usage file
* @segnum: segment number
*
* Description:
*
* Return Value: On success, 0 is returned. On error, one of the following
* negative error codes is returned.
*
* %-EIO - I/O error.
*
* %-ENOMEM - Insufficient amount of memory available.
*/
static inline int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum)
{
return nilfs_sufile_update(sufile, segnum, 0,
nilfs_sufile_do_cancel_free);
}
/** /**
* nilfs_sufile_scrap - make a segment garbage * nilfs_sufile_scrap - make a segment garbage
* @sufile: inode of segment usage file * @sufile: inode of segment usage file
...@@ -103,6 +83,38 @@ static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum) ...@@ -103,6 +83,38 @@ static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum)
return nilfs_sufile_update(sufile, segnum, 0, nilfs_sufile_do_free); return nilfs_sufile_update(sufile, segnum, 0, nilfs_sufile_do_free);
} }
/**
* nilfs_sufile_freev - free segments
* @sufile: inode of segment usage file
* @segnumv: array of segment numbers
* @nsegs: size of @segnumv array
* @ndone: place to store the number of freed segments
*/
static inline int nilfs_sufile_freev(struct inode *sufile, __u64 *segnumv,
size_t nsegs, size_t *ndone)
{
return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
nilfs_sufile_do_free);
}
/**
* nilfs_sufile_cancel_freev - reallocate freeing segments
* @sufile: inode of segment usage file
* @segnumv: array of segment numbers
* @nsegs: size of @segnumv array
* @ndone: place to store the number of cancelled segments
*
* Return Value: On success, 0 is returned. On error, a negative error codes
* is returned.
*/
static inline int nilfs_sufile_cancel_freev(struct inode *sufile,
__u64 *segnumv, size_t nsegs,
size_t *ndone)
{
return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
nilfs_sufile_do_cancel_free);
}
/** /**
* nilfs_sufile_set_error - mark a segment as erroneous * nilfs_sufile_set_error - mark a segment as erroneous
* @sufile: inode of segment usage file * @sufile: inode of segment usage file
......
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