THE_NILFS_LOADED, /* Roll-back/roll-forward has done and
the latest checkpoint was loaded */
THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */
- THE_NILFS_COND_NONGC_WRITE, /* Condition to wake up cleanerd */
};
/**
* struct the_nilfs - struct to supervise multiple nilfs mount points
* @ns_flags: flags
* @ns_count: reference count
+ * @ns_list: list head for nilfs_list
* @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_super_sem: semaphore for global operations across super block instances
+ * @ns_mount_mutex: mutex protecting mount process of nilfs
* @ns_writer_mutex: mutex protecting ns_writer attach/detach
* @ns_writer_refcount: number of referrers on ns_writer
- * @ns_sbh: buffer head of the on-disk super block
- * @ns_sbp: pointer to the super block data
- * @ns_used_segments: list of full segments in volatile active state
+ * @ns_current: back pointer to current mount
+ * @ns_sbh: buffer heads of on-disk super blocks
+ * @ns_sbp: pointers to super block data
+ * @ns_sbwtime: previous write time of super blocks
+ * @ns_sbsize: size of valid data in super block
* @ns_supers: list of nilfs super block structs
* @ns_seg_seq: segment sequence counter
* @ns_segnum: index number of the latest full segment.
* @ns_last_pseg: start block number of the latest segment
* @ns_last_seq: sequence value of the latest segment
* @ns_last_cno: checkpoint number of the latest segment
+ * @ns_prot_seq: least sequence number of segments which must not be reclaimed
* @ns_free_segments_count: counter of free segments
* @ns_segctor_sem: segment constructor semaphore
* @ns_dat: DAT file inode
* @ns_gc_dat: shadow inode of the DAT file inode for GC
* @ns_gc_inodes: dummy inodes to keep live blocks
* @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks
- * @ns_cleanerd_wq: wait queue for cleanerd
* @ns_blocksize_bits: bit length of block size
* @ns_nsegments: number of segments in filesystem
* @ns_blocks_per_segment: number of blocks per segment
struct the_nilfs {
unsigned long ns_flags;
atomic_t ns_count;
+ struct list_head ns_list;
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_super_sem;
+ struct mutex ns_mount_mutex;
struct mutex ns_writer_mutex;
atomic_t ns_writer_refcount;
+ /*
+ * components protected by ns_super_sem
+ */
+ struct nilfs_sb_info *ns_current;
+ struct list_head ns_supers;
+
/*
* used for
* - loading the latest checkpoint exclusively.
* - protecting s_dirt in the super_block struct
* (see nilfs_write_super) and the following fields.
*/
- struct buffer_head *ns_sbh;
- struct nilfs_super_block *ns_sbp;
- struct list_head ns_used_segments;
+ struct buffer_head *ns_sbh[2];
+ struct nilfs_super_block *ns_sbp[2];
+ time_t ns_sbwtime[2];
+ unsigned ns_sbsize;
unsigned ns_mount_state;
- struct list_head ns_supers;
/*
* Following fields are dedicated to a writable FS-instance.
* Except for the period seeking checkpoint, code outside the segment
- * constructor must lock a segment semaphore with transaction_begin()
- * and transaction_end(), when accessing these fields.
+ * constructor must lock a segment semaphore while accessing these
+ * fields.
* The writable FS-instance is sole during a lifetime of the_nilfs.
*/
u64 ns_seg_seq;
sector_t ns_last_pseg;
u64 ns_last_seq;
__u64 ns_last_cno;
+ u64 ns_prot_seq;
unsigned long ns_free_segments_count;
struct rw_semaphore ns_segctor_sem;
struct list_head ns_gc_inodes;
struct hlist_head *ns_gc_inodes_h;
- /* cleanerd */
- wait_queue_head_t ns_cleanerd_wq;
-
/* Disk layout information (static) */
unsigned int ns_blocksize_bits;
unsigned long ns_nsegments;
THE_NILFS_FNS(INIT, init)
THE_NILFS_FNS(LOADED, loaded)
THE_NILFS_FNS(DISCONTINUED, discontinued)
-THE_NILFS_FNS(COND_NONGC_WRITE, cond_nongc_write)
+
+/* Minimum interval of periodical update of superblocks (in seconds) */
+#define NILFS_SB_FREQ 10
+#define NILFS_ALTSB_FREQ 60 /* spare superblock */
void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
-struct the_nilfs *alloc_nilfs(struct block_device *);
+struct the_nilfs *find_or_create_nilfs(struct block_device *);
void put_nilfs(struct the_nilfs *);
int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
-void nilfs_dispose_used_segments(struct the_nilfs *);
+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 *);
+void nilfs_fall_back_super_block(struct the_nilfs *);
+void nilfs_swap_super_block(struct the_nilfs *);
static inline void get_nilfs(struct the_nilfs *nilfs)
mutex_unlock(&nilfs->ns_writer_mutex);
}
+static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
+{
+ if (!atomic_dec_and_test(&sbi->s_count))
+ kfree(sbi);
+}
+
static inline void
nilfs_get_segment_range(struct the_nilfs *nilfs, __u64 segnum,
sector_t *seg_start, sector_t *seg_end)
return cno;
}
+static inline int nilfs_segment_is_active(struct the_nilfs *nilfs, __u64 n)
+{
+ return n == nilfs->ns_segnum || n == nilfs->ns_nextnum;
+}
+
#endif /* _THE_NILFS_H */