]> git.neil.brown.name Git - LaFS.git/commitdiff
Fix some issues with special entries in the segment table.
authorNeilBrown <neilb@suse.de>
Sat, 3 Jul 2010 00:09:58 +0000 (10:09 +1000)
committerNeilBrown <neilb@suse.de>
Sat, 3 Jul 2010 00:51:27 +0000 (10:51 +1000)
We weren't handling all the special cases properly.
So fix that up and use #defines to make it more readable.

Signed-off-by: NeilBrown <neilb@suse.de>
segments.c

index 674c0fb6f8c6f6d735ad68b51729120f587b3a74..0a52a47e9c2ec6250246676d11ed4e5d2c9330b7 100644 (file)
@@ -699,6 +699,11 @@ int lafs_space_alloc(struct fs *fs, int credits, int why)
  * again and remove it properly so it can become cleanable later.
  */
 
+#define SCORE_MAX      0xFFFFFFFC      /* Maximum normal score */
+#define SCORE_ACTIVE   0xFFFFFFFD      /* This segment is being written to */
+#define SCORE_CLEANING 0xFFFFFFFE      /* This segment in being cleaned */
+#define SCORE_DEAD     0xFFFFFFFF      /* This segment is to be removed */
+
 struct segstat {
        u16     next;
        u16     dev;
@@ -1005,7 +1010,7 @@ static void segdelete(struct segtracker *st, struct segstat *ss)
 
 static void segdelete_all(struct segtracker *st, struct fs *fs)
 {
-       /* walk entire skip list.  Any entry with score of 0xFFFFFFFF
+       /* walk entire skip list.  Any entry with score of SCORE_DEAD
         * is deleted
         */
        u16 *where[SEG_NUM_HEIGHTS];
@@ -1017,7 +1022,7 @@ static void segdelete_all(struct segtracker *st, struct fs *fs)
        while (*where[0] != 0xFFFF) {
                u16 pos = *where[0];
                struct segstat *ss = segfollow(st, pos);
-               if (ss->score == 0xFFFFFFFF) {
+               if (ss->score == SCORE_DEAD) {
                        /* delete this entry */
 
                        /* Locking is really bad here */
@@ -1105,7 +1110,7 @@ again:
                if (fs->segtrack->free.first == 0xFFFF)
                        fs->segtrack->free.last = 0xFFFF;
                fs->segtrack->free.cnt--;
-               ss->score = 0xFFFFFFFD;
+               ss->score = SCORE_ACTIVE;
                /* still in table, but unlinked */
                spin_unlock(&fs->lock);
 
@@ -1270,14 +1275,16 @@ static int add_clean(struct fs *fs, unsigned int dev, u32 seg)
                 * the clean list.  If cleanable, set score to 0 to make
                 * sure it is found soon
                 */
-               if (ss->score == 0xFFFFFFFE) {
+               if (ss->score == SCORE_CLEANING) {
                        ss->next = fs->segtrack->clean.first;
                        fs->segtrack->clean.first = where[0][0];
                        if (fs->segtrack->clean.last == 0xFFFF)
                                fs->segtrack->clean.last =
                                        fs->segtrack->clean.first;
                        fs->segtrack->clean.cnt++;
-               } else if (ss->score != 0xFFFFFFFD) {
+               } 
+               if (ss->score != SCORE_ACTIVE) {
+                       /* Must be on the clean list now */
                        ss->score = 0;
                        ss->usage = 0;
                }
@@ -1493,9 +1500,9 @@ retry:
        dprintk("SEG: cleanable %d/%d score=%d usage=%d\n",
                ss->dev, ss->segment, ss->score, ss->usage);
 
+       ss->score = SCORE_CLEANING;
        if (ss->usage == 0) {
                int rv;
-               ss->score = 0xFFFFFFFE;
                spin_unlock(&fs->lock);
                rv = add_clean(fs, ss->dev, ss->segment);
                /* FIXME we dropped the lock, so maybe this could bug?? */
@@ -1554,15 +1561,17 @@ static int add_cleanable(struct fs *fs, unsigned int dev, u32 seg,
                score = youth * usage / segsize + 0x10000;
 
        spin_lock(&fs->lock);
+       if (score > SCORE_MAX)
+               score = SCORE_MAX;
 
        ss = segfind(fs->segtrack, dev, seg, where);
        if (ss) {
                /* already in the table.  Just update the usage.
                 * It must be on the right list.
                 */
-               if (ss->score == 0xFFFFFFFD)
+               if (ss->score == SCORE_ACTIVE)
                        ; /* still in use */
-               if (ss->usage == 0 && ss->score > 0)
+               else if (ss->usage == 0 && ss->score > 0)
                        ; /* on free list, leave it alone */
                else {
                        ss->usage = usage;
@@ -1594,7 +1603,7 @@ static int add_cleanable(struct fs *fs, unsigned int dev, u32 seg,
                fs->segtrack->cleanable.cnt = keep;
                ss = segfollow(fs->segtrack, ssnum);
                while (ss) {
-                       ss->score = 0xFFFFFFFF;
+                       ss->score = SCORE_DEAD;
                        ss = segfollow(fs->segtrack, ss->next);
                }
                segdelete_all(fs->segtrack, fs);
@@ -1920,7 +1929,7 @@ void lafs_empty_segment_table(struct fs *fs)
        fs->segtrack->cleanable.cnt = 0;
        while (ssnum != 0xffff) {
                ss = segfollow(fs->segtrack, ssnum);
-               ss->score = 0xFFFFFFFF;
+               ss->score = SCORE_DEAD;
                ssnum = ss->next;
        }
 
@@ -1930,7 +1939,7 @@ void lafs_empty_segment_table(struct fs *fs)
        fs->segtrack->clean.cnt = 0;
        while (ssnum != 0xffff) {
                ss = segfollow(fs->segtrack, ssnum);
-               ss->score = 0xFFFFFFFF;
+               ss->score = SCORE_DEAD;
                ssnum = ss->next;
        }
 
@@ -1940,7 +1949,7 @@ void lafs_empty_segment_table(struct fs *fs)
        fs->segtrack->free.cnt = 0;
        while (ssnum != 0xffff) {
                ss = segfollow(fs->segtrack, ssnum);
-               ss->score = 0xFFFFFFFF;
+               ss->score = SCORE_DEAD;
                ssnum = ss->next;
        }