
# be careful to keep the spacing in the defines - it counts

export

###################### make targets ########################
#
#   make config          prepares compilation
#   make all             makes driver, server and client
#   make test            minor test example
#   make clean           removes compile from BUILD dir
#   make distclean       removes config cache as well
#   make install         installs driver, utils, manpages
#
############################################################

#################### compile options #######################
#
# turn on to enable SSL channels   - set to 1 to enable secure enbd over SSL
USING_SSL   := 0
# debug level                      - do NOT change to 1 unless asked to
DEBUG       := 0
# root of build                    - you may prefer somewhere more private
BUILD       := /tmp
# will module be on an SMP machine - change to 1 if so
SMP         := 0
# where the kernel sources are     - alter to suit
LINUXDIR    := /lib/modules/$(shell uname -r)/build
# which compiler to use (KCC is for the kernel modules)
ifeq ($(ARCH), mips)
#Steven Hartley (shartley@encentrus.com)
# Added Mips support
CC          := mipsel-linux-gcc
KCC         := mipsel-linux-gcc
else
CC          := gcc
KCC         := gcc
endif
#
############################################################

#################### install options #######################
# placements                       - we will install binaries etc. to here
#
INSTALLPATH := /
PREFIX      := $(INSTALLPATH)/usr/local
#                                  - deduces KERNELRELEASE from LINUXDIR
ifndef KERNELRELEASE
KERNELRELEASE       := $(shell ( grep UTS_RELEASE $(LINUXDIR)/include/linux/version.h|head -1|cut -f 2 -d'"'|tr -d '\n' ) 2>/dev/null || uname -r)
endif
KERNELMAJOR         := $(shell echo $(KERNELRELEASE) | sed -e 's/^\([0-9]*[.][0-9]*\)[.].*$$/\1/')

KERNEL_VERSION      := $(shell echo $(KERNELRELEASE) | sed -e 's/^\([0-9]*\)[.].*$$/\1/')
KERNEL_PATCHLEVEL   := $(shell echo $(KERNELRELEASE) | sed -e 's/^$(KERNEL_VERSION)[.]\([0-9]*\)[.].*$$/\1/')
KERNEL_SUBLEVEL     := $(shell echo $(KERNELRELEASE) | sed -e 's/^$(KERNEL_VERSION)[.]$(KERNEL_PATCHLEVEL)[.]\([0-9]*\).*$$/\1/')
KERNEL_EXTRAVERSION := $(shell echo $(KERNELRELEASE) | sed -e 's/^$(KERNEL_VERSION)[.]$(KERNEL_PATCHLEVEL)[.]$(KERNEL_SUBLEVEL)\(.*\)$$/\1/')
#
#                                  - we install modules to here
MODDIR      := $(INSTALLPATH)/lib/modules/$(KERNELRELEASE)/misc
#                                  - only I change this
ENBDVERSION := 2.4.32
#                                  - what we use to install with
INSTALL     := install
#
############################################################

###################### run options #########################
#
# server machine (runs enbd-server)
SERVER      := localhost
# client machine (runs enbd-client and enbd.o)
CLIENT      := localhost
# client whole device name
DEVICE      := /dev/nda
# server builds these resources for export
EXPORT      := /tmp/core0 /tmp/core1
# each of this many blocks
SRVBLKS     := 4096
# blocksize on client and server 1024, 2048, 4096
BLKSIZ      := 1024
# control port
PORT        := 3033
# how many parallel channels (otherwise use server addr repeats)
OPTSOCK     := -n 4
#OPTSOCK     := $(SERVER) $(SERVER) $(SERVER) $(SERVER)
# session signature                        - default = random
OPTSIG      := -i "NBDabcdefNBD"
# blocksize                                - default = 1024B or highest offer
OPTBLK      := -b $(BLKSIZ)
# use raid linear or raid 0 or raid 1 on server - default = linear
OPTRAID     := -l
# timeout for first negotiate              - default = 60s
OPTTIME     := -t 120
# readonly on server side
OPTRO       := #-r
# server maintains write order until this many ms delay - default = 0ms
OPTORDER    := -w 500
# client uses checksumming protocol at startup
OPTMD5SUM   := #-m
# journalling
OPTJRNL     := #-j /tmp/nbd.log
# module readahead in blocks
RAHEAD      := 20
# module-based request aggregation (default 0)
MERGE_REQS  := 0
# module should check for partition table
CHK_PART    := 0
# module timeout seconds on daemon service
OPT_REQ_TIMEO= -p 5
# module force sync every n seconds
SYNC_INTVL  := 0
# make client asyncronous (default, no). client acks before net replies.
OPTASYNC    := #-a
# make server lock regions on accesses so multiple clients are OK.
OPTLOCK     := #-k
# make server async (default, no)
OPTSASYNC   := #-a
# server result caching
OPTRCACHE   := -h 10000 #-h 0
# enbd module parameters
MODPARMS    := rahead=$(RAHEAD) merge_requests=$(MERGE_REQS) \
               sync=$(SYNC_INTVL) check_partitions=$(CHK_PART)
