Skip to content
17 changes: 9 additions & 8 deletions CLI/eio_cli
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ def sanity(hdd, ssd):
# Performs a very basic regression of operations

modes = {3:"Write Through", 1:"Write Back", 2:"Read Only",0:"N/A"}
policies = {3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}
policies = {4:"lifo",3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}
blksizes = {"4096":4096, "2048":2048, "8192":8192,"":0}
for mode in ["wb","wt","ro"]:
for policy in ["rand","fifo","lru"]:
for policy in ["lifo","rand","fifo","lru"]:
for blksize in ["4096","2048","8192"]:
cache = Cache_rec(name = "test_cache", src_name = hdd,\
ssd_name = ssd, policy = policy, mode = mode,\
Expand Down Expand Up @@ -265,7 +265,7 @@ class Cache_rec(Structure):
blksize="", assoc=""):

modes = {"wt":3,"wb":1,"ro":2,"":0}
policies = {"rand":3,"fifo":1, "lru":2,"":0}
policies = {"lifo":4,"rand":3,"fifo":1, "lru":2,"":0}
blksizes = {"4096":4096, "2048":2048, "8192":8192,"":0}
associativity = {2048:128, 4096:256, 8192:512,0:0}

Expand All @@ -288,7 +288,7 @@ class Cache_rec(Structure):

# Display Cache info
modes = {3:"Write Through", 1:"Write Back", 2:"Read Only",0:"N/A"}
policies = {3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}
policies = {4:"lifo", 3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}

print "Cache Name : " + self.name
print "Source Device : " + self.src_name
Expand Down Expand Up @@ -404,7 +404,7 @@ class Cache_rec(Structure):
cache_match_expr = make_udev_match_expr(self.ssd_name, self.name)
print cache_match_expr
modes = {3:"wt", 1:"wb", 2:"ro",0:"N/A"}
policies = {3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}
policies = {4:"lifo", 3:"rand", 1:"fifo", 2:"lru", 0:"N/A"}

