This patch adds support for the field su_nsnapshot_blks and includes the
necessary flags to update it from the GC.

The GC already has the necessary information about which block belongs
to a snapshot and which doesn't. So these blocks are counted up and
passed to the caller.

The number of snapshot blocks will then be updated with
NILFS_IOCTL_SET_SUINFO ioctl.

Signed-off-by: Andreas Rohner <[email protected]>
---
 include/nilfs.h              |  9 +++++++++
 include/nilfs2_fs.h          | 12 ++++++++----
 lib/feature.c                |  2 ++
 lib/gc.c                     | 19 ++++++++++++++-----
 lib/nilfs.c                  |  2 ++
 man/mkfs.nilfs2.8            |  6 ++++++
 sbin/mkfs/mkfs.c             |  3 ++-
 sbin/nilfs-tune/nilfs-tune.c |  6 ++++--
 8 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/include/nilfs.h b/include/nilfs.h
index 8511163..e84656b 100644
--- a/include/nilfs.h
+++ b/include/nilfs.h
@@ -131,6 +131,7 @@ struct nilfs {
 #define NILFS_OPT_MMAP         0x01
 #define NILFS_OPT_SET_SUINFO   0x02
 #define NILFS_OPT_TRACK_LIVE_BLKS      0x04
+#define NILFS_OPT_TRACK_SNAPSHOTS      0x08
 
 
 struct nilfs *nilfs_open(const char *, const char *, int);
@@ -161,6 +162,7 @@ nilfs_opt_test_##name(const struct nilfs *nilfs)            
        \
 
 NILFS_OPT_FLAG(SET_SUINFO, set_suinfo);
 NILFS_OPT_FLAG(TRACK_LIVE_BLKS, track_live_blks);
+NILFS_OPT_FLAG(TRACK_SNAPSHOTS, track_snapshots);
 
 nilfs_cno_t nilfs_get_oldest_cno(struct nilfs *);
 
@@ -356,4 +358,11 @@ static inline int nilfs_feature_track_live_blks(const 
struct nilfs *nilfs)
                (fc & NILFS_FEATURE_COMPAT_SUFILE_EXTENSION);
 }
 
+static inline int nilfs_feature_track_snapshots(const struct nilfs *nilfs)
+{
+       __u64 fc = le64_to_cpu(nilfs->n_sb->s_feature_compat);
+       return (fc & NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS) &&
+               nilfs_feature_track_live_blks(nilfs);
+}
+
 #endif /* NILFS_H */
diff --git a/include/nilfs2_fs.h b/include/nilfs2_fs.h
index 427ca53..f1f315c 100644
--- a/include/nilfs2_fs.h
+++ b/include/nilfs2_fs.h
@@ -221,11 +221,13 @@ struct nilfs_super_block {
  */
 #define NILFS_FEATURE_COMPAT_SUFILE_EXTENSION          (1ULL << 0)
 #define NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS           (1ULL << 1)
+#define NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS           (1ULL << 2)
 
 #define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT            (1ULL << 0)
 
 #define NILFS_FEATURE_COMPAT_SUPP      (NILFS_FEATURE_COMPAT_SUFILE_EXTENSION \
-                               | NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS)
+                               | NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS \
+                               | NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS)
 #define NILFS_FEATURE_COMPAT_RO_SUPP   NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT
 #define NILFS_FEATURE_INCOMPAT_SUPP    0ULL
 
@@ -630,7 +632,7 @@ struct nilfs_segment_usage {
        __le32 su_nblocks;
        __le32 su_flags;
        __le32 su_nlive_blks;
-       __le32 su_pad;
+       __le32 su_nsnapshot_blks;
        __le64 su_nlive_lastmod;
 };
 
@@ -682,7 +684,7 @@ nilfs_segment_usage_set_clean(struct nilfs_segment_usage 
*su, size_t susz)
        su->su_flags = cpu_to_le32(0);
        if (susz >= NILFS_EXT_SEGMENT_USAGE_SIZE) {
                su->su_nlive_blks = cpu_to_le32(0);
-               su->su_pad = cpu_to_le32(0);
+               su->su_nsnapshot_blks = cpu_to_le32(0);
                su->su_nlive_lastmod = cpu_to_le64(0);
        }
 }