#
############################################################


SRVSIZ       := $(shell echo $$[ $(SRVBLKS) * $(BLKSIZ) ])

ifeq ($(USING_SSL),1)
SSLSUBDIR    =
CAPATH       =$(SSLSUBDIR)/demoCA
CAFILE       =cacert.pem
SERVERCERT   =$(SSLSUBDIR)/$(SERVER)_server.pem
CLIENTCERT   =$(SSLSUBDIR)/$(CLIENT)_client.pem
OPTCAPATH    = -CApath $(BUILD)/$(CAPATH)
OPTCAFILE    = -CAfile $(BUILD)/$(CAFILE)
OPTSCERT     = -cert $(BUILD)/$(SERVERCERT)
OPTCCERT     = -cert $(BUILD)/$(CLIENTCERT)
OPTVERIFY    = -verify 1
OPTFASTCIPHER= -cipher EXP-RC4-MD5
OPTCLISSL    = $(OPTCAFILE) $(OPTCCERT) $(OPTVERIFY) #$(OPTFASTCIPHER)
OPTSRVSSL    = $(OPTCAFILE) $(OPTSCERT) $(OPTVERIFY)   
endif
OPTSIZ       = -s $(SRVSIZ)

OPTCLI       = $(OPTSOCK) $(OPTBLK) $(OPTSIG) $(OPTTIME) $(OPTMD5SUM) $(OPTCLISSL) $(OPT_REQ_TIMEO) $(OPTJRNL) $(OPTASYNC) 
OPTSRV       = $(OPTSIG) $(OPTTIME) $(OPTBLK) $(OPTRAID) $(OPTSRVSSL) $(OPTRO) $(OPTORDER) $(OPTLOCK) $(OPTSASYNC) $(OPTRCACHE)


VPATH       := $(shell pwd)

CFLAGS       = -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 \
               -D_GNU_SOURCE=1 -D_XOPEN_SOURCE=1 -D_FILE_OFFSET_BITS=64 \
               -Wall -Winline

ifeq ($(DEBUG),0)
  CFLAGS    += -O2
else
  CFLAGS    += -O -g
endif
ifneq ($(SMP),0)
EXTRA_CFLAGS+= -D__SMP__ -DCONFIG_X86_LOCAL_APIC
endif

DATE        := $(shell date)
LIBS         =
LDFLAGS      =
ifeq ($(KERNELMAJOR),2.6)
MODULES      = enbd.ko enbd_ioctl.ko
else
MODULES      = enbd.o enbd_bufferwr.o enbd_ioctl.o enbd_raw.o
endif

ifeq ($(USING_SSL),1)
EXTRA_CFLAGS+= -DUSING_SSL=1
EXTRA_LIBS  += -lssl -lcrypto # -lsocket -lnsl
EXTRA_LDFLAGS=
endif

ifeq ($(ARCH),um)
SUBARCH := $(shell uname -m | sed -e 's/i.86/i386/' -e 's/sun4u/sparc64/' -e 's/arm.*/arm/' -e 's/sa110/arm/')
EXTRA_CFLAGS+=  -DUM_FASTCALL  \
		-D__arch_$(ARCH)__ \
		-DSUBARCH=\"$(SUBARCH)\" \
		-D_LARGEFILE64_SOURCE \
		-I$(LINUXDIR)/arch/$(ARCH)/include \
		-Derrno=kernel_errno \
		-I$(LINUXDIR)/arch/$(ARCH)/kernel/tt/include \
		-I$(LINUXDIR)/arch/$(ARCH)/kernel/skas/include