try:
udev_rule = udev_template.replace("<cache_name>",\
Expand Down Expand Up @@ -485,7 +485,7 @@ def create_parser():
parser_edit.add_argument("-m", action="store", dest="mode", \
choices=["wb","wt","ro"], help="cache mode",default="")
parser_edit.add_argument("-p", action="store", dest="policy", \
choices=["rand","fifo","lru"], help="cache \
choices=["lifo","rand","fifo","lru"], help="cache \
replacement policy",default="")

#info
Expand All @@ -504,7 +504,7 @@ def create_parser():
parser_create.add_argument("-s", action="store", dest="ssd",\
required=True, help="name of the ssd device")
parser_create.add_argument("-p", action="store", dest="policy",\
choices=["rand","fifo","lru"],\
choices=["lifo","rand","fifo","lru"],\
help="cache replacement policy",default="lru")
parser_create.add_argument("-m", action="store", dest="mode",\
choices=["wb","wt","ro"],\
Expand All @@ -521,7 +521,7 @@ def create_parser():
parser_enable.add_argument("-s", action="store", dest="ssd",\
required=True, help="name of the ssd device")
parser_enable.add_argument("-p", action="store", dest="policy",
choices=["rand","fifo","lru"],\
choices=["lifo","rand","fifo","lru"],\
help="cache replacement policy",default="lru")
parser_enable.add_argument("-m", action="store", dest="mode",\
choices=["wb","wt","ro"],\
Expand Down Expand Up @@ -563,6 +563,7 @@ def main():
run_cmd("/sbin/modprobe enhanceio_fifo")
run_cmd("/sbin/modprobe enhanceio_lru")
run_cmd("/sbin/modprobe enhanceio_rand")
run_cmd("/sbin/modprobe enhanceio_lifo")

f = open("/run/eio.lock", "w")
fcntl.flock(f, fcntl.LOCK_EX)
Expand Down
2 changes: 1 addition & 1 deletion Driver/enhanceio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ config ENHANCEIO
The caching engine is a loadable kernel module ("enhanceio.ko")
implemented as a device mapper target. The cache replacement
policies are implemented as loadable kernel modules
("enhanceio_fifo.ko", "enhanceio_lru.ko") that register with
("enhanceio_fifo.ko", "enhanceio_lru.ko", "enhanceio_lifo.ko") that register with
the caching engine module.

If unsure, say N.
4 changes: 3 additions & 1 deletion Driver/enhanceio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ KERNEL_SOURCE_VERSION ?= $(shell uname -r)
KERNEL_TREE ?= /lib/modules/$(KERNEL_SOURCE_VERSION)/build
EXTRA_CFLAGS += -I$(KERNEL_TREE)/drivers/md -I./ -DCOMMIT_REV="\"$(COMMIT_REV)\""
EXTRA_CFLAGS += -I$(KERNEL_TREE)/include/ -I$(KERNEL_TREE)/include/linux
obj-m += enhanceio.o enhanceio_lru.o enhanceio_fifo.o enhanceio_rand.o
obj-m += enhanceio.o enhanceio_lru.o enhanceio_fifo.o enhanceio_rand.o enhanceio_lifo.o
enhanceio-y += \
eio_conf.o \
eio_ioctl.o \
Expand All @@ -20,6 +20,7 @@ enhanceio-y += \
eio_ttc.o
enhanceio_fifo-y += eio_fifo.o
enhanceio_rand-y += eio_rand.o
enhanceio_lifo-y += eio_lifo.o
enhanceio_lru-y += eio_lru.o
.PHONY: all
all: modules
Expand All @@ -33,6 +34,7 @@ modules_install: modules
install -o root -g root -m 0755 enhanceio_rand.ko $(DESTDIR)/lib/modules/$(KERNEL_SOURCE_VERSION)/extra/enhanceio/
install -o root -g root -m 0755 enhanceio_fifo.ko $(DESTDIR)/lib/modules/$(KERNEL_SOURCE_VERSION)/extra/enhanceio/
install -o root -g root -m 0755 enhanceio_lru.ko $(DESTDIR)/lib/modules/$(KERNEL_SOURCE_VERSION)/extra/enhanceio/
install -o root -g root -m 0755 enhanceio_lifo.ko $(DESTDIR)/lib/modules/$(KERNEL_SOURCE_VERSION)/extra/enhanceio/
depmod -a
.PHONY: install
install: modules_install
Expand Down
4 changes: 4 additions & 0 deletions Driver/enhanceio/dkms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ DEST_MODULE_LOCATION[1]="/updates"

BUILT_MODULE_NAME[2]="enhanceio_lru"
DEST_MODULE_LOCATION[2]="/updates"


BUILT_MODULE_NAME[3]="enhanceio_lifo"
DEST_MODULE_LOCATION[3]="/updates"
4 changes: 3 additions & 1 deletion Driver/enhanceio/eio.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,9 @@ struct flash_cacheblock {
#define CACHE_REPL_FIFO 1
#define CACHE_REPL_LRU 2
#define CACHE_REPL_RANDOM 3
#define CACHE_REPL_LIFO 4
#define CACHE_REPL_FIRST CACHE_REPL_FIFO
#define CACHE_REPL_LAST CACHE_REPL_RANDOM
#define CACHE_REPL_LAST CACHE_REPL_LIFO
#define CACHE_REPL_DEFAULT CACHE_REPL_FIFO

struct eio_policy_and_name {
Expand All @@ -393,6 +394,7 @@ static const struct eio_policy_and_name eio_policy_names[] = {
{ CACHE_REPL_FIFO, "fifo" },
{ CACHE_REPL_LRU, "lru" },
{ CACHE_REPL_RANDOM, "rand" },
{ CACHE_REPL_LIFO, "lifo" },
};


Expand Down
2 changes: 1 addition & 1 deletion Driver/enhanceio/eio_fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,4 @@ module_exit(fifo_unregister);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("FIFO policy for EnhanceIO");
MODULE_AUTHOR("STEC, Inc. based on code by Facebook");
MODULE_AUTHOR("STEC, Inc. based on code by Facebook");
237 changes: 237 additions & 0 deletions Driver/enhanceio/eio_lifo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/*
* eio_lifo.c
*
* Copyright (C) 2012 STEC, Inc. All rights not specifically granted
* under a license included herein are reserved
* Made EnhanceIO specific changes.
* Saied Kazemi <skazemi@stec-inc.com>
* Siddharth Choudhuri <schoudhuri@stec-inc.com>
*
* Copyright 2010 Facebook, Inc.
* Author: Mohan Srinivasan (mohan@facebook.com)
*
* Based on DM-Cache:
* Copyright (C) International Business Machines Corp., 2006
* Author: Ming Zhao (mingzhao@ufl.edu)
*
* 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; under version 2 of the License.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include "eio.h"
/* Generic policy functions prototypes */
int eio_lifo_init(struct cache_c *);
void eio_lifo_exit(void);
int eio_lifo_cache_sets_init(struct eio_policy *);
int eio_lifo_cache_blk_init(struct eio_policy *);
void eio_lifo_find_reclaim_dbn(struct eio_policy *, index_t, index_t *);
int eio_lifo_clean_set(struct eio_policy *, index_t, int);

/* Per policy instance initialization */
struct eio_policy *eio_lifo_instance_init(void);

/* Per cache set data structure */
struct eio_lifo_cache_set {
index_t set_lifo_next;
index_t set_clean_next;
};

/*
* Context that captures the LIFO replacement policy
*/
static struct eio_policy_header eio_lifo_ops = {
.sph_name = CACHE_REPL_LIFO,
.sph_instance_init = eio_lifo_instance_init,
};

/*
* Initialize LIFO policy.
*/
int eio_lifo_init(struct cache_c *dmc)
{
return 0;
}

/*
* Initialize LIFO data structure called from ctr.
*/
int eio_lifo_cache_sets_init(struct eio_policy *p_ops)
{
int i;
sector_t order;
struct cache_c *dmc = p_ops->sp_dmc;
struct eio_lifo_cache_set *cache_sets;

pr_info("Initializing lifo cache sets\n");
order = (dmc->size >> dmc->consecutive_shift) *
sizeof(struct eio_lifo_cache_set);

dmc->sp_cache_set = vmalloc((size_t)order);
if (dmc->sp_cache_set == NULL)
return -ENOMEM;

cache_sets = (struct eio_lifo_cache_set *)dmc->sp_cache_set;

for (i = 0; i < (int)(dmc->size >> dmc->consecutive_shift); i++) {
cache_sets[i].set_lifo_next = i * dmc->assoc;
cache_sets[i].set_clean_next = i * dmc->assoc;
}

return 0;
}

/*
* The actual function that returns a victim block in index.
*/
void eio_lifo_find_reclaim_dbn(struct eio_policy *p_ops, index_t start_index,
index_t *index)
{
index_t end_index;
int slots_searched = 0;
index_t i;
index_t set;
struct eio_lifo_cache_set *cache_sets;
struct cache_c *dmc = p_ops->sp_dmc;

set = start_index / dmc->assoc;
end_index = start_index + dmc->assoc;
cache_sets = (struct eio_lifo_cache_set *)dmc->sp_cache_set;

i = cache_sets[set].set_lifo_next;
while (slots_searched < (int)dmc->assoc) {
EIO_ASSERT(i >= start_index);
EIO_ASSERT(i < end_index);
if (EIO_CACHE_STATE_GET(dmc, i) == VALID) {
*index = i;
break;
}
slots_searched++;
i--;
if (i == start_index - 1)
i = end_index - 1;
}
i--;
if (i == start_index - 1)
i = end_index - 1;
cache_sets[set].set_lifo_next = i;
}

/*
* Go through the entire set and clean.
*/
int eio_lifo_clean_set(struct eio_policy *p_ops, index_t set, int to_clean)
{
index_t i;
int scanned = 0, nr_writes = 0;
index_t start_index;
index_t end_index;
struct eio_lifo_cache_set *cache_sets;
struct cache_c *dmc;

dmc = p_ops->sp_dmc;
cache_sets = (struct eio_lifo_cache_set *)dmc->sp_cache_set;
start_index = set * dmc->assoc;
end_index = start_index + dmc->assoc;
i = cache_sets[set].set_clean_next;

while ((scanned < (int)dmc->assoc) && (nr_writes < to_clean)) {
if ((EIO_CACHE_STATE_GET(dmc, i) & (DIRTY | BLOCK_IO_INPROG)) == DIRTY) {
EIO_CACHE_STATE_ON(dmc, i, DISKWRITEINPROG);
nr_writes++;
}
scanned++;
i++;
if (i == end_index)
i = start_index;
}
cache_sets[set].set_clean_next = i;

return nr_writes;
}

/*
* LIFO is per set, so do nothing on a per block init.
*/
int eio_lifo_cache_blk_init(struct eio_policy *p_ops)
{
return 0;
}

/*
* Allocate a new instance of eio_policy per dmc
*/
struct eio_policy *eio_lifo_instance_init(void)
{
struct eio_policy *new_instance;

new_instance = vmalloc(sizeof(struct eio_policy));
if (new_instance == NULL) {
pr_err("ssdscache_lifo_instance_init: vmalloc failed");
return NULL;
}

/* Initialize the LIFO specific functions and variables */
new_instance->sp_name = CACHE_REPL_LIFO;
new_instance->sp_policy.lru = NULL;
new_instance->sp_repl_init = eio_lifo_init;
new_instance->sp_repl_exit = eio_lifo_exit;
new_instance->sp_repl_sets_init = eio_lifo_cache_sets_init;
new_instance->sp_repl_blk_init = eio_lifo_cache_blk_init;
new_instance->sp_find_reclaim_dbn = eio_lifo_find_reclaim_dbn;
new_instance->sp_clean_set = eio_lifo_clean_set;
new_instance->sp_dmc = NULL;

try_module_get(THIS_MODULE);

pr_info("eio_lifo_instance_init: created new instance of LIFO");

return new_instance;
}

/*
* Cleanup an instance of eio_policy (called from dtr).
*/
void eio_lifo_exit(void)
{
module_put(THIS_MODULE);
}

static
int __init lifo_register(void)
{
int ret;

ret = eio_register_policy(&eio_lifo_ops);
if (ret != 0)
pr_info("eio_lifo already registered");

return ret;
}

static
void __exit lifo_unregister(void)
{
int ret;

ret = eio_unregister_policy(&eio_lifo_ops);
if (ret != 0)
pr_err("eio_lifo unregister failed");
}

module_init(lifo_register);
module_exit(lifo_unregister);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LIFO policy for EnhanceIO");
MODULE_AUTHOR("STEC, Inc. based on code by Facebook");
2 changes: 2 additions & 0 deletions Install-EIO
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ _LoadMods ()
${SBPREFIX}modprobe enhanceio_rand &&
${SBPREFIX}modprobe enhanceio_fifo &&
${SBPREFIX}modprobe enhanceio_lru &&
${SBPREFIX}modprobe enhanceio_lifo &&

return 0
return 1
}
Expand Down
1 change: 1 addition & 0 deletions Install.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Loading Modules:
# modprode enhanceio_rand
# modprode enhanceio_fifo
# modprode enhanceio_lru
# modprode enhanceio_lifo

Once the modules have been loaded you will be able to use eio_cli to create/modify caches.

Expand Down