@@ -723,7 +725,7 @@ struct nilfs_suinfo {
        __u32 sui_nblocks;
        __u32 sui_flags;
        __u32 sui_nlive_blks;
-       __u32 sui_pad;
+       __u32 sui_nsnapshot_blks;
        __u64 sui_nlive_lastmod;
 };
 
@@ -764,6 +766,7 @@ enum {
        NILFS_SUINFO_UPDATE_FLAGS,
        NILFS_SUINFO_UPDATE_NLIVE_BLKS,
        NILFS_SUINFO_UPDATE_NLIVE_LASTMOD,
+       NILFS_SUINFO_UPDATE_NSNAPSHOT_BLKS,
        __NR_NILFS_SUINFO_UPDATE_FIELDS,
 };
 
@@ -788,6 +791,7 @@ NILFS_SUINFO_UPDATE_FNS(LASTMOD, lastmod)
 NILFS_SUINFO_UPDATE_FNS(NBLOCKS, nblocks)
 NILFS_SUINFO_UPDATE_FNS(FLAGS, flags)
 NILFS_SUINFO_UPDATE_FNS(NLIVE_BLKS, nlive_blks)
+NILFS_SUINFO_UPDATE_FNS(NSNAPSHOT_BLKS, nsnapshot_blks)
 NILFS_SUINFO_UPDATE_FNS(NLIVE_LASTMOD, nlive_lastmod)
 
 enum {
diff --git a/lib/feature.c b/lib/feature.c
index ebe8c3f..376fa53 100644
--- a/lib/feature.c
+++ b/lib/feature.c
@@ -59,6 +59,8 @@ static const struct nilfs_feature features[] = {
          NILFS_FEATURE_COMPAT_SUFILE_EXTENSION, "sufile_ext" },
        { NILFS_FEATURE_TYPE_COMPAT,
          NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS, "track_live_blks" },
+       { NILFS_FEATURE_TYPE_COMPAT,
+         NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS, "track_snapshots" },
        /* Read-only compat features */
        { NILFS_FEATURE_TYPE_COMPAT_RO,
          NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT, "block_count" },
diff --git a/lib/gc.c b/lib/gc.c
index a2461b9..f1b8b85 100644
--- a/lib/gc.c
+++ b/lib/gc.c
@@ -629,12 +629,13 @@ static int nilfs_toss_bdescs(struct nilfs_vector *bdescv)
 static size_t nilfs_count_nlive_blks(const struct nilfs *nilfs,
                                     __u64 segnum,
                                     struct nilfs_vector *vdescv,
-                                    struct nilfs_vector *bdescv)
+                                    struct nilfs_vector *bdescv,
+                                    size_t *pnss)
 {
        struct nilfs_vdesc *vdesc;
        struct nilfs_bdesc *bdesc;
        int i;
-       size_t res = 0;
+       size_t res = 0, nss = 0;
 
        for (i = 0; i < nilfs_vector_get_size(bdescv); i++) {
                bdesc = nilfs_vector_get_element(bdescv, i);
@@ -651,10 +652,16 @@ static size_t nilfs_count_nlive_blks(const struct nilfs 
*nilfs,
 
                if (nilfs_get_segnum_of_block(nilfs, vdesc->vd_blocknr) ==
                    segnum && (nilfs_vdesc_snapshot(vdesc) ||
-                   !nilfs_vdesc_protection_period(vdesc)))
+                   !nilfs_vdesc_protection_period(vdesc))) {
                        ++res;
+                       if (nilfs_vdesc_snapshot(vdesc))
+                               ++nss;
+               }
        }
 
+       if (pnss)
+               *pnss = nss;
+
        return res;
 }
 