endif
#Steven Hartley (shartley@encentrus.com)
# Added Mips support
ifeq ($(ARCH), mips)
XCOMPILE     = --host="$(KCC)"
endif


SYSTEM      := $(shell uname -s)

.PHONY: config foo pretest

all: utils module 

config: $(BUILD)/configure
ifndef LINUXDIR
	@echo 'LINUXDIR Not defined'; false
endif
	export CONFIG_SITE=$(VPATH)/conf/config.$(SYSTEM); \
	cd $(BUILD);  ./configure --srcdir=$(VPATH)/nbd $(XCOMPILE) \
                                  --with-kernel-srcdir=$(LINUXDIR); \
	$(MAKE) VPATH=$(VPATH)/nbd \
                CFLAGS="$(CFLAGS) \
                      -I$(BUILD) \
                      -I$(VPATH)/kernel/linux-$(KERNELMAJOR).x/include \
                      $(EXTRA_CFLAGS) -DDEBUG=$(DEBUG)" \
                EXTRA_LIBS="$(EXTRA_LDFLAGS) $(LIBS) $(EXTRA_LIBS)" \
                $@

nbd/configure: nbd/configure.in
	autoconf $< > $@ && chmod +x $@

$(BUILD)/configure: nbd/configure
	mkdir -p $(BUILD)
	cp $< $@ && chmod +x $@

$(BUILD)/Makefile: $(BUILD)/configure
	$(MAKE) config

utils: $(BUILD)/Makefile
	$(MAKE) -C $(BUILD) VPATH=$(VPATH)/nbd \
                            CFLAGS="$(CFLAGS) \
                                  -I$(BUILD) \
                                  -I$(VPATH)/kernel/linux-$(KERNELMAJOR).x/include \
                                  -I$(LINUXDIR)/include \
                                    $(EXTRA_CFLAGS) \
                                  -DDEBUG=$(DEBUG)" \
                            EXTRA_LIBS="$(EXTRA_LDFLAGS) \
                                        $(LIBS) $(EXTRA_LIBS)" 


module:
ifeq ($(KERNELMAJOR),2.6)
	     @export VPATH="$(VPATH)/kernel/linux-2.6.x"; \
             cp -a "$$VPATH" "$(BUILD)/linux-2.6.x" && \
                   cd "$(BUILD)/linux-2.6.x/drivers/block"; \
             $(MAKE) -C "$(LINUXDIR)" \
                   CC="$(KCC) -I$$VPATH/include" \
                   -f "$$VPATH/Makefile" \
                   SUBDIRS="$(BUILD)/linux-2.6.x/drivers/block/enbd" \
                   KBUILD_VERBOSE=1 \
                   CONFIG_BLK_DEV_ENBD=m \
                   CONFIG_BLK_DEV_ENBD_IOCTL=m \
                   CFLAGS_MODULE="-DMODULE -I\"$$VPATH/include\"" \
                   MODVERDIR="$(BUILD)/linux-2.6.x/.tmp_versions" \
                   VERSION="$(KERNEL_VERSION)" \
                   PATCHLEVEL="$(KERNEL_PATCHLEVEL)" \
                   SUBLEVEL="$(KERNEL_SUBLEVEL)" \
                   EXTRAVERSION="$(KERNEL_EXTRAVERSION)" \
                   $(if $(ARCH),ARCH=$(ARCH)) \
                   modules && \
                   for file in $(MODULES); do \
                     if ! test -s "$(BUILD)/linux-2.6.x/drivers/block/enbd/$$file"; then \
                         ld  -r -o "$(BUILD)/linux-2.6.x/drivers/block/enbd/$$file" "$(BUILD)/linux-2.6.x/drivers/block/enbd/$${file%.ko}.o" "$(BUILD)/linux-2.6.x/drivers/block/enbd/$${file%.ko}.mod.o"; \
                     fi; \
                     cp "$(BUILD)/linux-2.6.x/drivers/block/enbd/$$file" "$(BUILD)/"; \
                   done || \
             { echo "*************************************"; \
               echo "* please apply kernel patch instead *"; \
               echo "*************************************"; \
             } ; exit 0;
