设计新Xlator扩展GlusterFS[转]
原文:http://www.linuxidc.com/Linux/2013-08/89105.htm
1. GlusterFS概述
GlusterFS是一個開源的分布式文件系統,具有強大的Scale-Out橫向擴展能力,通過擴展能夠支持數PB存儲容量和處理數千客戶端。GlusterFS借助TCP/IP或InfiniBand RDMA網絡將物理分布的存儲資源聚集在一起,使用單一全局命名空間來管理數據。GlusterFS基于可堆疊的用戶空間設計,可為各種不同的數據負載提供優異的性能。
GlusterFS支持運行在任何標準IP網絡上標準應用程序的標準客戶端,用戶可以在全局統一的命名空間中使用Glusterfs/NFS/CIFS等標準協議來訪問應用數據。GlusterFS使得用戶可擺脫原有的獨立、高成本的封閉存儲系統,能夠利用普通廉價的存儲設備來部署可集中管理、橫向擴展、虛擬化的存儲池,存儲容量可擴展至TB/PB級。Glusterfs的深入剖析請參考”GlusterFS集群文件系統研究”一文?http://www.linuxidc.com/Linux/2011-12/50579.htm?。GlusterFS主要特征如下:
1) 擴展性和高性能
2) 高可用性
3) 全局統一命名空間
4) 彈性哈希算法
5) 彈性卷管理
6) 基于標準協議
2. Xlator工作原理
GlusterFS采用模塊化、堆棧式的架構,可通過靈活的配置支持高度定制化的應用環境,比如大文件存儲、海量小文件存儲、云存儲、多傳輸協議應用等。每個功能以模塊形式實現,然后以積木方式進行簡單的組合,即可實現復雜的功能。比如,Replicate模塊可實現RAID1,Stripe模塊可實現RAID0,通過兩者的組合可實現RAID10和RAID01,同時獲得高性能和高可靠性。
GlusterFS堆棧式設計思想源自GNU/Hurd微內核操作系統,具有很強的系統擴展能力,系統設計實現復雜性降低很多,基本功能模塊的堆棧式組合就可以實現強大的功能。基本模塊稱為Translator,它是GlusterFS提供的一種強大文件系統功能擴展機制,借助這種良好定義的接口可以高效簡便地擴展文件系統的功能。
GlusterFS中所有的功能都通過Translator機制實現,服務端與客戶端模塊接口是兼容的,同一個translator可同時在兩邊加載。每個translator都是SO動態庫,運行時根據配置動態加載。每個模塊實現特定基本功能,比如Cluster, Storage, Performance, Protocol,Features等,基本簡單的模塊可以通過堆棧式的組合來實現復雜的功能,Translator可以把對外部系統的訪問轉換成目標系統的適當調用。大部分模塊都運行在客戶端,比如合成器、I/O調度器和性能優化等,服務端相對簡單許多。客戶端和存儲服務器均有自己的存儲棧,構成了一棵Translator功能樹,應用了若干模塊。模塊化和堆棧式的架構設計,極大降低了系統設計復雜性,簡化了系統的實現、升級以及系統維護。
?
Gluster卷Translator棧圖
GlusterFS概念中,由一系列translator構成的完整功能棧稱之為Volume(如上圖所示),分配給一個volume的本地文件系統稱為brick,被至少一個translator處理過的brick稱為subvolume。FUSE模塊位于客戶端,POSIX模塊位于服務器端,它們通常是volume中首個或最后一個模塊,依賴于訪問數據流的方向。中間部分會再加入其他功能的模塊,構成一個完整的volume,這些模塊通過一張圖(graph)有機結合在一起。這是一種多層設計,運行時通過有序地向上或向下調用相鄰模塊接口來傳遞消息,調用關系由每個模塊根據自身功能和translator圖來決定。由translator實現的卷的完整數據流,如下圖所示。
?
GlusterFS數據流
3. Xlator結構和相關API
Xlator是高度模塊化的組件,具有良好定義的內部結構,包括結構體和接口函數原型定義。因此,要實現一個xlator,必須嚴格按照定義來實現,具體講就是要實現xlator.h中定義的xlator_fops、xlator_cbks、init、fini、volume_options等結構體中的參數和函數指針,描述如下:
struct xlator_fops {
? ? ? ? fop_lookup_t? ? ? ? lookup;
? ? ? ? fop_stat_t? ? ? ? ? stat;
? ? ? ? fop_fstat_t? ? ? ? ? fstat;
? ? ? ? fop_truncate_t? ? ? truncate;
? ? ? ? fop_ftruncate_t? ? ? ftruncate;
? ? ? ? fop_access_t? ? ? ? access;
? ? ? ? fop_readlink_t? ? ? readlink;
? ? ? ? fop_mknod_t? ? ? ? ? mknod;
? ? ? ? fop_mkdir_t? ? ? ? ? mkdir;
? ? ? ? fop_unlink_t? ? ? ? unlink;
? ? ? ? fop_rmdir_t? ? ? ? ? rmdir;
? ? ? ? fop_symlink_t? ? ? ? symlink;
? ? ? ? fop_rename_t? ? ? ? rename;
? ? ? ? fop_link_t? ? ? ? ? link;
? ? ? ? fop_create_t? ? ? ? create;
? ? ? ? fop_open_t? ? ? ? ? open;
? ? ? ? fop_readv_t? ? ? ? ? readv;
? ? ? ? fop_writev_t? ? ? ? writev;
? ? ? ? fop_flush_t? ? ? ? ? flush;
? ? ? ? fop_fsync_t? ? ? ? ? fsync;
? ? ? ? fop_opendir_t? ? ? ? opendir;
? ? ? ? fop_readdir_t? ? ? ? readdir;
? ? ? ? fop_readdirp_t? ? ? readdirp;
? ? ? ? fop_fsyncdir_t? ? ? fsyncdir;
? ? ? ? fop_statfs_t? ? ? ? statfs;
? ? ? ? fop_setxattr_t? ? ? setxattr;
? ? ? ? fop_getxattr_t? ? ? getxattr;
? ? ? ? fop_fsetxattr_t? ? ? fsetxattr;
? ? ? ? fop_fgetxattr_t? ? ? fgetxattr;
? ? ? ? fop_removexattr_t? ? removexattr;
? ? ? ? fop_lk_t? ? ? ? ? ? lk;
? ? ? ? fop_inodelk_t? ? ? ? inodelk;
? ? ? ? fop_finodelk_t? ? ? finodelk;
? ? ? ? fop_entrylk_t? ? ? ? entrylk;
? ? ? ? fop_fentrylk_t? ? ? fentrylk;
? ? ? ? fop_rchecksum_t? ? ? rchecksum;
? ? ? ? fop_xattrop_t? ? ? ? xattrop;
? ? ? ? fop_fxattrop_t? ? ? fxattrop;
? ? ? ? fop_setattr_t? ? ? ? setattr;
? ? ? ? fop_fsetattr_t? ? ? fsetattr;
? ? ? ? fop_getspec_t? ? ? ? getspec;
? ? ? ? /* these entries are used for a typechecking hack in STACK_WIND _only_ */
? ? ? ? fop_lookup_cbk_t? ? ? ? lookup_cbk;
? ? ? ? fop_stat_cbk_t? ? ? ? ? stat_cbk;
? ? ? ? fop_fstat_cbk_t? ? ? ? ? fstat_cbk;
? ? ? ? fop_truncate_cbk_t? ? ? truncate_cbk;
? ? ? ? fop_ftruncate_cbk_t? ? ? ftruncate_cbk;
? ? ? ? fop_access_cbk_t? ? ? ? access_cbk;
? ? ? ? fop_readlink_cbk_t? ? ? readlink_cbk;
? ? ? ? fop_mknod_cbk_t? ? ? ? ? mknod_cbk;
? ? ? ? fop_mkdir_cbk_t? ? ? ? ? mkdir_cbk;
? ? ? ? fop_unlink_cbk_t? ? ? ? unlink_cbk;
? ? ? ? fop_rmdir_cbk_t? ? ? ? ? rmdir_cbk;
? ? ? ? fop_symlink_cbk_t? ? ? ? symlink_cbk;
? ? ? ? fop_rename_cbk_t? ? ? ? rename_cbk;
? ? ? ? fop_link_cbk_t? ? ? ? ? link_cbk;
? ? ? ? fop_create_cbk_t? ? ? ? create_cbk;
? ? ? ? fop_open_cbk_t? ? ? ? ? open_cbk;
? ? ? ? fop_readv_cbk_t? ? ? ? ? readv_cbk;
? ? ? ? fop_writev_cbk_t? ? ? ? writev_cbk;
? ? ? ? fop_flush_cbk_t? ? ? ? ? flush_cbk;
? ? ? ? fop_fsync_cbk_t? ? ? ? ? fsync_cbk;
? ? ? ? fop_opendir_cbk_t? ? ? ? opendir_cbk;
? ? ? ? fop_readdir_cbk_t? ? ? ? readdir_cbk;
? ? ? ? fop_readdirp_cbk_t? ? ? readdirp_cbk;
? ? ? ? fop_fsyncdir_cbk_t? ? ? fsyncdir_cbk;
? ? ? ? fop_statfs_cbk_t? ? ? ? statfs_cbk;
? ? ? ? fop_setxattr_cbk_t? ? ? setxattr_cbk;
? ? ? ? fop_getxattr_cbk_t? ? ? getxattr_cbk;
? ? ? ? fop_fsetxattr_cbk_t? ? ? fsetxattr_cbk;
? ? ? ? fop_fgetxattr_cbk_t? ? ? fgetxattr_cbk;
? ? ? ? fop_removexattr_cbk_t? ? removexattr_cbk;
? ? ? ? fop_lk_cbk_t? ? ? ? ? ? lk_cbk;
? ? ? ? fop_inodelk_cbk_t? ? ? ? inodelk_cbk;
? ? ? ? fop_finodelk_cbk_t? ? ? finodelk_cbk;
? ? ? ? fop_entrylk_cbk_t? ? ? ? entrylk_cbk;
? ? ? ? fop_fentrylk_cbk_t? ? ? fentrylk_cbk;
? ? ? ? fop_rchecksum_cbk_t? ? ? rchecksum_cbk;
? ? ? ? fop_xattrop_cbk_t? ? ? ? xattrop_cbk;
? ? ? ? fop_fxattrop_cbk_t? ? ? fxattrop_cbk;
? ? ? ? fop_setattr_cbk_t? ? ? ? setattr_cbk;
? ? ? ? fop_fsetattr_cbk_t? ? ? fsetattr_cbk;
? ? ? ? fop_getspec_cbk_t? ? ? ? getspec_cbk;
};
struct xlator_cbks {
? ? ? ? cbk_forget_t? ? forget;
? ? ? ? cbk_release_t? release;
? ? ? ? cbk_release_t? releasedir;
};
void? ? ? ? ? ? (*fini) (xlator_t *this);
int32_t? ? ? ? ? (*init) (xlator_t *this);
typedef struct volume_options {
? ? ? ? char? ? ? ? ? ? ? ? *key[ZR_VOLUME_MAX_NUM_KEY];
? ? ? ? /* different key, same meaning */
? ? ? ? volume_option_type_t type;
? ? ? ? int64_t? ? ? ? ? ? ? min;? /* 0 means no range */
? ? ? ? int64_t? ? ? ? ? ? ? max;? /* 0 means no range */
? ? ? ? char? ? ? ? ? ? ? ? *value[ZR_OPTION_MAX_ARRAY_SIZE];
? ? ? ? /* If specified, will check for one of
? ? ? ? ? the value from this array */
? ? ? ? char? ? ? ? ? ? ? ? *default_value;
? ? ? ? char? ? ? ? ? ? ? ? *description; /* about the key */
} volume_option_t;
xlator_fops和xlator_cbks結構體中的函數指針在xlator.h中都有嚴格的明確定義,實現時必須完全遵從。其中,xlator_fops是Linux中file_operations, inode_operations和super_operatioins的組合。另外,以上結構體和函數指針名分別確定為fops, cbks, init, fini, options,不可更改。因為xlator最終以SO動態庫形式提供給glusterfs主體程序使用,需要使用統一確定的名稱來加載和定位xlator中函數指針和變量。Init, fini分別用于xlator加載和卸載時的處理工作,這個對于每個xlator的個性化私有數據處理非常有用。如果xlator模板提供的接口和參數無法滿足需求,可以有效利用這兩個接口進行處理。值得一提的是,xlator并不一定要實現以上全部的函數指針和變量,可以僅實現特定相關的部分,其它的部分會在運行時自動填入默認的值,并直接傳遞給下一個translator, 同時指定回調函數,回調函數傳回之前translator的結果。
?Translator采用異步和回調函數的實現機制,這意味著處理特定請求的代碼必須被分為兩個部分:調用函數和回調函數。一個xlator的函數調用下一個translator的函數,然后無阻塞的返回。當調用下一個translator的函數時,回調函數可能會立即被調用,也可能稍后在一個不同的線程上被調用。在兩種情況下,回調函數都不會像同步函數那樣獲取其上下文。GlusterFS提供了幾種方式用于在調用函數及其回調函數間保存和傳遞上下文,但是必須xlator自行處理而不能完全依賴協議棧。
Translator的回調機制主要采用了STACK_WIND和STACK_UNWIND。當xlator fops某個函數被調用,表示接受到一個請求,使用frame stack來表示。Fops函數中執行相應操作,然后可把該請求使用STACK_WIND傳遞給下一個或多個translator。當完成一個請求而不再需要調用下一個translator,或者當任務完成從回調函數中回到上一個translator時需要調用STACK_UNWIND。實際上,最好使用STACK_UNWIND_STRICT,它可以用來指定那類請求你已經完成了。相關宏在stack.h中定義,原型如下:
#define STACK_WIND(frame, rfn, obj, fn, params ...)
#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn,params ...)
#define STACK_UNWIND(frame, params ...)
#define STACK_UNWIND_STRICT(op, frame, params ...)
其中用到的參數如下:?
Frame:stack frame表示請求
Rfn::回調函數,當下一個translator完成時會調用該函數
Obj::正在控制的translator對象
Fn:從下一個translator的fops table中指定要調用的translator函數
Params:任何其他被調用函數的參數(比如,inodes, fd, offset, data buffer)
Cky:cookie,這是一個opaque指針
Op:操作類型,用來檢查附加的參數符合函數的期望
每個translator-stack frame都有一個local指針,用來儲存該translator特定的上下文,這是在調用和回調函數間存儲上下文的主要機制。當stack銷毀時,每個frame的local如果不為NULL都會被傳遞給GF_FREE,但是不會執行其他的清理工作。如果local結構體包含指針或引用其他對象,就需要仔細處理這些。因此比較理想的情況是,內存和其它資源能在stack被銷毀前被釋放,不要完全依賴自動的GFS_GFREE。最為妥當的做法是定義特定translator的銷毀函數,并在STACK_UNWIND返回前手工調用。
Xlator大部分的調用函數和回調函數以文件描述符(fd_t)或inode(inode_t)作為參數。通常translator需要存儲一些自有的上下文,這些上下文獨立于單個請求的生命周期。比如,DHT存儲目錄對應的布局映射(layout map)和某inode最后可知的位置。Glusterfs提供了一系列的函數用于存儲此類上下文。在每種情況下,第二個參數是一個指向translator對象的指針,需要存儲的數據與其相關,存儲的值是一個unsigned的64位整數。這些函數返回0代表成功,在_get和_del函數中使用引用參數而不是返回值。
inode_ctx_put (inode, xlator, value)
inode_ctx_get (inode, xlator, &value)
inode_ctx_del (inode, xlator, &value)
fd_ctx_set (fd, xlator, value)
fd_ctx_get (fd, xlator, &value)
fd_ctx_del (fd, xlator, &value)
傳遞給調用函數和回調函數的inode_t或fd_t指針只是借來(borrowed)引用。如果希望該對象稍后還存在,最好調用inode_ref或fd_ref增加一個持久引用,并且當引用不再需要時調用inode_unref或fd_unref。?
另外一個常用的類型是dict_t,它是一個通用的排序字典或hash-map的數據結構,可用來存放任意類型值并以字符串為鍵值。例如,存儲的值可以是任意大小的有符號或無符號整數,字符串,或二進制。字符串和二進制需要被標記在不需要時由glusterfs函數釋放,或由glibc釋放或根本不釋放。Dict_t*和*data_t對象都是引用計數的,只有當引用數為0時被釋放。同inodes和文件描述符一樣,如果希望通過參數接受的dict_t持久存在,必須調用_ref和_unref處理器生命周期。字典并不是僅用于調用和回調函數,也可用于傳遞不同的模塊選項,包括translator初始化的選項。事實上,目前translator的init函數主要用于解析字典中的選項。向translatro中添加一個選項,需要在translator的options數組中添加一個實體。每一個選項可以是boolean,整數,字符串,路徑,translator名稱,和其它一些自定義類型。如果是字符串,可以指定有效值。解析后的選項和其它的信息可以存放在xlator_t結構體中的private內。
Translators中大部分的logging是通過gf_log函數實現,其參數包括字符串(通常是this->name)、log等級、格式化串以及格式化的其他參數。日志等級分為GF_LOG_ERROR, GF_LOG_WARNING , GF_LOG_LOG和GF_LOG_DEBUG。Xlator可以封裝gfs_log自定義相關宏,或采用現有等級,這樣translator的日志在運行時就能被輸出。設計xlator時,可以添加一個translator 日志等級選項,也可以實現一個特定的xattr調用用于傳遞新值。
4. 構造新Xlator
這里我們通過構造一個稱為NULL的Xlator來梳理構造新xlator的基本方法。NULL Xlator本身不實現具體的功能,僅作為類似Proxy的中轉,用于演示構造xlator的結構和方法。NULL Xlator實現包括四個文件,null.h, null.c, null_fops.h, null_fops.c,其中null_fops.h, null_fops.c與defaults.h, defaults.c完全相同。Null.h內容如下:
#ifndef __NULL_H__
#define __NULL_H__
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "mem-types.h"
typedef struct {
? ? ? ? xlator_t *target;
} null_private_t;
enum gf_null_mem_types_ {
? ? ? ? gf_null_mt_priv_t = gf_common_mt_end + 1,
? ? ? ? gf_null_mt_end
};
#endif /* __NULL_H__ */
其中,自定義了私有數據結構體null_private_t和內部數據類型。Null.c內容如下:
#include <ctype.h>
#include <sys/uio.h>
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "glusterfs.h"
#include "call-stub.h"
#include "defaults.h"
#include "logging.h"
#include "xlator.h"
#include "null.h"
#include "null_fops.h"
int32_t
init (xlator_t *this)
{
? ? ? ? xlator_t *tgt_xl = NULL;
? ? ? ? null_private_t *priv = NULL;
? ? ? ? if (!this->children || this->children->next) {
? ? ? ? ? ? ? ? gf_log (this->name, GF_LOG_ERROR,
? ? ? ? ? ? ? ? ? ? ? ? "FATAL: null should have exactly one child");
? ? ? ? ? ? ? ? return -1;
? ? ? ? }
? ? ? ? priv = GF_CALLOC (1, sizeof (null_private_t), gf_null_mt_priv_t);
? ? ? ? if (!priv)
? ? ? ? ? ? ? ? return -1;
? ? ? ? /* Init priv here */
? ? ? ? priv->target = tgt_xl;
? ? ? ? gf_log (this->name, GF_LOG_DEBUG, "null xlator loaded");
? ? ? ? return 0;
}
void
fini (xlator_t *this)
{
? ? ? ? null_private_t *priv = this->private;
? ? ? ? if (!priv)
? ? ? ? ? ? ? ? return;
? ? ? ? this->private = NULL;
? ? ? ? GF_FREE (priv);
? ? ? ? return;
}
struct xlator_fops fops = {
? ? ? ? .lookup? ? ? ? = null_lookup,
? ? ? ? .stat? ? ? ? ? = null_stat,
? ? ? ? .fstat? ? ? ? ? = null_fstat,
? ? ? ? .truncate? ? ? = null_truncate,
? ? ? ? .ftruncate? ? ? = null_ftruncate,
? ? ? ? .access? ? ? ? = null_access,
? ? ? ? .readlink? ? ? = null_readlink,
? ? ? ? .mknod? ? ? ? ? = null_mknod,
? ? ? ? .mkdir? ? ? ? ? = null_mkdir,
? ? ? ? .unlink? ? ? ? = null_unlink,
? ? ? ? .rmdir? ? ? ? ? = null_rmdir,
? ? ? ? .symlink? ? ? ? = null_symlink,
? ? ? ? .rename? ? ? ? = null_rename,
? ? ? ? .link? ? ? ? ? = null_link,
? ? ? ? .create? ? ? ? = null_create,
? ? ? ? .open? ? ? ? ? = null_open,
? ? ? ? .readv? ? ? ? ? = null_readv,
? ? ? ? .writev? ? ? ? = null_writev,
? ? ? ? .flush? ? ? ? ? = null_flush,
? ? ? ? .fsync? ? ? ? ? = null_fsync,
? ? ? ? .opendir? ? ? ? = null_opendir,
? ? ? ? .readdir? ? ? ? = null_readdir,
? ? ? ? .readdirp? ? ? = null_readdirp,
? ? ? ? .fsyncdir? ? ? = null_fsyncdir,
? ? ? ? .statfs? ? ? ? = null_statfs,
? ? ? ? .setxattr? ? ? = null_setxattr,
? ? ? ? .getxattr? ? ? = null_getxattr,
? ? ? ? .fsetxattr? ? ? = null_fsetxattr,
? ? ? ? .fgetxattr? ? ? = null_fgetxattr,
? ? ? ? .removexattr? ? = null_removexattr,
? ? ? ? .lk? ? ? ? ? ? = null_lk,
? ? ? ? .inodelk? ? ? ? = null_inodelk,
? ? ? ? .finodelk? ? ? = null_finodelk,
? ? ? ? .entrylk? ? ? ? = null_entrylk,
? ? ? ? .fentrylk? ? ? = null_fentrylk,
? ? ? ? .rchecksum? ? ? = null_rchecksum,
? ? ? ? .xattrop? ? ? ? = null_xattrop,
? ? ? ? .fxattrop? ? ? = null_fxattrop,
? ? ? ? .setattr? ? ? ? = null_setattr,
? ? ? ? .fsetattr? ? ? = null_fsetattr,
? ? ? ? .getspec? ? ? ? = null_getspec,
};
struct xlator_cbks cbks = {
? ? ? ? .forget = null_forget,
? ? ? ? .release = null_release,
? ? ? ? .releasedir = null_releasedir,
};
struct volume_options options[] = {
? ? ? ? { .key? = {NULL} },
};
這其中主要實現了上面提到的init和fini函數,fops調用函數指針和cbks回調函數指針,以及卷參數選項options。一個新xlator的代碼基本框架就是如此,這里因為沒有實現具體功能,各種結構體、變量和函數實現都相對非常簡單。如果要實現特定功能的xlator,可以以此為模塊進行擴展。Glusterfs源碼中xlator都是很好的例子,但有些很復雜,不適合初學者,可以先從簡單的rot-13, read-only, bypass, negative-lookup等xlator開始研究,然后構造出自己所需功能的xlator。
5. 編譯新Xlator
設計并編碼實現新Xlator后,我們需要將其編譯成SO形式的動態庫,提供給Glusterfs使用。編譯過程中,需要使用到glusterfs其他部分的相關代碼,要求設置較為復雜的編譯環境。這里我們編寫了Makefile文件設置環境并進行編譯,內容如下:
# Change these to match your source code.
TARGET? = null.so
OBJECTS = null.o null_fops.o
# Change these to match your environment.
GLFS_SRC? = /home/liuag/glusterfs-3.2.5
GLFS_VERS = 3.2.5
GLFS_LIB? = /opt/glusterfs/3.2.5/lib64/
HOST_OS? = GF_LINUX_HOST_OS
# You shouldn't need to change anything below here.
CFLAGS? = -fPIC -Wall -O2 \
? ? ? ? ? -DHAVE_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(HOST_OS) \
? ? ? ? ? -I$(GLFS_SRC) -I$(GLFS_SRC)/libglusterfs/src \
? ? ? ? ? -I$(GLFS_SRC)/contrib/uuid -I.
LDFLAGS = -shared -nostartfiles -L$(GLFS_LIB) -lglusterfs -lpthread
$(TARGET): $(OBJECTS)
? ? ? ? $(CC) $(CFLAGS) $(OBJECTS) $(LDFLAGS) -o $(TARGET)
install: $(TARGET)
? ? ? ? cp $(TARGET) $(GLFS_LIB)/glusterfs/$(GLFS_VERS)/xlator/null
clean:
? ? ? ? rm -f $(TARGET) $(OBJECTS)
將Makefile設置成與自己相匹配的編譯環境,然后直接make即可生成null.so動態庫,make install安裝null新xlator。至此,一個新xlator就構造成功了,之后我們就可以使用它了。
6. 測試新Xlator
最激動人心的時刻終于到來了,現在我們可以通過修改volume配置文件來添加并測試新構造的null xlator。這個xlator可以工作在客戶端或服務器端,可以修改相應卷配置文件或fuse卷配置文件來實現。下面以服務器端加載為例,局部卷配置修改如下:
volume test-posix
? ? type storage/posix
? ? option directory /data/test-1
end-volume
volume test-null
? ? type null/null
? ? subvolumes test-posix
end-volume
volume test-access-control
? ? type features/access-control
? ? subvolumes test-null
end-volume
… …
OK,現在重啟glusterd服務,然后mount這個卷,就可以測試null xlator功能了。當然,你可能什么功能都測試不出來,因為我們什么功能都沒實現。
轉載于:https://www.cnblogs.com/langren1992/p/5316309.html
總結
以上是生活随笔為你收集整理的设计新Xlator扩展GlusterFS[转]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统-命令解释程序(实验一)
- 下一篇: 【自译】八步成为数据科学家