@@ -685,7 +692,7 @@ static int nilfs_try_set_suinfo(struct nilfs *nilfs, __u64 
*segnums,
        struct nilfs_suinfo_update *sup;
        struct timeval tv;
        int ret = -1;
-       size_t i, nblocks;
+       size_t i, nblocks, nss;
 
        supv = nilfs_vector_create(sizeof(struct nilfs_suinfo_update));
        if (!supv)
@@ -709,10 +716,12 @@ static int nilfs_try_set_suinfo(struct nilfs *nilfs, 
__u64 *segnums,
 
                if (nilfs_opt_test_track_live_blks(nilfs)) {
                        nilfs_suinfo_update_set_nlive_blks(sup);
+                       nilfs_suinfo_update_set_nsnapshot_blks(sup);
 
                        nblocks = nilfs_count_nlive_blks(nilfs,
-                                       segnums[i], vdescv, bdescv);
+                                       segnums[i], vdescv, bdescv, &nss);
                        sup->sup_sui.sui_nlive_blks = nblocks;
+                       sup->sup_sui.sui_nsnapshot_blks = nss;
                }
        }
 
diff --git a/lib/nilfs.c b/lib/nilfs.c
index 2067fc0..c453d5b 100644
--- a/lib/nilfs.c
+++ b/lib/nilfs.c
@@ -381,6 +381,8 @@ struct nilfs *nilfs_open(const char *dev, const char *dir, 
int flags)
 
                if (nilfs_feature_track_live_blks(nilfs))
                        nilfs_opt_set_track_live_blks(nilfs);
+               if (nilfs_feature_track_snapshots(nilfs))
+                       nilfs_opt_set_track_snapshots(nilfs);
        }
 
        if (flags &
diff --git a/man/mkfs.nilfs2.8 b/man/mkfs.nilfs2.8
index 2431ac9..c784883 100644
--- a/man/mkfs.nilfs2.8
+++ b/man/mkfs.nilfs2.8
@@ -182,6 +182,12 @@ Enables the tracking of live blocks, which might improve 
the effectiveness of
 garbage collection, but entails a small runtime overhead. It is important to
 note, that this feature depends on sufile_ext, which can only be set
 at file system creation time.
+.TP
+.B track_snapshots
+Enables an efficient heuristic tracking of the number of snapshot blocks in a
+segment. This prevents starvation of segments and improves the overall
+performance. It is important to note, that this feature depends on sufile_ext,
+which can only be set at file system creation time.
 .RE
 .TP
 .B \-q
diff --git a/sbin/mkfs/mkfs.c b/sbin/mkfs/mkfs.c
index 680311c..e69abc8 100644
--- a/sbin/mkfs/mkfs.c
+++ b/sbin/mkfs/mkfs.c
@@ -1083,7 +1083,8 @@ static inline void check_ctime(time_t ctime)
 static const __u64 ok_features[NILFS_MAX_FEATURE_TYPES] = {
        /* Compat */
        NILFS_FEATURE_COMPAT_SUFILE_EXTENSION |
-       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS,
+       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS |
+       NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS,
        /* Read-only compat */
        NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT,
        /* Incompat */
diff --git a/sbin/nilfs-tune/nilfs-tune.c b/sbin/nilfs-tune/nilfs-tune.c
index 7889310..d595366 100644
--- a/sbin/nilfs-tune/nilfs-tune.c
+++ b/sbin/nilfs-tune/nilfs-tune.c
@@ -84,7 +84,8 @@ static void nilfs_tune_usage(void)
 
 static const __u64 ok_features[NILFS_MAX_FEATURE_TYPES] = {
        /* Compat */
-       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS,
+       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS |
+       NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS,
        /* Read-only compat */
        NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT,
        /* Incompat */
@@ -93,7 +94,8 @@ static const __u64 ok_features[NILFS_MAX_FEATURE_TYPES] = {
 
 static const __u64 clear_ok_features[NILFS_MAX_FEATURE_TYPES] = {
        /* Compat */
-       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS,
+       NILFS_FEATURE_COMPAT_TRACK_LIVE_BLKS |
+       NILFS_FEATURE_COMPAT_TRACK_SNAPSHOTS,
        /* Read-only compat */
        NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT,
        /* Incompat */
-- 
2.3.0

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to