else
# Steven Hartley: New Rule for mips cross compiler using Rules.mak
ifeq ($(ARCH),mips)
	@$(MAKE) -C "$(LINUXDIR)" \
                   CC="$(KCC) -I$(VPATH)/kernel/linux-2.4.x/include" \
         	   SUBDIRS="$(VPATH)/kernel/linux-2.4.x/drivers/block" \
         	   VPATH="$(VPATH)/kernel/linux-2.4.x/drivers/block" \
         	   KBUILD_VERBOSE=1 \
         	   CONFIG_BLK_DEV_ENBD=m \
         	   CONFIG_BLK_DEV_ENBD_IOCTL=m \
         	   EXTRA_CFLAGS="-DMODULE \
                                 -I$(VPATH)/kernel/linux-2.4.x/include" \
         	modules
else
	for file in $(MODULES); do \
	  $(MAKE) -C "$(BUILD)" \
                -f "$(VPATH)/kernel/linux/drivers/block/Makefile" \
                   VPATH="$(VPATH)/kernel/linux/drivers/block" \
                   CONFIG_BLK_DEV_ENBD=m \
         	   CONFIG_BLK_DEV_ENBD_IOCTL=m \
                   CC="$(KCC)" \
                   EXTRA_CFLAGS="$(EXTRA_CFLAGS) \
                               -D__KERNEL__ \
                               -DMODULE \
                               -DDEBUG=$(DEBUG) \
                               -DCONFIG_ENBD=m \
                               -DENBD_VERSION='\"$(ENBDVERSION) Date: $(DATE)\"' \
                               -I$(VPATH)/kernel/linux/include \
                               -I$(LINUXDIR)/include \
			       " \
                   TOPDIR="$(LINUXDIR)" \
                   VERSION="$(KERNEL_VERSION)" \
                   PATCHLEVEL="$(KERNEL_PATCHLEVEL)" \
                   SUBLEVEL="$(KERNEL_SUBLEVEL)" \
                   EXTRAVERSION="$(KERNEL_EXTRAVERSION)" \
                   $(if $(ARCH),ARCH=$(ARCH)) \
                   $$file ; \
        done
endif
endif

distclean: clean
	$(MAKE) -C $(BUILD) VPATH=$(VPATH)/nbd $@

clean: utils-clean module-clean

utils-clean:
	$(MAKE) -C $(BUILD) VPATH=$(VPATH)/nbd clean

module-clean:
	cd $(BUILD) && { \
            rm -f enbd.o .enbd.o.flags enbd_*.o .enbd_*.o.flags ; \
            rm -f enbd_*.ko enbd.ko ; \
            rm -fr linux-2.6.x ; \
        }

install: utils-install module-install

utils-install:
	$(MAKE) -C $(BUILD) VPATH=$(VPATH)/nbd PREFIX="$(PREFIX)" install

module-install:
	mkdir -p $(MODDIR); \
	for m in $(MODULES); do \
	        $(INSTALL) $(BUILD)/$$m $(MODDIR)/$$m; \
        done

devices:
	cd /dev; $(VPATH)/nbd/scripts/MAKEDEV $(DEVICE)

FILES := $(shell cat $(VPATH)/FILES)


CMD := sh -c 

ENV = OPTASYNC="$(OPTASYNC)" \
      OPTBLK="$(OPTBLK)" \
      OPTCLISSL="$(OPTCLISSL)" \
      OPTJRNL="$(OPTJRNL)" \
      OPTLOCK="$(OPTLOCK)" \
      OPTMD5SUM="$(OPTMD5SUM)" \
      OPTORDER="$(OPTORDER)" \
      OPTRAID="$(OPTRAID)" \
      OPTRCACHE="$(OPTRCACHE)" \
      OPTRO="$(OPTRO)" \
      OPTSASYNC="$(OPTSASYNC)" \
      OPTSIG="$(OPTSIG)" \
      OPTSOCK="$(OPTSOCK)" \
      OPTSRVSSL="$(OPTSRVSSL)" \
      OPTTIME="$(OPTTIME)" \
      OPT_REQ_TIMEO="$(OPT_REQ_TIMEO)" \
      BUILD="$(BUILD)" \
      VPATH="$(BUILD)" \
      DEVICE="$(DEVICE)" \
      SERVER="$(SERVER)" \
      CLIENT="$(CLIENT)" \
      EXPORT="$(EXPORT)" \
      BLKSIZ="$(BLKSIZ)" \
      SRVSIZ="$(SRVSIZ)" \
      RAHEAD="$(RAHEAD)" \
      MERGE_REQS="$(MERGE_REQS)" \
      CHK_PART="$(CHK_PART)" 
	

pretest:
	@if ! /sbin/lsmod | grep -wq enbd; then \
	    echo "Please load the enbd and enbd_ioctl modules first."; \
            exit 1; \
	fi
	@if ! /sbin/lsmod | grep -wq enbd_ioctl; then \
	    echo "Please load the enbd AND enbd_ioctl modules first."; \
            exit 1; \
	fi

# just start server and client (modules already loaded)
notest: pretest
	@export $(ENV); $(VPATH)/nbd/enbd-maketest --notest --noreload; \
	echo done
# assume modules already loaded
test:   pretest
	@export $(ENV); $(SUDO) $(VPATH)/nbd/enbd-maketest --noreload; \
	echo done

ifeq ($(USING_SSL),1)
install-server-certs:
	$(MAKE) -C $(BUILD) -f $(VPATH)/ssl/Makefile VPATH=$(VPATH)/ssl $@
install-client-certs:
	$(MAKE) -C $(BUILD) -f $(VPATH)/ssl/Makefile VPATH=$(VPATH)/ssl $@
install-master-certs:
	$(MAKE) -C $(BUILD) -f $(VPATH)/ssl/Makefile VPATH=$(VPATH)/ssl $@
install-all-certs:
	$(MAKE) -C $(BUILD) -f $(VPATH)/ssl/Makefile VPATH=$(VPATH)/ssl $@
install-clean:
	$(MAKE) -C $(BUILD) -f $(VPATH)/ssl/Makefile VPATH=$(VPATH)/ssl $@
else
install-server-certs:
install-client-certs:
install-master-certs:
install-all-certs:
install-clean:
endif 

IS_ROOT := $(shell [ `id -u` = 0 ] && echo yes || echo no)
ifeq ($(IS_ROOT),yes)
  SUDO := 
else
  SUDO := sudo
endif


test-reconnect:
	 $(CMD) "time dd if=/dev/zero of=$(DEVICE) bs=$(BLKSIZ) count=5"
	 $(CMD) "$(SUDO) kill `pstree -p | grep enbd-server | head -1 | tr -d 'a-zA-Z-|()'`"
	 $(CMD) "time dd if=/dev/zero of=$(DEVICE) bs=$(BLKSIZ) count=5"
	 $(CMD) "$(SUDO) nice -19 $(BUILD)/enbd-server $(PORT) $(EXPORT) $(OPTSRV) ; pstree -p | grep enbd-server; sleep 300" & 

test-regress:
	-@$(CMD) "time dd if=/dev/zero of=$(DEVICE) bs=1024 " </dev/null & 
	 $(CMD) "sleep 5 ; $(SUDO) kill `ps aux | grep enbd-server | grep -v grep | awk '{ print $$2 }' | tail -1`" &


rescue: 
	export $(ENV); $(VPATH)/nbd/enbd-maketest --stop;  \
	export $(ENV); $(VPATH)/nbd/enbd-maketest --unload; 
	echo done

KERNEL_PATCH := kernel/patches/enbd-$(shell echo $(KERNELRELEASE) | sed -e 's/-.*//').pat

kernel_patches:
	$(MAKE) $(KERNEL_PATCH) > /tmp/`basename $(KERNEL_PATCH)` 

.PHONY: $(KERNEL_PATCH)

$(KERNEL_PATCH): 
	kernel_patch=$(KERNEL_PATCH); \
        if [ ! -e $$kernel_patch ]; then exit 1; fi ; \
        pwd=`pwd`; \
	cd $(LINUXDIR)/.. ; \
	diffstat $$pwd/$$kernel_patch | awk '{ if ( $$2 == "|")  print $$1 }' | while read file; do \
	    if [ -e `basename $(LINUXDIR)`/$$file.pre-enbd ]; then \
	      diff -u `basename $(LINUXDIR)`/$$file{.pre-enbd,}; \
	    else \
	      diff -u --label=`basename $(LINUXDIR)`/$$file.pre-enbd - `basename $(LINUXDIR)`/$$file </dev/null; \
	    fi; \
	  done ; true


